The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/8088
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) ===
From f3c4805b2267aa6e8af890499ee8c72673522b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Tue, 27 Oct 2020 18:56:45 -0400 Subject: [PATCH 1/5] shared: Drop GroupId and UserId MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- shared/util_linux_cgo.go | 97 ---------------------------------------- 1 file changed, 97 deletions(-) diff --git a/shared/util_linux_cgo.go b/shared/util_linux_cgo.go index 72d0794953..155975d265 100644 --- a/shared/util_linux_cgo.go +++ b/shared/util_linux_cgo.go @@ -6,7 +6,6 @@ package shared import ( "fmt" "os" - "unsafe" // Used by cgo _ "github.com/lxc/lxd/lxd/include" @@ -58,102 +57,6 @@ import "C" const ABSTRACT_UNIX_SOCK_LEN int = C.ABSTRACT_UNIX_SOCK_LEN -// UserId is an adaption from https://codereview.appspot.com/4589049. -func UserId(name string) (int, error) { - var pw C.struct_passwd - var result *C.struct_passwd - - bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX) - if bufSize < 0 { - bufSize = 4096 - } - - buf := C.malloc(C.size_t(bufSize)) - if buf == nil { - return -1, fmt.Errorf("allocation failed") - } - defer C.free(buf) - - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - -again: - rv, errno := C.getpwnam_r(cname, - &pw, - (*C.char)(buf), - C.size_t(bufSize), - &result) - if rv < 0 { - // OOM killer will take care of us if we end up doing this too - // often. - if errno == unix.ERANGE { - bufSize *= 2 - tmp := C.realloc(buf, C.size_t(bufSize)) - if tmp == nil { - return -1, fmt.Errorf("allocation failed") - } - buf = tmp - goto again - } - return -1, fmt.Errorf("failed user lookup: %s", unix.Errno(rv)) - } - - if result == nil { - return -1, fmt.Errorf("unknown user %s", name) - } - - return int(C.int(result.pw_uid)), nil -} - -// GroupId is an adaption from https://codereview.appspot.com/4589049. -func GroupId(name string) (int, error) { - var grp C.struct_group - var result *C.struct_group - - bufSize := C.sysconf(C._SC_GETGR_R_SIZE_MAX) - if bufSize < 0 { - bufSize = 4096 - } - - buf := C.malloc(C.size_t(bufSize)) - if buf == nil { - return -1, fmt.Errorf("allocation failed") - } - - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - -again: - rv, errno := C.getgrnam_r(cname, - &grp, - (*C.char)(buf), - C.size_t(bufSize), - &result) - if rv != 0 { - // OOM killer will take care of us if we end up doing this too - // often. - if errno == unix.ERANGE { - bufSize *= 2 - tmp := C.realloc(buf, C.size_t(bufSize)) - if tmp == nil { - return -1, fmt.Errorf("allocation failed") - } - buf = tmp - goto again - } - - C.free(buf) - return -1, fmt.Errorf("failed group lookup: %s", unix.Errno(rv)) - } - C.free(buf) - - if result == nil { - return -1, fmt.Errorf("unknown group %s", name) - } - - return int(C.int(result.gr_gid)), nil -} - func ReadPid(r *os.File) int { return int(C.read_pid(C.int(r.Fd()))) } From 30e814b42b0a19355c2bad3a2e971c7bf44c5f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Tue, 27 Oct 2020 18:57:23 -0400 Subject: [PATCH 2/5] lxd: Port to os/user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/endpoints/socket.go | 14 ++++++++++---- lxd/sys/os.go | 24 ++++++++++++++++++------ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lxd/endpoints/socket.go b/lxd/endpoints/socket.go index 6eeccba3fc..98a81a2646 100644 --- a/lxd/endpoints/socket.go +++ b/lxd/endpoints/socket.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "os" + "os/user" "strconv" "github.com/lxc/lxd/client" @@ -86,14 +87,19 @@ func socketUnixSetPermissions(path string, mode os.FileMode) error { } // Change the ownership of the given unix socket file, -func socketUnixSetOwnership(path string, group string) error { +func socketUnixSetOwnership(path string, groupName string) error { var gid int var err error - if group != "" { - gid, err = shared.GroupId(group) + if groupName != "" { + g, err := user.LookupGroup(groupName) if err != nil { - return fmt.Errorf("cannot get group ID of '%s': %v", group, err) + return fmt.Errorf("cannot get group ID of '%s': %v", groupName, err) + } + + gid, err = strconv.Atoi(g.Gid) + if err != nil { + return err } } else { gid = os.Getgid() diff --git a/lxd/sys/os.go b/lxd/sys/os.go index 61cdf47394..0ab6d8f281 100644 --- a/lxd/sys/os.go +++ b/lxd/sys/os.go @@ -3,7 +3,9 @@ package sys import ( + "os/user" "path/filepath" + "strconv" "sync" log "github.com/lxc/lxd/shared/log15" @@ -115,24 +117,34 @@ func (s *OS) Init() error { } // Detect if it is possible to run daemons as an unprivileged user and group. - for _, user := range []string{"lxd", "nobody"} { - uid, err := shared.UserId(user) + for _, userName := range []string{"lxd", "nobody"} { + u, err := user.Lookup(userName) if err != nil { continue } - s.UnprivUser = user + uid, err := strconv.ParseUint(u.Uid, 10, 32) + if err != nil { + return err + } + + s.UnprivUser = userName s.UnprivUID = uint32(uid) break } - for _, group := range []string{"lxd", "nogroup"} { - gid, err := shared.GroupId(group) + for _, groupName := range []string{"lxd", "nogroup"} { + g, err := user.LookupGroup(groupName) if err != nil { continue } - s.UnprivGroup = group + gid, err := strconv.ParseUint(g.Gid, 10, 32) + if err != nil { + return err + } + + s.UnprivGroup = groupName s.UnprivGID = uint32(gid) break } From a38f4092d40c68c77a704353776bf7edce98edd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Tue, 27 Oct 2020 19:07:58 -0400 Subject: [PATCH 3/5] lxd/daemon: Log protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/daemon.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/daemon.go b/lxd/daemon.go index 52308da8c3..1de4938c70 100644 --- a/lxd/daemon.go +++ b/lxd/daemon.go @@ -425,7 +425,7 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) { untrustedOk := (r.Method == "GET" && c.Get.AllowUntrusted) || (r.Method == "POST" && c.Post.AllowUntrusted) if trusted { - logger.Debug("Handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr, "user": username}) + logger.Debug("Handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr, "username": username, "protocol": protocol}) r = r.WithContext(context.WithValue(context.WithValue(r.Context(), "username", username), "protocol", protocol)) } else if untrustedOk && r.Header.Get("X-LXD-authenticated") == "" { logger.Debug(fmt.Sprintf("Allowing untrusted %s", r.Method), log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr}) From 1694cfd678f4eadeddda4831f3103a1d3aaed439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Tue, 27 Oct 2020 19:08:35 -0400 Subject: [PATCH 4/5] lxd/daemon: Pass writer to Authenticate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/certificates.go | 2 +- lxd/daemon.go | 6 +++--- lxd/images.go | 2 +- lxd/operations.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lxd/certificates.go b/lxd/certificates.go index 917f5d1178..673ae5a386 100644 --- a/lxd/certificates.go +++ b/lxd/certificates.go @@ -125,7 +125,7 @@ func certificatesPost(d *Daemon, r *http.Request) response.Response { return response.SmartError(err) } - trusted, _, protocol, err := d.Authenticate(r) + trusted, _, protocol, err := d.Authenticate(nil, r) if err != nil { return response.SmartError(err) } diff --git a/lxd/daemon.go b/lxd/daemon.go index 1de4938c70..94f6728b1c 100644 --- a/lxd/daemon.go +++ b/lxd/daemon.go @@ -241,7 +241,7 @@ func allowProjectPermission(feature string, permission string) func(d *Daemon, r // Convenience function around Authenticate func (d *Daemon) checkTrustedClient(r *http.Request) error { - trusted, _, _, err := d.Authenticate(r) + trusted, _, _, err := d.Authenticate(nil, r) if !trusted || err != nil { if err != nil { return err @@ -258,7 +258,7 @@ func (d *Daemon) checkTrustedClient(r *http.Request) error { // will validate the TLS certificate or Macaroon. // // This does not perform authorization, only validates authentication -func (d *Daemon) Authenticate(r *http.Request) (bool, string, string, error) { +func (d *Daemon) Authenticate(w http.ResponseWriter, r *http.Request) (bool, string, string, error) { // Allow internal cluster traffic if r.TLS != nil { cert, _ := x509.ParseCertificate(d.endpoints.NetworkCert().KeyPair().Certificate[0]) @@ -403,7 +403,7 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) { } // Authentication - trusted, username, protocol, err := d.Authenticate(r) + trusted, username, protocol, err := d.Authenticate(w, r) if err != nil { // If not a macaroon discharge request, return the error _, ok := err.(*bakery.DischargeRequiredError) diff --git a/lxd/images.go b/lxd/images.go index d97e759408..4fb55b9087 100644 --- a/lxd/images.go +++ b/lxd/images.go @@ -696,7 +696,7 @@ func imageCreateInPool(d *Daemon, info *api.Image, storagePool string) error { } func imagesPost(d *Daemon, r *http.Request) response.Response { - trusted, _, _, _ := d.Authenticate(r) + trusted, _, _, _ := d.Authenticate(nil, r) secret := r.Header.Get("X-LXD-secret") fingerprint := r.Header.Get("X-LXD-fingerprint") diff --git a/lxd/operations.go b/lxd/operations.go index e5d934c9ed..b46427f1cf 100644 --- a/lxd/operations.go +++ b/lxd/operations.go @@ -372,7 +372,7 @@ func operationWaitGet(d *Daemon, r *http.Request) response.Response { id := mux.Vars(r)["id"] secret := r.FormValue("secret") - trusted, _, _, _ := d.Authenticate(r) + trusted, _, _, _ := d.Authenticate(nil, r) if !trusted && secret == "" { return response.Forbidden(nil) } From e5a01555ba6d1e25ce859be84a5b9b9d4a88b8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Tue, 27 Oct 2020 19:08:53 -0400 Subject: [PATCH 5/5] lxd/daemon: Record username on unix queries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #8012 Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/daemon.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lxd/daemon.go b/lxd/daemon.go index 94f6728b1c..8e8cd12c20 100644 --- a/lxd/daemon.go +++ b/lxd/daemon.go @@ -11,6 +11,7 @@ import ( "net/http" "net/url" "os" + "os/user" "path/filepath" "strings" "sync" @@ -37,6 +38,7 @@ import ( "github.com/lxc/lxd/lxd/events" "github.com/lxc/lxd/lxd/firewall" "github.com/lxc/lxd/lxd/instance" + "github.com/lxc/lxd/lxd/ucred" // Import instance/drivers without name so init() runs. _ "github.com/lxc/lxd/lxd/instance/drivers" @@ -273,6 +275,21 @@ func (d *Daemon) Authenticate(w http.ResponseWriter, r *http.Request) (bool, str // Local unix socket queries if r.RemoteAddr == "@" { + if w != nil { + conn := extractUnderlyingConn(w) + cred, err := ucred.GetCred(conn) + if err != nil { + return false, "", "", err + } + + u, err := user.LookupId(fmt.Sprintf("%d", cred.Uid)) + if err != nil { + return true, fmt.Sprintf("uid=%d", cred.Uid), "unix", nil + } + + return true, u.Username, "unix", nil + } + return true, "", "unix", nil }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel