diff --git a/core/internal/server/network/agent_networkmanager.go b/core/internal/server/network/agent_networkmanager.go index 55c7f207..abe25a46 100644 --- a/core/internal/server/network/agent_networkmanager.go +++ b/core/internal/server/network/agent_networkmanager.go @@ -252,6 +252,28 @@ func (a *SecretAgent) GetSecrets( } if settingName == "vpn" && a.backend != nil { + // Check for cached PKCS11 PIN first + isPKCS11Request := len(fields) == 1 && fields[0] == "key_pass" + if isPKCS11Request { + a.backend.cachedPKCS11Mu.Lock() + cached := a.backend.cachedPKCS11PIN + if cached != nil && cached.ConnectionUUID == connUuid { + a.backend.cachedPKCS11PIN = nil + a.backend.cachedPKCS11Mu.Unlock() + + log.Infof("[SecretAgent] Using cached PKCS11 PIN") + + out := nmSettingMap{} + vpnSec := nmVariantMap{} + vpnSec["secrets"] = dbus.MakeVariant(map[string]string{"key_pass": cached.PIN}) + out[settingName] = vpnSec + + return out, nil + } + a.backend.cachedPKCS11Mu.Unlock() + } + + // Check for cached VPN password a.backend.cachedVPNCredsMu.Lock() cached := a.backend.cachedVPNCreds if cached != nil && cached.ConnectionUUID == connUuid { @@ -261,9 +283,9 @@ func (a *SecretAgent) GetSecrets( log.Infof("[SecretAgent] Using cached password from pre-activation prompt") out := nmSettingMap{} - sec := nmVariantMap{} - sec["password"] = dbus.MakeVariant(cached.Password) - out[settingName] = sec + vpnSec := nmVariantMap{} + vpnSec["secrets"] = dbus.MakeVariant(map[string]string{"password": cached.Password}) + out[settingName] = vpnSec if cached.SavePassword { a.backend.pendingVPNSaveMu.Lock() @@ -367,16 +389,41 @@ func (a *SecretAgent) GetSecrets( } sec[k] = dbus.MakeVariant(v) } - out[settingName] = sec + + // Check if this is PKCS11 auth (key_pass) + pin, isPKCS11 := reply.Secrets["key_pass"] switch settingName { - case "802-1x": - log.Infof("[SecretAgent] Returning 802-1x enterprise secrets with %d fields", len(sec)) case "vpn": - log.Infof("[SecretAgent] Returning VPN secrets with %d fields for %s", len(sec), vpnSvc) - } + // VPN secrets must be wrapped in a "secrets" key per NM spec + secretsDict := make(map[string]string) + for k, v := range reply.Secrets { + if k != "username" { + secretsDict[k] = v + } + } + vpnSec := nmVariantMap{} + vpnSec["secrets"] = dbus.MakeVariant(secretsDict) + out[settingName] = vpnSec + log.Infof("[SecretAgent] Returning VPN secrets with %d fields for %s", len(secretsDict), vpnSvc) - if settingName == "vpn" && a.backend != nil && (vpnUsername != "" || reply.Save) { + // Cache PKCS11 PIN in case GetSecrets is called again during activation + if isPKCS11 && a.backend != nil { + a.backend.cachedPKCS11Mu.Lock() + a.backend.cachedPKCS11PIN = &cachedPKCS11PIN{ + ConnectionUUID: connUuid, + PIN: pin, + } + a.backend.cachedPKCS11Mu.Unlock() + log.Infof("[SecretAgent] Cached PKCS11 PIN for potential re-request") + } + case "802-1x": + out[settingName] = sec + log.Infof("[SecretAgent] Returning 802-1x enterprise secrets with %d fields", len(sec)) + default: + out[settingName] = sec + } + if settingName == "vpn" && a.backend != nil && !isPKCS11 && (vpnUsername != "" || reply.Save) { pw := reply.Secrets["password"] a.backend.pendingVPNSaveMu.Lock() a.backend.pendingVPNSave = &pendingVPNCredentials{ diff --git a/core/internal/server/network/backend_networkmanager.go b/core/internal/server/network/backend_networkmanager.go index f1a4af1a..588f76f8 100644 --- a/core/internal/server/network/backend_networkmanager.go +++ b/core/internal/server/network/backend_networkmanager.go @@ -72,6 +72,8 @@ type NetworkManagerBackend struct { pendingVPNSaveMu sync.Mutex cachedVPNCreds *cachedVPNCredentials cachedVPNCredsMu sync.Mutex + cachedPKCS11PIN *cachedPKCS11PIN + cachedPKCS11Mu sync.Mutex onStateChange func() } @@ -89,6 +91,11 @@ type cachedVPNCredentials struct { SavePassword bool } +type cachedPKCS11PIN struct { + ConnectionUUID string + PIN string +} + func NewNetworkManagerBackend(nmConn ...gonetworkmanager.NetworkManager) (*NetworkManagerBackend, error) { var nm gonetworkmanager.NetworkManager var err error diff --git a/core/internal/server/network/backend_networkmanager_vpn.go b/core/internal/server/network/backend_networkmanager_vpn.go index fd39b58f..c1c3266e 100644 --- a/core/internal/server/network/backend_networkmanager_vpn.go +++ b/core/internal/server/network/backend_networkmanager_vpn.go @@ -683,6 +683,11 @@ func (b *NetworkManagerBackend) updateVPNConnectionState() { b.state.LastError = "" b.stateMutex.Unlock() + // Clear cached PKCS11 PIN on success + b.cachedPKCS11Mu.Lock() + b.cachedPKCS11PIN = nil + b.cachedPKCS11Mu.Unlock() + b.pendingVPNSaveMu.Lock() pending := b.pendingVPNSave b.pendingVPNSave = nil @@ -699,6 +704,11 @@ func (b *NetworkManagerBackend) updateVPNConnectionState() { b.state.ConnectingVPNUUID = "" b.state.LastError = "VPN connection failed" b.stateMutex.Unlock() + + // Clear cached PKCS11 PIN on failure + b.cachedPKCS11Mu.Lock() + b.cachedPKCS11PIN = nil + b.cachedPKCS11Mu.Unlock() return } } @@ -711,6 +721,11 @@ func (b *NetworkManagerBackend) updateVPNConnectionState() { b.state.ConnectingVPNUUID = "" b.state.LastError = "VPN connection failed" b.stateMutex.Unlock() + + // Clear cached PKCS11 PIN + b.cachedPKCS11Mu.Lock() + b.cachedPKCS11PIN = nil + b.cachedPKCS11Mu.Unlock() } }