mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-31 00:42:50 -05:00
Compare commits
3 Commits
651672afe2
...
37f972d075
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37f972d075 | ||
|
|
7d8de6e6f0 | ||
|
|
7ff751f8a2 |
@@ -233,6 +233,9 @@ func (a *SecretAgent) GetSecrets(
|
||||
if a.manager != nil && connType == "802-11-wireless" && a.manager.WasRecentlyFailed(ssid) {
|
||||
reason = "wrong-password"
|
||||
}
|
||||
if settingName == "vpn" && isPKCS11Auth(conn, vpnSvc) {
|
||||
reason = "pkcs11"
|
||||
}
|
||||
|
||||
var connId, connUuid string
|
||||
if c, ok := conn["connection"]; ok {
|
||||
@@ -579,6 +582,15 @@ func inferVPNFields(conn map[string]nmVariantMap, vpnService string) []string {
|
||||
connType := dataMap["connection-type"]
|
||||
|
||||
switch {
|
||||
case strings.Contains(vpnService, "openconnect"):
|
||||
authType := dataMap["authtype"]
|
||||
userCert := dataMap["usercert"]
|
||||
if authType == "cert" && strings.HasPrefix(userCert, "pkcs11:") {
|
||||
return []string{"key_pass"}
|
||||
}
|
||||
if dataMap["username"] == "" {
|
||||
fields = []string{"username", "password"}
|
||||
}
|
||||
case strings.Contains(vpnService, "openvpn"):
|
||||
if connType == "password" || connType == "password-tls" {
|
||||
if dataMap["username"] == "" {
|
||||
@@ -586,7 +598,7 @@ func inferVPNFields(conn map[string]nmVariantMap, vpnService string) []string {
|
||||
}
|
||||
}
|
||||
case strings.Contains(vpnService, "vpnc"), strings.Contains(vpnService, "l2tp"),
|
||||
strings.Contains(vpnService, "pptp"), strings.Contains(vpnService, "openconnect"):
|
||||
strings.Contains(vpnService, "pptp"):
|
||||
if dataMap["username"] == "" {
|
||||
fields = []string{"username", "password"}
|
||||
}
|
||||
@@ -597,6 +609,8 @@ func inferVPNFields(conn map[string]nmVariantMap, vpnService string) []string {
|
||||
|
||||
func vpnFieldMeta(field, vpnService string) (label string, isSecret bool) {
|
||||
switch field {
|
||||
case "key_pass":
|
||||
return "PIN", true
|
||||
case "password":
|
||||
return "Password", true
|
||||
case "Xauth password":
|
||||
@@ -624,6 +638,25 @@ func vpnFieldMeta(field, vpnService string) (label string, isSecret bool) {
|
||||
return titleCaser.String(strings.ReplaceAll(field, "-", " ")), false
|
||||
}
|
||||
|
||||
func isPKCS11Auth(conn map[string]nmVariantMap, vpnService string) bool {
|
||||
if !strings.Contains(vpnService, "openconnect") {
|
||||
return false
|
||||
}
|
||||
vpnSettings, ok := conn["vpn"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
dataVariant, ok := vpnSettings["data"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
dataMap, ok := dataVariant.Value().(map[string]string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return dataMap["authtype"] == "cert" && strings.HasPrefix(dataMap["usercert"], "pkcs11:")
|
||||
}
|
||||
|
||||
func readVPNPasswordFlags(conn map[string]nmVariantMap, settingName string) uint32 {
|
||||
if settingName != "vpn" {
|
||||
return 0xFFFF
|
||||
|
||||
@@ -282,26 +282,73 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
|
||||
}
|
||||
}
|
||||
|
||||
needsUsernamePrePrompt := false
|
||||
var vpnServiceType string
|
||||
var vpnData map[string]string
|
||||
if vpnSettings, ok := targetSettings["vpn"]; ok {
|
||||
if svc, ok := vpnSettings["service-type"].(string); ok {
|
||||
vpnServiceType = svc
|
||||
}
|
||||
if data, ok := vpnSettings["data"].(map[string]string); ok {
|
||||
connType := data["connection-type"]
|
||||
username := data["username"]
|
||||
// OpenVPN password auth needs username in vpn.data
|
||||
if strings.Contains(vpnServiceType, "openvpn") &&
|
||||
(connType == "password" || connType == "password-tls") &&
|
||||
username == "" {
|
||||
needsUsernamePrePrompt = true
|
||||
}
|
||||
vpnData = data
|
||||
}
|
||||
}
|
||||
|
||||
// If username is needed but missing, prompt for it before activating
|
||||
if needsUsernamePrePrompt && b.promptBroker != nil {
|
||||
authAction := detectVPNAuthAction(vpnServiceType, vpnData)
|
||||
|
||||
switch authAction {
|
||||
case "openvpn_username":
|
||||
if b.promptBroker == nil {
|
||||
return fmt.Errorf("OpenVPN password authentication requires interactive prompt")
|
||||
}
|
||||
if err := b.handleOpenVPNUsernameAuth(targetConn, connName, targetUUID, vpnServiceType); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
b.stateMutex.Lock()
|
||||
b.state.IsConnectingVPN = true
|
||||
b.state.ConnectingVPNUUID = targetUUID
|
||||
b.stateMutex.Unlock()
|
||||
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
|
||||
nm := b.nmConn.(gonetworkmanager.NetworkManager)
|
||||
_, err = nm.ActivateConnection(targetConn, nil, nil)
|
||||
if err != nil {
|
||||
b.stateMutex.Lock()
|
||||
b.state.IsConnectingVPN = false
|
||||
b.state.ConnectingVPNUUID = ""
|
||||
b.stateMutex.Unlock()
|
||||
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to activate VPN: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func detectVPNAuthAction(serviceType string, data map[string]string) string {
|
||||
if data == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(serviceType, "openvpn"):
|
||||
connType := data["connection-type"]
|
||||
username := data["username"]
|
||||
if (connType == "password" || connType == "password-tls") && username == "" {
|
||||
return "openvpn_username"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleOpenVPNUsernameAuth(targetConn gonetworkmanager.Connection, connName, targetUUID, vpnServiceType string) error {
|
||||
log.Infof("[ConnectVPN] OpenVPN requires username in vpn.data - prompting before activation")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
@@ -328,9 +375,16 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
|
||||
return fmt.Errorf("credentials prompt failed: %w", err)
|
||||
}
|
||||
|
||||
if reply.Cancel {
|
||||
return fmt.Errorf("user cancelled authentication")
|
||||
}
|
||||
|
||||
username := reply.Secrets["username"]
|
||||
password := reply.Secrets["password"]
|
||||
if username != "" {
|
||||
if username == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
connObj := b.dbusConn.Object("org.freedesktop.NetworkManager", targetConn.GetPath())
|
||||
var existingSettings map[string]map[string]dbus.Variant
|
||||
if err := connObj.Call("org.freedesktop.NetworkManager.Settings.Connection.GetSettings", 0).Store(&existingSettings); err != nil {
|
||||
@@ -375,7 +429,7 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
|
||||
settings, uint32(0x1), map[string]dbus.Variant{}).Store(&result); err != nil {
|
||||
return fmt.Errorf("failed to save username: %w", err)
|
||||
}
|
||||
log.Infof("[ConnectVPN] Username saved to connection, now activating")
|
||||
log.Infof("[ConnectVPN] Username saved to connection")
|
||||
|
||||
if password != "" && !reply.Save {
|
||||
b.cachedVPNCredsMu.Lock()
|
||||
@@ -387,32 +441,6 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
|
||||
b.cachedVPNCredsMu.Unlock()
|
||||
log.Infof("[ConnectVPN] Cached password for GetSecrets")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.stateMutex.Lock()
|
||||
b.state.IsConnectingVPN = true
|
||||
b.state.ConnectingVPNUUID = targetUUID
|
||||
b.stateMutex.Unlock()
|
||||
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
|
||||
nm := b.nmConn.(gonetworkmanager.NetworkManager)
|
||||
_, err = nm.ActivateConnection(targetConn, nil, nil)
|
||||
if err != nil {
|
||||
b.stateMutex.Lock()
|
||||
b.state.IsConnectingVPN = false
|
||||
b.state.ConnectingVPNUUID = ""
|
||||
b.stateMutex.Unlock()
|
||||
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to activate VPN: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ FloatingWindow {
|
||||
property string passwordInput: ""
|
||||
property var currentFlow: PolkitService.agent?.flow
|
||||
property bool isLoading: false
|
||||
readonly property int inputFieldHeight: Theme.fontSizeMedium + Theme.spacingL * 2
|
||||
property int calculatedHeight: Math.max(240, headerRow.implicitHeight + mainColumn.implicitHeight + Theme.spacingM * 3)
|
||||
|
||||
function focusPasswordField() {
|
||||
@@ -202,7 +203,7 @@ FloatingWindow {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: passwordField.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
|
||||
@@ -28,14 +28,29 @@ FloatingWindow {
|
||||
property var fieldsInfo: []
|
||||
property var secretValues: ({})
|
||||
|
||||
readonly property bool showUsernameField: requiresEnterprise && !isVpnPrompt && fieldsInfo.length === 0
|
||||
readonly property bool showPasswordField: fieldsInfo.length === 0
|
||||
readonly property bool showAnonField: requiresEnterprise && !isVpnPrompt
|
||||
readonly property bool showDomainField: requiresEnterprise && !isVpnPrompt
|
||||
readonly property bool showShowPasswordCheckbox: fieldsInfo.length === 0
|
||||
readonly property bool showSavePasswordCheckbox: (isVpnPrompt || fieldsInfo.length > 0) && promptReason !== "pkcs11"
|
||||
|
||||
readonly property int inputFieldHeight: Theme.fontSizeMedium + Theme.spacingL * 2
|
||||
readonly property int inputFieldWithSpacing: inputFieldHeight + Theme.spacingM
|
||||
readonly property int checkboxRowHeight: Theme.fontSizeMedium + Theme.spacingS
|
||||
readonly property int headerHeight: Theme.fontSizeLarge + Theme.fontSizeMedium + Theme.spacingM * 2
|
||||
readonly property int buttonRowHeight: 36 + Theme.spacingM
|
||||
|
||||
property int calculatedHeight: {
|
||||
if (fieldsInfo.length > 0)
|
||||
return 180 + (fieldsInfo.length * 60);
|
||||
if (requiresEnterprise)
|
||||
return 430;
|
||||
if (isVpnPrompt)
|
||||
return 260;
|
||||
return 230;
|
||||
let h = headerHeight + buttonRowHeight + Theme.spacingL * 2;
|
||||
h += fieldsInfo.length * inputFieldWithSpacing;
|
||||
if (showUsernameField) h += inputFieldWithSpacing;
|
||||
if (showPasswordField) h += inputFieldWithSpacing;
|
||||
if (showAnonField) h += inputFieldWithSpacing;
|
||||
if (showDomainField) h += inputFieldWithSpacing;
|
||||
if (showShowPasswordCheckbox) h += checkboxRowHeight;
|
||||
if (showSavePasswordCheckbox) h += checkboxRowHeight;
|
||||
return h;
|
||||
}
|
||||
|
||||
function focusFirstField() {
|
||||
@@ -127,6 +142,7 @@ FloatingWindow {
|
||||
case "private-key-password":
|
||||
return I18n.tr("Private Key Password");
|
||||
case "pin":
|
||||
case "key_pass":
|
||||
return I18n.tr("PIN");
|
||||
case "psk":
|
||||
return I18n.tr("Password");
|
||||
@@ -188,7 +204,13 @@ FloatingWindow {
|
||||
}
|
||||
|
||||
objectName: "wifiPasswordModal"
|
||||
title: isVpnPrompt ? I18n.tr("VPN Password") : I18n.tr("Wi-Fi Password")
|
||||
title: {
|
||||
if (promptReason === "pkcs11")
|
||||
return I18n.tr("Smartcard PIN");
|
||||
if (isVpnPrompt)
|
||||
return I18n.tr("VPN Password");
|
||||
return I18n.tr("Wi-Fi Password");
|
||||
}
|
||||
minimumSize: Qt.size(420, calculatedHeight)
|
||||
maximumSize: Qt.size(420, calculatedHeight)
|
||||
color: Theme.surfaceContainer
|
||||
@@ -242,7 +264,7 @@ FloatingWindow {
|
||||
Column {
|
||||
id: contentCol
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
width: parent.width - Theme.spacingL * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
@@ -260,7 +282,13 @@ FloatingWindow {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: isVpnPrompt ? I18n.tr("Connect to VPN") : I18n.tr("Connect to Wi-Fi")
|
||||
text: {
|
||||
if (promptReason === "pkcs11")
|
||||
return I18n.tr("Smartcard Authentication");
|
||||
if (isVpnPrompt)
|
||||
return I18n.tr("Connect to VPN");
|
||||
return I18n.tr("Connect to Wi-Fi");
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
@@ -272,6 +300,8 @@ FloatingWindow {
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (promptReason === "pkcs11")
|
||||
return I18n.tr("Enter PIN for ") + wifiPasswordSSID;
|
||||
if (fieldsInfo.length > 0)
|
||||
return I18n.tr("Enter credentials for ") + wifiPasswordSSID;
|
||||
if (isVpnPrompt)
|
||||
@@ -325,7 +355,7 @@ FloatingWindow {
|
||||
required property int index
|
||||
|
||||
width: contentCol.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: fieldInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
@@ -388,12 +418,12 @@ FloatingWindow {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: usernameInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
border.width: usernameInput.activeFocus ? 2 : 1
|
||||
visible: requiresEnterprise && !isVpnPrompt && fieldsInfo.length === 0
|
||||
visible: showUsernameField
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@@ -419,12 +449,12 @@ FloatingWindow {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: passwordInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
border.width: passwordInput.activeFocus ? 2 : 1
|
||||
visible: fieldsInfo.length === 0
|
||||
visible: showPasswordField
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@@ -456,9 +486,9 @@ FloatingWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: requiresEnterprise && !isVpnPrompt
|
||||
visible: showAnonField
|
||||
width: parent.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: anonInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
@@ -487,9 +517,9 @@ FloatingWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: requiresEnterprise && !isVpnPrompt
|
||||
visible: showDomainField
|
||||
width: parent.width
|
||||
height: 50
|
||||
height: inputFieldHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: domainMatchInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
@@ -523,7 +553,7 @@ FloatingWindow {
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
visible: fieldsInfo.length === 0
|
||||
visible: showShowPasswordCheckbox
|
||||
|
||||
Rectangle {
|
||||
id: showPasswordCheckbox
|
||||
@@ -563,7 +593,7 @@ FloatingWindow {
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
visible: isVpnPrompt || fieldsInfo.length > 0
|
||||
visible: showSavePasswordCheckbox
|
||||
|
||||
Rectangle {
|
||||
id: savePasswordCheckbox
|
||||
|
||||
@@ -186,7 +186,7 @@ exec = sh -c "$QS_CMD; hyprctl dispatch exit"
|
||||
HYPRLAND_EOF
|
||||
COMPOSITOR_CONFIG="$TEMP_CONFIG"
|
||||
fi
|
||||
CURRENT_VERSION=$(hyprctl version | grep "Tag:" | awk '{print $2}' | tr -d 'v,')
|
||||
CURRENT_VERSION=$(hyprland --version | grep "Tag:" | awk '{print $2}' | tr -d 'v,')
|
||||
MINIMUM_VERSION="0.53.0"
|
||||
if [ "$(printf '%s\n%s' "$MINIMUM_VERSION" "$CURRENT_VERSION" | sort -V | head -n1)" = "$MINIMUM_VERSION" ]; then
|
||||
exec start-hyprland -- --config "$COMPOSITOR_CONFIG"
|
||||
|
||||
@@ -4,7 +4,7 @@ export XDG_SESSION_TYPE=wayland
|
||||
export QT_QPA_PLATFORM=wayland
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
|
||||
export EGL_PLATFORM=gbm
|
||||
CURRENT_VERSION=$(hyprctl version | grep "Tag:" | awk '{print $2}' | tr -d 'v,')
|
||||
CURRENT_VERSION=$(hyprland --version | grep "Tag:" | awk '{print $2}' | tr -d 'v,')
|
||||
|
||||
MINIMUM_VERSION="0.53.0"
|
||||
|
||||
|
||||
@@ -6677,6 +6677,18 @@
|
||||
"reference": "Modules/Settings/DockTab.qml:144",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Smartcard Authentication",
|
||||
"context": "Smartcard Authentication",
|
||||
"reference": "Modals/WifiPasswordModal.qml:272",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Smartcard PIN",
|
||||
"context": "Smartcard PIN",
|
||||
"reference": "Modals/WifiPasswordModal.qml:194",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Some plugins require a newer version of DMS:",
|
||||
"context": "Some plugins require a newer version of DMS:",
|
||||
|
||||
Reference in New Issue
Block a user