github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/systemd/dbus.go (about) 1 package systemd 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strconv" 9 10 "github.com/hanks177/podman/v4/pkg/rootless" 11 "github.com/coreos/go-systemd/v22/dbus" 12 godbus "github.com/godbus/dbus/v5" 13 "github.com/sirupsen/logrus" 14 ) 15 16 // IsSystemdSessionValid checks if sessions is valid for provided rootless uid. 17 func IsSystemdSessionValid(uid int) bool { 18 var conn *godbus.Conn 19 var err error 20 var object godbus.BusObject 21 var seat0Path godbus.ObjectPath 22 dbusDest := "org.freedesktop.login1" 23 dbusInterface := "org.freedesktop.login1.Manager" 24 dbusPath := "/org/freedesktop/login1" 25 26 if rootless.IsRootless() { 27 conn, err = GetLogindConnection(rootless.GetRootlessUID()) 28 if err != nil { 29 // unable to fetch systemd object for logind 30 logrus.Debugf("systemd-logind: %s", err) 31 return false 32 } 33 object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath)) 34 if err := object.Call(dbusInterface+".GetSeat", 0, "seat0").Store(&seat0Path); err != nil { 35 // unable to get seat0 path. 36 logrus.Debugf("systemd-logind: %s", err) 37 return false 38 } 39 seat0Obj := conn.Object(dbusDest, seat0Path) 40 activeSession, err := seat0Obj.GetProperty(dbusDest + ".Seat.ActiveSession") 41 if err != nil { 42 // unable to get active sessions. 43 logrus.Debugf("systemd-logind: %s", err) 44 return false 45 } 46 activeSessionMap, ok := activeSession.Value().([]interface{}) 47 if !ok || len(activeSessionMap) < 2 { 48 // unable to get active session map. 49 logrus.Debugf("systemd-logind: %s", err) 50 return false 51 } 52 activeSessionPath, ok := activeSessionMap[1].(godbus.ObjectPath) 53 if !ok { 54 // unable to fetch active session path. 55 logrus.Debugf("systemd-logind: %s", err) 56 return false 57 } 58 activeSessionObj := conn.Object(dbusDest, activeSessionPath) 59 sessionUser, err := activeSessionObj.GetProperty(dbusDest + ".Session.User") 60 if err != nil { 61 // unable to fetch session user from activeSession path. 62 logrus.Debugf("systemd-logind: %s", err) 63 return false 64 } 65 dbusUser, ok := sessionUser.Value().([]interface{}) 66 if !ok { 67 // not a valid user. 68 return false 69 } 70 if len(dbusUser) < 2 { 71 // not a valid session user. 72 return false 73 } 74 activeUID, ok := dbusUser[0].(uint32) 75 if !ok { 76 return false 77 } 78 // active session found which belongs to following rootless user 79 if activeUID == uint32(uid) { 80 return true 81 } 82 return false 83 } 84 return true 85 } 86 87 // GetDbusConnection returns a user connection to D-BUS 88 func GetLogindConnection(uid int) (*godbus.Conn, error) { 89 return dbusAuthConnectionLogind(uid) 90 } 91 92 func dbusAuthConnectionLogind(uid int) (*godbus.Conn, error) { 93 var conn *godbus.Conn 94 var err error 95 conn, err = godbus.SystemBusPrivate() 96 if err != nil { 97 return nil, err 98 } 99 methods := []godbus.Auth{godbus.AuthExternal(strconv.Itoa(uid))} 100 if err = conn.Auth(methods); err != nil { 101 conn.Close() 102 return nil, err 103 } 104 err = conn.Hello() 105 if err != nil { 106 conn.Close() 107 return nil, err 108 } 109 return conn, nil 110 } 111 112 func dbusAuthRootlessConnection(createBus func(opts ...godbus.ConnOption) (*godbus.Conn, error)) (*godbus.Conn, error) { 113 conn, err := createBus() 114 if err != nil { 115 return nil, err 116 } 117 118 methods := []godbus.Auth{godbus.AuthExternal(strconv.Itoa(rootless.GetRootlessUID()))} 119 120 err = conn.Auth(methods) 121 if err != nil { 122 conn.Close() 123 return nil, err 124 } 125 126 return conn, nil 127 } 128 129 func newRootlessConnection() (*dbus.Conn, error) { 130 return dbus.NewConnection(func() (*godbus.Conn, error) { 131 return dbusAuthRootlessConnection(func(opts ...godbus.ConnOption) (*godbus.Conn, error) { 132 path := filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "systemd/private") 133 return godbus.Dial(fmt.Sprintf("unix:path=%s", path)) 134 }) 135 }) 136 } 137 138 // ConnectToDBUS returns a DBUS connection. It works both as root and non-root 139 // users. 140 func ConnectToDBUS() (*dbus.Conn, error) { 141 if rootless.IsRootless() { 142 return newRootlessConnection() 143 } 144 return dbus.NewSystemdConnectionContext(context.Background()) 145 }