diff options
| author | Giacomo Leidi <goodoldpaul@autistici.org> | 2024-10-08 00:40:26 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2024-12-18 18:32:40 +0100 |
| commit | 58f430f69e71f95cedab9912c1c9f2cc8660fad9 (patch) | |
| tree | aa6522c5e928ca36acdf6fc479e86e526a4e4b5c | |
| parent | 478b9ccea854ec4407643a44d40ee61584fbc73d (diff) | |
accounts: Add /etc/subuid and /etc/subgid support.
This commit adds a new record type, <subid-entry> and serializers
and deserializers for it in (gnu build accounts). Each instance of this
record represents one line in either /etc/subuid or /etc/subgid. Since
Shadow uses the same representation for both files, it should be ok if
we do it as well.
This commit adds also <subid-range>, a user facing representation of
<subid-entry>. It is supposed to be usable directly in OS configurations.
* gnu/build/accounts.scm (subid-entry): New record;
(write-subgid): add serializer for subgids;
(write-subuid): add serializer for subuids;
(read-subgid): add serializer for subgids;
(read-subuid): add serializer for subuids.
* gnu/system/accounts.scm (subid-range): New record.
* test/accounts.scm: Test them.
Change-Id: I6b037e40e354c069bf556412bb5b626bd3ea1b2c
Signed-off-by: Giacomo Leidi <goodoldpaul@autistici.org>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
| -rw-r--r-- | gnu/build/accounts.scm | 37 | ||||
| -rw-r--r-- | gnu/system/accounts.scm | 17 | ||||
| -rw-r--r-- | tests/accounts.scm | 55 |
3 files changed, 106 insertions, 3 deletions
diff --git a/gnu/build/accounts.scm b/gnu/build/accounts.scm index fa6f454b5ed..ea8c69f2051 100644 --- a/gnu/build/accounts.scm +++ b/gnu/build/accounts.scm | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2019, 2021, 2023 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2019, 2021, 2023 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org> | ||
| 3 | ;;; | 4 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 5 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 6 | ;;; |
| @@ -51,13 +52,23 @@ | |||
| 51 | group-entry-gid | 52 | group-entry-gid |
| 52 | group-entry-members | 53 | group-entry-members |
| 53 | 54 | ||
| 55 | subid-entry | ||
| 56 | subid-entry? | ||
| 57 | subid-entry-name | ||
| 58 | subid-entry-start | ||
| 59 | subid-entry-count | ||
| 60 | |||
| 54 | %password-lock-file | 61 | %password-lock-file |
| 55 | write-group | 62 | write-group |
| 56 | write-passwd | 63 | write-passwd |
| 57 | write-shadow | 64 | write-shadow |
| 65 | write-subgid | ||
| 66 | write-subuid | ||
| 58 | read-group | 67 | read-group |
| 59 | read-passwd | 68 | read-passwd |
| 60 | read-shadow | 69 | read-shadow |
| 70 | read-subgid | ||
| 71 | read-subuid | ||
| 61 | 72 | ||
| 62 | %id-min | 73 | %id-min |
| 63 | %id-max | 74 | %id-max |
| @@ -68,11 +79,12 @@ | |||
| 68 | 79 | ||
| 69 | ;;; Commentary: | 80 | ;;; Commentary: |
| 70 | ;;; | 81 | ;;; |
| 71 | ;;; This modules provides functionality equivalent to the C library's | 82 | ;;; This module provides functionality equivalent to the C library's |
| 72 | ;;; <shadow.h>, <pwd.h>, and <grp.h> routines, as well as a subset of the | 83 | ;;; <shadow.h>, <pwd.h>, and <grp.h> routines, as well as a subset of the |
| 73 | ;;; functionality of the Shadow command-line tools. It can parse and write | 84 | ;;; functionality of the Shadow command-line tools. It can parse and write |
| 74 | ;;; /etc/passwd, /etc/shadow, and /etc/group. It can also take care of UID | 85 | ;;; /etc/passwd, /etc/shadow, /etc/group, /etc/subuid and /etc/subgid. It can |
| 75 | ;;; and GID allocation in a way similar to what 'useradd' does. | 86 | ;;; also take care of UID and GID allocation in a way similar to what 'useradd' |
| 87 | ;;; does. The same goes for sub UID and sub GID allocation. | ||
| 76 | ;;; | 88 | ;;; |
| 77 | ;;; The benefit is twofold: less code is involved, and the ID allocation | 89 | ;;; The benefit is twofold: less code is involved, and the ID allocation |
| 78 | ;;; strategy and state preservation is made explicit. | 90 | ;;; strategy and state preservation is made explicit. |
| @@ -225,6 +237,17 @@ each field." | |||
| 225 | (serialization list->comma-separated comma-separated->list) | 237 | (serialization list->comma-separated comma-separated->list) |
| 226 | (default '()))) | 238 | (default '()))) |
| 227 | 239 | ||
| 240 | (define-database-entry <subid-entry> ;<subid.h> | ||
| 241 | subid-entry make-subid-entry | ||
| 242 | subid-entry? | ||
| 243 | (serialization #\: subid-entry->string string->subid-entry) | ||
| 244 | |||
| 245 | (name subid-entry-name) | ||
| 246 | (start subid-entry-start | ||
| 247 | (serialization number->string string->number)) | ||
| 248 | (count subid-entry-count | ||
| 249 | (serialization number->string string->number))) | ||
| 250 | |||
| 228 | (define %password-lock-file | 251 | (define %password-lock-file |
| 229 | ;; The password database lock file used by libc's 'lckpwdf'. Users should | 252 | ;; The password database lock file used by libc's 'lckpwdf'. Users should |
| 230 | ;; grab this lock with 'with-file-lock' when they access the databases. | 253 | ;; grab this lock with 'with-file-lock' when they access the databases. |
| @@ -265,6 +288,10 @@ to it atomically and set the appropriate permissions." | |||
| 265 | (database-writer "/etc/shadow" #o600 shadow-entry->string)) | 288 | (database-writer "/etc/shadow" #o600 shadow-entry->string)) |
| 266 | (define write-group | 289 | (define write-group |
| 267 | (database-writer "/etc/group" #o644 group-entry->string)) | 290 | (database-writer "/etc/group" #o644 group-entry->string)) |
| 291 | (define write-subuid | ||
| 292 | (database-writer "/etc/subuid" #o644 subid-entry->string)) | ||
| 293 | (define write-subgid | ||
| 294 | (database-writer "/etc/subgid" #o644 subid-entry->string)) | ||
| 268 | 295 | ||
| 269 | (define (database-reader file string->entry) | 296 | (define (database-reader file string->entry) |
| 270 | (lambda* (#:optional (file-or-port file)) | 297 | (lambda* (#:optional (file-or-port file)) |
| @@ -287,6 +314,10 @@ to it atomically and set the appropriate permissions." | |||
| 287 | (database-reader "/etc/shadow" string->shadow-entry)) | 314 | (database-reader "/etc/shadow" string->shadow-entry)) |
| 288 | (define read-group | 315 | (define read-group |
| 289 | (database-reader "/etc/group" string->group-entry)) | 316 | (database-reader "/etc/group" string->group-entry)) |
| 317 | (define read-subuid | ||
| 318 | (database-reader "/etc/subuid" string->subid-entry)) | ||
| 319 | (define read-subgid | ||
| 320 | (database-reader "/etc/subgid" string->subid-entry)) | ||
| 290 | 321 | ||
| 291 | 322 | ||
| 292 | ;;; | 323 | ;;; |
diff --git a/gnu/system/accounts.scm b/gnu/system/accounts.scm index 586cff1842e..9a006c188db 100644 --- a/gnu/system/accounts.scm +++ b/gnu/system/accounts.scm | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org> | ||
| 3 | ;;; | 4 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 5 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 6 | ;;; |
| @@ -39,6 +40,12 @@ | |||
| 39 | user-group-id | 40 | user-group-id |
| 40 | user-group-system? | 41 | user-group-system? |
| 41 | 42 | ||
| 43 | subid-range | ||
| 44 | subid-range? | ||
| 45 | subid-range-name | ||
| 46 | subid-range-start | ||
| 47 | subid-range-count | ||
| 48 | |||
| 42 | sexp->user-account | 49 | sexp->user-account |
| 43 | sexp->user-group | 50 | sexp->user-group |
| 44 | 51 | ||
| @@ -85,6 +92,16 @@ | |||
| 85 | (system? user-group-system? ; Boolean | 92 | (system? user-group-system? ; Boolean |
| 86 | (default #f))) | 93 | (default #f))) |
| 87 | 94 | ||
| 95 | (define-record-type* <subid-range> | ||
| 96 | subid-range make-subid-range | ||
| 97 | subid-range? | ||
| 98 | (name subid-range-name) | ||
| 99 | (start subid-range-start (default #f)) ; number | ||
| 100 | (count subid-range-count ; number | ||
| 101 | ; from find_new_sub_gids.c and | ||
| 102 | ; find_new_sub_uids.c | ||
| 103 | (default 65536))) | ||
| 104 | |||
| 88 | (define (default-home-directory account) | 105 | (define (default-home-directory account) |
| 89 | "Return the default home directory for ACCOUNT." | 106 | "Return the default home directory for ACCOUNT." |
| 90 | (string-append "/home/" (user-account-name account))) | 107 | (string-append "/home/" (user-account-name account))) |
diff --git a/tests/accounts.scm b/tests/accounts.scm index 78136390bbf..4944c22f499 100644 --- a/tests/accounts.scm +++ b/tests/accounts.scm | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org> | ||
| 3 | ;;; | 4 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 5 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 6 | ;;; |
| @@ -41,6 +42,16 @@ root:" (crypt "secret" "$6$abc") ":17169:::::: | |||
| 41 | charlie:" (crypt "hey!" "$6$abc") ":17169:::::: | 42 | charlie:" (crypt "hey!" "$6$abc") ":17169:::::: |
| 42 | nobody:!:0::::::\n")) | 43 | nobody:!:0::::::\n")) |
| 43 | 44 | ||
| 45 | (define %subuid-sample | ||
| 46 | "\ | ||
| 47 | root:100000:300 | ||
| 48 | ada:100300:300\n") | ||
| 49 | |||
| 50 | (define %subgid-sample | ||
| 51 | "\ | ||
| 52 | root:100000:600 | ||
| 53 | ada:100600:300\n") | ||
| 54 | |||
| 44 | 55 | ||
| 45 | (test-begin "accounts") | 56 | (test-begin "accounts") |
| 46 | 57 | ||
| @@ -135,6 +146,50 @@ nobody:!:0::::::\n")) | |||
| 135 | read-shadow) | 146 | read-shadow) |
| 136 | port)))) | 147 | port)))) |
| 137 | 148 | ||
| 149 | (test-equal "write-subuid" | ||
| 150 | %subuid-sample | ||
| 151 | (call-with-output-string | ||
| 152 | (lambda (port) | ||
| 153 | (write-subuid (list (subid-entry | ||
| 154 | (name "root") | ||
| 155 | (start 100000) | ||
| 156 | (count 300)) | ||
| 157 | (subid-entry | ||
| 158 | (name "ada") | ||
| 159 | (start 100300) | ||
| 160 | (count 300))) | ||
| 161 | port)))) | ||
| 162 | |||
| 163 | (test-equal "read-subuid + write-subuid" | ||
| 164 | %subuid-sample | ||
| 165 | (call-with-output-string | ||
| 166 | (lambda (port) | ||
| 167 | (write-subuid (call-with-input-string %subuid-sample | ||
| 168 | read-subuid) | ||
| 169 | port)))) | ||
| 170 | |||
| 171 | (test-equal "write-subgid" | ||
| 172 | %subgid-sample | ||
| 173 | (call-with-output-string | ||
| 174 | (lambda (port) | ||
| 175 | (write-subgid (list (subid-entry | ||
| 176 | (name "root") | ||
| 177 | (start 100000) | ||
| 178 | (count 600)) | ||
| 179 | (subid-entry | ||
| 180 | (name "ada") | ||
| 181 | (start 100600) | ||
| 182 | (count 300))) | ||
| 183 | port)))) | ||
| 184 | |||
| 185 | (test-equal "read-subgid + write-subgid" | ||
| 186 | %subgid-sample | ||
| 187 | (call-with-output-string | ||
| 188 | (lambda (port) | ||
| 189 | (write-subgid (call-with-input-string %subgid-sample | ||
| 190 | read-subgid) | ||
| 191 | port)))) | ||
| 192 | |||
| 138 | 193 | ||
| 139 | (define allocate-groups (@@ (gnu build accounts) allocate-groups)) | 194 | (define allocate-groups (@@ (gnu build accounts) allocate-groups)) |
| 140 | (define allocate-passwd (@@ (gnu build accounts) allocate-passwd)) | 195 | (define allocate-passwd (@@ (gnu build accounts) allocate-passwd)) |
