mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-13 00:42:49 -05:00
switch hto monorepo structure
This commit is contained in:
528
backend/internal/server/network/agent_networkmanager.go
Normal file
528
backend/internal/server/network/agent_networkmanager.go
Normal file
@@ -0,0 +1,528 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/backend/internal/errdefs"
|
||||
"github.com/AvengeMedia/DankMaterialShell/backend/internal/log"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
nmAgentManagerPath = "/org/freedesktop/NetworkManager/AgentManager"
|
||||
nmAgentManagerIface = "org.freedesktop.NetworkManager.AgentManager"
|
||||
nmSecretAgentIface = "org.freedesktop.NetworkManager.SecretAgent"
|
||||
agentObjectPath = "/org/freedesktop/NetworkManager/SecretAgent"
|
||||
agentIdentifier = "com.danklinux.NMAgent"
|
||||
)
|
||||
|
||||
type SecretAgent struct {
|
||||
conn *dbus.Conn
|
||||
objPath dbus.ObjectPath
|
||||
id string
|
||||
prompts PromptBroker
|
||||
manager *Manager
|
||||
backend *NetworkManagerBackend
|
||||
}
|
||||
|
||||
type nmVariantMap map[string]dbus.Variant
|
||||
type nmSettingMap map[string]nmVariantMap
|
||||
|
||||
const introspectXML = `
|
||||
<node>
|
||||
<interface name="org.freedesktop.NetworkManager.SecretAgent">
|
||||
<method name="GetSecrets">
|
||||
<arg type="a{sa{sv}}" name="connection" direction="in"/>
|
||||
<arg type="o" name="connection_path" direction="in"/>
|
||||
<arg type="s" name="setting_name" direction="in"/>
|
||||
<arg type="as" name="hints" direction="in"/>
|
||||
<arg type="u" name="flags" direction="in"/>
|
||||
<arg type="a{sa{sv}}" name="secrets" direction="out"/>
|
||||
</method>
|
||||
<method name="DeleteSecrets">
|
||||
<arg type="a{sa{sv}}" name="connection" direction="in"/>
|
||||
<arg type="o" name="connection_path" direction="in"/>
|
||||
</method>
|
||||
<method name="DeleteSecrets2">
|
||||
<arg type="o" name="connection_path" direction="in"/>
|
||||
<arg type="s" name="setting" direction="in"/>
|
||||
</method>
|
||||
<method name="CancelGetSecrets">
|
||||
<arg type="o" name="connection_path" direction="in"/>
|
||||
<arg type="s" name="setting_name" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="org.freedesktop.DBus.Introspectable">
|
||||
<method name="Introspect">
|
||||
<arg name="data" type="s" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>`
|
||||
|
||||
func NewSecretAgent(prompts PromptBroker, manager *Manager, backend *NetworkManagerBackend) (*SecretAgent, error) {
|
||||
c, err := dbus.ConnectSystemBus()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to system bus: %w", err)
|
||||
}
|
||||
|
||||
sa := &SecretAgent{
|
||||
conn: c,
|
||||
objPath: dbus.ObjectPath(agentObjectPath),
|
||||
id: agentIdentifier,
|
||||
prompts: prompts,
|
||||
manager: manager,
|
||||
backend: backend,
|
||||
}
|
||||
|
||||
if err := c.Export(sa, sa.objPath, nmSecretAgentIface); err != nil {
|
||||
c.Close()
|
||||
return nil, fmt.Errorf("failed to export secret agent: %w", err)
|
||||
}
|
||||
|
||||
if err := c.Export(sa, sa.objPath, "org.freedesktop.DBus.Introspectable"); err != nil {
|
||||
c.Close()
|
||||
return nil, fmt.Errorf("failed to export introspection: %w", err)
|
||||
}
|
||||
|
||||
mgr := c.Object("org.freedesktop.NetworkManager", dbus.ObjectPath(nmAgentManagerPath))
|
||||
call := mgr.Call(nmAgentManagerIface+".Register", 0, sa.id)
|
||||
if call.Err != nil {
|
||||
c.Close()
|
||||
return nil, fmt.Errorf("failed to register agent with NetworkManager: %w", call.Err)
|
||||
}
|
||||
|
||||
log.Infof("[SecretAgent] Registered with NetworkManager (id=%s, unique name=%s, fixed path=%s)", sa.id, c.Names()[0], sa.objPath)
|
||||
return sa, nil
|
||||
}
|
||||
|
||||
func (a *SecretAgent) Close() {
|
||||
if a.conn != nil {
|
||||
mgr := a.conn.Object("org.freedesktop.NetworkManager", dbus.ObjectPath(nmAgentManagerPath))
|
||||
mgr.Call(nmAgentManagerIface+".Unregister", 0, a.id)
|
||||
a.conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *SecretAgent) GetSecrets(
|
||||
conn map[string]nmVariantMap,
|
||||
path dbus.ObjectPath,
|
||||
settingName string,
|
||||
hints []string,
|
||||
flags uint32,
|
||||
) (nmSettingMap, *dbus.Error) {
|
||||
log.Infof("[SecretAgent] GetSecrets called: path=%s, setting=%s, hints=%v, flags=%d",
|
||||
path, settingName, hints, flags)
|
||||
|
||||
const (
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4
|
||||
)
|
||||
|
||||
connType, displayName, vpnSvc := readConnTypeAndName(conn)
|
||||
ssid := readSSID(conn)
|
||||
fields := fieldsNeeded(settingName, hints)
|
||||
|
||||
log.Infof("[SecretAgent] connType=%s, name=%s, vpnSvc=%s, fields=%v, flags=%d", connType, displayName, vpnSvc, fields, flags)
|
||||
|
||||
if a.backend != nil {
|
||||
a.backend.stateMutex.RLock()
|
||||
isConnecting := a.backend.state.IsConnecting
|
||||
connectingSSID := a.backend.state.ConnectingSSID
|
||||
isConnectingVPN := a.backend.state.IsConnectingVPN
|
||||
connectingVPNUUID := a.backend.state.ConnectingVPNUUID
|
||||
a.backend.stateMutex.RUnlock()
|
||||
|
||||
switch connType {
|
||||
case "802-11-wireless":
|
||||
// If we're connecting to a WiFi network, only respond if it's the one we're connecting to
|
||||
if isConnecting && connectingSSID != ssid {
|
||||
log.Infof("[SecretAgent] Ignoring WiFi request for SSID '%s' - we're connecting to '%s'", ssid, connectingSSID)
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
|
||||
}
|
||||
case "vpn", "wireguard":
|
||||
var connUuid string
|
||||
if c, ok := conn["connection"]; ok {
|
||||
if v, ok := c["uuid"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
connUuid = s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're connecting to a VPN, only respond if it's the one we're connecting to
|
||||
// This prevents interfering with nmcli/other tools when our app isn't connecting
|
||||
if isConnectingVPN && connUuid != connectingVPNUUID {
|
||||
log.Infof("[SecretAgent] Ignoring VPN request for UUID '%s' - we're connecting to '%s'", connUuid, connectingVPNUUID)
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
// For VPN connections with no hints, we can't provide a proper UI.
|
||||
// Defer to other agents (like nm-applet or VPN-specific auth dialogs)
|
||||
// that can handle the VPN type properly (e.g., OpenConnect with SAML, etc.)
|
||||
if settingName == "vpn" {
|
||||
log.Infof("[SecretAgent] VPN with empty hints - deferring to other agents for %s", vpnSvc)
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
|
||||
}
|
||||
|
||||
const (
|
||||
NM_SETTING_SECRET_FLAG_NONE = 0
|
||||
NM_SETTING_SECRET_FLAG_AGENT_OWNED = 1
|
||||
NM_SETTING_SECRET_FLAG_NOT_SAVED = 2
|
||||
NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 4
|
||||
)
|
||||
|
||||
var passwordFlags uint32 = 0xFFFF
|
||||
switch settingName {
|
||||
case "802-11-wireless-security":
|
||||
if wifiSecSettings, ok := conn["802-11-wireless-security"]; ok {
|
||||
if flagsVariant, ok := wifiSecSettings["psk-flags"]; ok {
|
||||
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
|
||||
passwordFlags = pwdFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
case "802-1x":
|
||||
if dot1xSettings, ok := conn["802-1x"]; ok {
|
||||
if flagsVariant, ok := dot1xSettings["password-flags"]; ok {
|
||||
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
|
||||
passwordFlags = pwdFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if passwordFlags == 0xFFFF {
|
||||
log.Warnf("[SecretAgent] Could not determine password-flags for empty hints - returning NoSecrets error")
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
|
||||
} else if passwordFlags&NM_SETTING_SECRET_FLAG_NOT_REQUIRED != 0 {
|
||||
log.Infof("[SecretAgent] Secrets not required (flags=%d)", passwordFlags)
|
||||
out := nmSettingMap{}
|
||||
out[settingName] = nmVariantMap{}
|
||||
return out, nil
|
||||
} else if passwordFlags&NM_SETTING_SECRET_FLAG_AGENT_OWNED != 0 {
|
||||
log.Warnf("[SecretAgent] Secrets are agent-owned but we don't store secrets (flags=%d) - returning NoSecrets error", passwordFlags)
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
|
||||
} else {
|
||||
log.Infof("[SecretAgent] No secrets needed, using system stored secrets (flags=%d)", passwordFlags)
|
||||
out := nmSettingMap{}
|
||||
out[settingName] = nmVariantMap{}
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
|
||||
reason := reasonFromFlags(flags)
|
||||
if a.manager != nil && connType == "802-11-wireless" && a.manager.WasRecentlyFailed(ssid) {
|
||||
reason = "wrong-password"
|
||||
}
|
||||
|
||||
var connId, connUuid string
|
||||
if c, ok := conn["connection"]; ok {
|
||||
if v, ok := c["id"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
connId = s
|
||||
}
|
||||
}
|
||||
if v, ok := c["uuid"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
connUuid = s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
token, err := a.prompts.Ask(ctx, PromptRequest{
|
||||
Name: displayName,
|
||||
SSID: ssid,
|
||||
ConnType: connType,
|
||||
VpnService: vpnSvc,
|
||||
SettingName: settingName,
|
||||
Fields: fields,
|
||||
Hints: hints,
|
||||
Reason: reason,
|
||||
ConnectionId: connId,
|
||||
ConnectionUuid: connUuid,
|
||||
ConnectionPath: string(path),
|
||||
})
|
||||
if err != nil {
|
||||
log.Warnf("[SecretAgent] Failed to create prompt: %v", err)
|
||||
return nil, dbus.MakeFailedError(err)
|
||||
}
|
||||
|
||||
log.Infof("[SecretAgent] Waiting for user input (token=%s)", token)
|
||||
reply, err := a.prompts.Wait(ctx, token)
|
||||
if err != nil {
|
||||
log.Warnf("[SecretAgent] Prompt failed or cancelled: %v", err)
|
||||
|
||||
// Clear connecting state immediately on cancellation
|
||||
if a.backend != nil {
|
||||
a.backend.stateMutex.Lock()
|
||||
wasConnecting := a.backend.state.IsConnecting
|
||||
wasConnectingVPN := a.backend.state.IsConnectingVPN
|
||||
cancelledSSID := a.backend.state.ConnectingSSID
|
||||
if wasConnecting || wasConnectingVPN {
|
||||
log.Infof("[SecretAgent] Clearing connecting state due to cancelled prompt")
|
||||
a.backend.state.IsConnecting = false
|
||||
a.backend.state.ConnectingSSID = ""
|
||||
a.backend.state.IsConnectingVPN = false
|
||||
a.backend.state.ConnectingVPNUUID = ""
|
||||
}
|
||||
a.backend.stateMutex.Unlock()
|
||||
|
||||
// If this was a WiFi connection that was just cancelled, remove the connection profile
|
||||
// (it was created with AddConnection but activation was cancelled)
|
||||
if wasConnecting && cancelledSSID != "" && connType == "802-11-wireless" {
|
||||
log.Infof("[SecretAgent] Removing connection profile for cancelled WiFi connection: %s", cancelledSSID)
|
||||
if err := a.backend.ForgetWiFiNetwork(cancelledSSID); err != nil {
|
||||
log.Warnf("[SecretAgent] Failed to remove cancelled connection profile: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if (wasConnecting || wasConnectingVPN) && a.backend.onStateChange != nil {
|
||||
a.backend.onStateChange()
|
||||
}
|
||||
}
|
||||
|
||||
if reply.Cancel || errors.Is(err, errdefs.ErrSecretPromptCancelled) {
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.UserCanceled", nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, errdefs.ErrSecretPromptTimeout) {
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.Failed", nil)
|
||||
}
|
||||
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.Failed", nil)
|
||||
}
|
||||
|
||||
log.Infof("[SecretAgent] User provided secrets, save=%v", reply.Save)
|
||||
|
||||
out := nmSettingMap{}
|
||||
sec := nmVariantMap{}
|
||||
for k, v := range reply.Secrets {
|
||||
sec[k] = dbus.MakeVariant(v)
|
||||
}
|
||||
out[settingName] = sec
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// If save=true, persist secrets in background after returning to NetworkManager
|
||||
// This MUST happen after we return secrets, in a goroutine
|
||||
if reply.Save {
|
||||
go func() {
|
||||
log.Infof("[SecretAgent] Persisting secrets with Update2: path=%s, setting=%s", path, settingName)
|
||||
|
||||
// Get existing connection settings
|
||||
connObj := a.conn.Object("org.freedesktop.NetworkManager", path)
|
||||
var existingSettings map[string]map[string]dbus.Variant
|
||||
if err := connObj.Call("org.freedesktop.NetworkManager.Settings.Connection.GetSettings", 0).Store(&existingSettings); err != nil {
|
||||
log.Warnf("[SecretAgent] GetSettings failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Build minimal settings with ONLY the section we're updating
|
||||
// This avoids D-Bus type serialization issues with complex types like IPv6 addresses
|
||||
settings := make(map[string]map[string]dbus.Variant)
|
||||
|
||||
// Copy connection section (required for Update2)
|
||||
if connSection, ok := existingSettings["connection"]; ok {
|
||||
settings["connection"] = connSection
|
||||
}
|
||||
|
||||
// Update settings based on type
|
||||
switch settingName {
|
||||
case "vpn":
|
||||
// Set password-flags=0 and add secrets to vpn section
|
||||
vpn, ok := existingSettings["vpn"]
|
||||
if !ok {
|
||||
vpn = make(map[string]dbus.Variant)
|
||||
}
|
||||
|
||||
// Get existing data map (vpn.data is string->string)
|
||||
var data map[string]string
|
||||
if dataVariant, ok := vpn["data"]; ok {
|
||||
if dm, ok := dataVariant.Value().(map[string]string); ok {
|
||||
data = make(map[string]string)
|
||||
for k, v := range dm {
|
||||
data[k] = v
|
||||
}
|
||||
} else {
|
||||
data = make(map[string]string)
|
||||
}
|
||||
} else {
|
||||
data = make(map[string]string)
|
||||
}
|
||||
|
||||
// Update password-flags to 0 (system-stored)
|
||||
data["password-flags"] = "0"
|
||||
vpn["data"] = dbus.MakeVariant(data)
|
||||
|
||||
// Add secrets (vpn.secrets is string->string)
|
||||
secs := make(map[string]string)
|
||||
for k, v := range reply.Secrets {
|
||||
secs[k] = v
|
||||
}
|
||||
vpn["secrets"] = dbus.MakeVariant(secs)
|
||||
settings["vpn"] = vpn
|
||||
|
||||
log.Infof("[SecretAgent] Updated VPN settings: password-flags=0, secrets with %d fields", len(secs))
|
||||
|
||||
case "802-11-wireless-security":
|
||||
// Set psk-flags=0 for WiFi
|
||||
wifiSec, ok := existingSettings["802-11-wireless-security"]
|
||||
if !ok {
|
||||
wifiSec = make(map[string]dbus.Variant)
|
||||
}
|
||||
wifiSec["psk-flags"] = dbus.MakeVariant(uint32(0))
|
||||
|
||||
// Add PSK secret
|
||||
if psk, ok := reply.Secrets["psk"]; ok {
|
||||
wifiSec["psk"] = dbus.MakeVariant(psk)
|
||||
log.Infof("[SecretAgent] Updated WiFi settings: psk-flags=0")
|
||||
}
|
||||
settings["802-11-wireless-security"] = wifiSec
|
||||
|
||||
case "802-1x":
|
||||
// Set password-flags=0 for 802.1x
|
||||
dot1x, ok := existingSettings["802-1x"]
|
||||
if !ok {
|
||||
dot1x = make(map[string]dbus.Variant)
|
||||
}
|
||||
dot1x["password-flags"] = dbus.MakeVariant(uint32(0))
|
||||
|
||||
// Add password secret
|
||||
if password, ok := reply.Secrets["password"]; ok {
|
||||
dot1x["password"] = dbus.MakeVariant(password)
|
||||
log.Infof("[SecretAgent] Updated 802.1x settings: password-flags=0")
|
||||
}
|
||||
settings["802-1x"] = dot1x
|
||||
}
|
||||
|
||||
// Call Update2 with correct signature:
|
||||
// Update2(IN settings, IN flags, IN args) -> OUT result
|
||||
// flags: 0x1 = to-disk
|
||||
var result map[string]dbus.Variant
|
||||
err := connObj.Call("org.freedesktop.NetworkManager.Settings.Connection.Update2", 0,
|
||||
settings, uint32(0x1), map[string]dbus.Variant{}).Store(&result)
|
||||
if err != nil {
|
||||
log.Warnf("[SecretAgent] Update2(to-disk) failed: %v", err)
|
||||
} else {
|
||||
log.Infof("[SecretAgent] Successfully persisted secrets to disk for %s", settingName)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (a *SecretAgent) DeleteSecrets(conn map[string]nmVariantMap, path dbus.ObjectPath) *dbus.Error {
|
||||
ssid := readSSID(conn)
|
||||
log.Infof("[SecretAgent] DeleteSecrets called: path=%s, SSID=%s", path, ssid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *SecretAgent) DeleteSecrets2(path dbus.ObjectPath, setting string) *dbus.Error {
|
||||
log.Infof("[SecretAgent] DeleteSecrets2 (alternate) called: path=%s, setting=%s", path, setting)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *SecretAgent) CancelGetSecrets(path dbus.ObjectPath, settingName string) *dbus.Error {
|
||||
log.Infof("[SecretAgent] CancelGetSecrets called: path=%s, setting=%s", path, settingName)
|
||||
|
||||
if a.prompts != nil {
|
||||
if err := a.prompts.Cancel(string(path), settingName); err != nil {
|
||||
log.Warnf("[SecretAgent] Failed to cancel prompt: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *SecretAgent) Introspect() (string, *dbus.Error) {
|
||||
return introspectXML, nil
|
||||
}
|
||||
|
||||
func readSSID(conn map[string]nmVariantMap) string {
|
||||
if w, ok := conn["802-11-wireless"]; ok {
|
||||
if v, ok := w["ssid"]; ok {
|
||||
if b, ok := v.Value().([]byte); ok {
|
||||
return string(b)
|
||||
}
|
||||
if s, ok := v.Value().(string); ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func readConnTypeAndName(conn map[string]nmVariantMap) (string, string, string) {
|
||||
var connType, name, svc string
|
||||
if c, ok := conn["connection"]; ok {
|
||||
if v, ok := c["type"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
connType = s
|
||||
}
|
||||
}
|
||||
if v, ok := c["id"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
name = s
|
||||
}
|
||||
}
|
||||
}
|
||||
if vpn, ok := conn["vpn"]; ok {
|
||||
if v, ok := vpn["service-type"]; ok {
|
||||
if s, ok2 := v.Value().(string); ok2 {
|
||||
svc = s
|
||||
}
|
||||
}
|
||||
}
|
||||
if name == "" && connType == "802-11-wireless" {
|
||||
name = readSSID(conn)
|
||||
}
|
||||
return connType, name, svc
|
||||
}
|
||||
|
||||
func fieldsNeeded(setting string, hints []string) []string {
|
||||
switch setting {
|
||||
case "802-11-wireless-security":
|
||||
return []string{"psk"}
|
||||
case "802-1x":
|
||||
return []string{"identity", "password"}
|
||||
case "vpn":
|
||||
return hints
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
}
|
||||
|
||||
func reasonFromFlags(flags uint32) string {
|
||||
const (
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 0x8
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 0x40000000
|
||||
)
|
||||
|
||||
if flags&NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW != 0 {
|
||||
return "wrong-password"
|
||||
}
|
||||
if flags&NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED != 0 {
|
||||
return "user-requested"
|
||||
}
|
||||
return "required"
|
||||
}
|
||||
Reference in New Issue
Block a user