From f2191929a8888e4b8799cda3c7c188020a4cabf6 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Fri, 17 Jun 2022 13:49:34 -0700 Subject: wrap OSICAT:USER-INFO with getent(1) fallback Signed-off-by: Sean Whitton --- consfigurator.asd | 2 +- src/connection/linux-namespace.lisp | 4 ++++ src/connection/setuid.lisp | 2 +- src/package.lisp | 20 +++++++++++--------- src/property/user.lisp | 20 ++++++++++++++++++++ src/util/linux-namespace.lisp | 2 +- 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/consfigurator.asd b/consfigurator.asd index 86c55ac..2b315cb 100644 --- a/consfigurator.asd +++ b/consfigurator.asd @@ -27,7 +27,6 @@ (:cffi-grovel-file "src/libcap" :if-feature :linux) (:file "src/util") (:file "src/util/posix1e") - (:file "src/util/linux-namespace") (:file "src/connection") (:file "src/property") (:file "src/propspec") @@ -52,6 +51,7 @@ (:file "src/property/fstab") (:file "src/property/crypttab") (:file "src/property/user") + (:file "src/util/linux-namespace") (:file "src/property/git") (:file "src/property/gnupg") (:file "src/property/ssh") diff --git a/src/connection/linux-namespace.lisp b/src/connection/linux-namespace.lisp index 2924f2e..a17b4e4 100644 --- a/src/connection/linux-namespace.lisp +++ b/src/connection/linux-namespace.lisp @@ -277,6 +277,8 @@ setgroups(2) is denied in the namespace." (let ((owner (get-userns-owner (caar ns-fds)))) (if (zerop owner) (nix:setgroups nil) + ;; We can't use USER:USER-INFO here because we can't + ;; run commands using RUNLINES. (alet (osicat:user-info owner) ;; As a precaution, we could also setuid & setgid to ;; OWNER here. However, it ought to be meaningless @@ -330,6 +332,8 @@ setgroups(2) is denied in the namespace." (nix:fchdir root-fd) (chroot "."))) (mapc #'nix:close opened-fds)) (when uid + ;; We similarly can't use USER:USER-INFO here because we still can't + ;; run commands using RUNLINES. (alet (or (osicat:user-info uid) (error "~&Could not look up user info for UID ~A." uid)) (setf user (cdr (assoc :name it))) diff --git a/src/connection/setuid.lisp b/src/connection/setuid.lisp index fda100f..5c21020 100644 --- a/src/connection/setuid.lisp +++ b/src/connection/setuid.lisp @@ -25,7 +25,7 @@ (error "~&SETUIDing requires a Lisp image running as root")) (informat 1 "~&SETUIDing to ~A" user) (let* ((ent - (or (osicat:user-info user) + (or (user:user-info user) (failed-change "~&Could not look up user info for ~A." user))) (xdg-cache-home (ensure-directory-pathname diff --git a/src/package.lisp b/src/package.lisp index df05b19..a8b298e 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -414,14 +414,6 @@ #:posix-capability-p)) - (package :consfigurator.util.linux-namespace - (:use #:consfigurator.util.posix1e #:cffi) - (:export #:get-ids-offset - #:reduce-id-maps - #:shift-ids - #:setgroups-p - #:get-userns-owner)) - (package :consfigurator.property.cmd (:export #:single)) @@ -571,7 +563,17 @@ #:has-login-shell #:has-enabled-password #:has-locked-password - #:passwd-field)) + #:passwd-field + #:user-info)) + + (package :consfigurator.util.linux-namespace + (:use #:consfigurator.util.posix1e #:cffi) + (:local-nicknames (#:user #:consfigurator.property.user)) + (:export #:get-ids-offset + #:reduce-id-maps + #:shift-ids + #:setgroups-p + #:get-userns-owner)) (package :consfigurator.property.chroot (:local-nicknames (#:service #:consfigurator.property.service) diff --git a/src/property/user.lisp b/src/property/user.lisp index 74d4737..1dd9f1d 100644 --- a/src/property/user.lisp +++ b/src/property/user.lisp @@ -141,3 +141,23 @@ properties not strictly POSIX-compatible." (defun user-exists (username) (zerop (mrun :for-exit "getent" "passwd" username))) + +(defun user-info (username-or-uid) + "Return passwd database entry for USERNAME-OR-UID as an alist. + +Falls back to getent(1), which is not specified in POSIX, so use of this +function makes properties not strictly POSIX-compatible." + ;; getpwnam(3) and getpwuid(3) can fail to load the required NSS modules if + ;; we have chrooted or similar. In that case, it appears as though the user + ;; does not exist. So fall back to getent(1). + (or (and (lisp-connection-p) (osicat:user-info username-or-uid)) + (aand (runlines "getent" "passwd" (aetypecase username-or-uid + (string it) + (number (write-to-string it)))) + (destructuring-bind (name password uid gid &rest rest) + (split-string (car it) :separator '(#\:)) + (declare (ignore password)) + (list* (cons :name name) + (cons :user-id (parse-integer uid)) + (cons :group-id (parse-integer gid)) + (pairlis '(:gecos :home :shell) rest)))))) diff --git a/src/util/linux-namespace.lisp b/src/util/linux-namespace.lisp index 3bc2e59..53c816b 100644 --- a/src/util/linux-namespace.lisp +++ b/src/util/linux-namespace.lisp @@ -24,7 +24,7 @@ numerical subordinate ID and numerical subordinate ID count for the first entry in FILE for IDENTIFIER." (with-open-file (file file) - (loop with info = (osicat:user-info identifier) + (loop with info = (user:user-info identifier) with fields = (list (cdr (assoc :name info)) (write-to-string (cdr (assoc :user-id info)))) -- cgit v1.2.3