@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019, 2021, 2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -51,13 +52,23 @@ (define-module (gnu build accounts)
group-entry-gid
group-entry-members
+ subid-entry
+ subid-entry?
+ subid-entry-name
+ subid-entry-start
+ subid-entry-count
+
%password-lock-file
write-group
write-passwd
write-shadow
+ write-subgid
+ write-subuid
read-group
read-passwd
read-shadow
+ read-subgid
+ read-subuid
%id-min
%id-max
@@ -68,11 +79,12 @@ (define-module (gnu build accounts)
;;; Commentary:
;;;
-;;; This modules provides functionality equivalent to the C library's
+;;; This module provides functionality equivalent to the C library's
;;; <shadow.h>, <pwd.h>, and <grp.h> routines, as well as a subset of the
;;; functionality of the Shadow command-line tools. It can parse and write
-;;; /etc/passwd, /etc/shadow, and /etc/group. It can also take care of UID
-;;; and GID allocation in a way similar to what 'useradd' does.
+;;; /etc/passwd, /etc/shadow, /etc/group, /etc/subuid and /etc/subgid. It can
+;;; also take care of UID and GID allocation in a way similar to what 'useradd'
+;;; does. The same goes for sub UID and sub GID allocation.
;;;
;;; The benefit is twofold: less code is involved, and the ID allocation
;;; strategy and state preservation is made explicit.
@@ -225,6 +237,17 @@ (define-database-entry <group-entry> ;<grp.h>
(serialization list->comma-separated comma-separated->list)
(default '())))
+(define-database-entry <subid-entry> ;<subid.h>
+ subid-entry make-subid-entry
+ subid-entry?
+ (serialization #\: subid-entry->string string->subid-entry)
+
+ (name subid-entry-name)
+ (start subid-entry-start
+ (serialization number->string string->number))
+ (count subid-entry-count
+ (serialization number->string string->number)))
+
(define %password-lock-file
;; The password database lock file used by libc's 'lckpwdf'. Users should
;; grab this lock with 'with-file-lock' when they access the databases.
@@ -265,6 +288,10 @@ (define write-shadow
(database-writer "/etc/shadow" #o600 shadow-entry->string))
(define write-group
(database-writer "/etc/group" #o644 group-entry->string))
+(define write-subuid
+ (database-writer "/etc/subuid" #o644 subid-entry->string))
+(define write-subgid
+ (database-writer "/etc/subgid" #o644 subid-entry->string))
(define (database-reader file string->entry)
(lambda* (#:optional (file-or-port file))
@@ -287,6 +314,10 @@ (define read-shadow
(database-reader "/etc/shadow" string->shadow-entry))
(define read-group
(database-reader "/etc/group" string->group-entry))
+(define read-subuid
+ (database-reader "/etc/subuid" string->subid-entry))
+(define read-subgid
+ (database-reader "/etc/subgid" string->subid-entry))
;;;
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -39,6 +40,12 @@ (define-module (gnu system accounts)
user-group-id
user-group-system?
+ subid-range
+ subid-range?
+ subid-range-name
+ subid-range-start
+ subid-range-count
+
sexp->user-account
sexp->user-group
@@ -85,6 +92,16 @@ (define-record-type* <user-group>
(system? user-group-system? ; Boolean
(default #f)))
+(define-record-type* <subid-range>
+ subid-range make-subid-range
+ subid-range?
+ (name subid-range-name)
+ (start subid-range-start (default #f)) ; number
+ (count subid-range-count ; number
+ ; from find_new_sub_gids.c and
+ ; find_new_sub_uids.c
+ (default 65536)))
+
(define (default-home-directory account)
"Return the default home directory for ACCOUNT."
(string-append "/home/" (user-account-name account)))
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -41,6 +42,16 @@ (define %shadow-sample
charlie:" (crypt "hey!" "$6$abc") ":17169::::::
nobody:!:0::::::\n"))
+(define %subuid-sample
+ "\
+root:100000:300
+ada:100300:300\n")
+
+(define %subgid-sample
+ "\
+root:100000:600
+ada:100600:300\n")
+
(test-begin "accounts")
@@ -135,6 +146,50 @@ (define %shadow-sample
read-shadow)
port))))
+(test-equal "write-subuid"
+ %subuid-sample
+ (call-with-output-string
+ (lambda (port)
+ (write-subuid (list (subid-entry
+ (name "root")
+ (start 100000)
+ (count 300))
+ (subid-entry
+ (name "ada")
+ (start 100300)
+ (count 300)))
+ port))))
+
+(test-equal "read-subuid + write-subuid"
+ %subuid-sample
+ (call-with-output-string
+ (lambda (port)
+ (write-subuid (call-with-input-string %subuid-sample
+ read-subuid)
+ port))))
+
+(test-equal "write-subgid"
+ %subgid-sample
+ (call-with-output-string
+ (lambda (port)
+ (write-subgid (list (subid-entry
+ (name "root")
+ (start 100000)
+ (count 600))
+ (subid-entry
+ (name "ada")
+ (start 100600)
+ (count 300)))
+ port))))
+
+(test-equal "read-subgid + write-subgid"
+ %subgid-sample
+ (call-with-output-string
+ (lambda (port)
+ (write-subgid (call-with-input-string %subgid-sample
+ read-subgid)
+ port))))
+
(define allocate-groups (@@ (gnu build accounts) allocate-groups))
(define allocate-passwd (@@ (gnu build accounts) allocate-passwd))