aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2022-06-17 13:49:34 -0700
committerSean Whitton <spwhitton@spwhitton.name>2022-06-17 14:13:58 -0700
commitf2191929a8888e4b8799cda3c7c188020a4cabf6 (patch)
treee7911a1fe279499505900ee7a5be0d0cfb6ec16e
parent0b1fdac4616a56831827134abae259eadd3dc67d (diff)
downloadconsfigurator-f2191929a8888e4b8799cda3c7c188020a4cabf6.tar.gz
wrap OSICAT:USER-INFO with getent(1) fallback
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
-rw-r--r--consfigurator.asd2
-rw-r--r--src/connection/linux-namespace.lisp4
-rw-r--r--src/connection/setuid.lisp2
-rw-r--r--src/package.lisp20
-rw-r--r--src/property/user.lisp20
-rw-r--r--src/util/linux-namespace.lisp2
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))))