2014-04-30 15:44:59 +02:00
|
|
|
|
;;; GNU Guix --- Functional package management for GNU
|
2016-03-20 15:02:38 +01:00
|
|
|
|
;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
|
2015-03-03 08:14:14 +01:00
|
|
|
|
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
|
2014-04-30 15:44:59 +02:00
|
|
|
|
;;;
|
|
|
|
|
;;; This file is part of GNU Guix.
|
|
|
|
|
;;;
|
|
|
|
|
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
|
|
|
|
;;; under the terms of the GNU General Public License as published by
|
|
|
|
|
;;; the Free Software Foundation; either version 3 of the License, or (at
|
|
|
|
|
;;; your option) any later version.
|
|
|
|
|
;;;
|
|
|
|
|
;;; GNU Guix is distributed in the hope that it will be useful, but
|
|
|
|
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;;; GNU General Public License for more details.
|
|
|
|
|
;;;
|
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
2014-09-03 10:47:05 +02:00
|
|
|
|
(define-module (gnu build activation)
|
2014-09-03 11:14:12 +02:00
|
|
|
|
#:use-module (gnu build linux-boot)
|
2014-04-30 22:17:56 +02:00
|
|
|
|
#:use-module (guix build utils)
|
2014-04-30 15:44:59 +02:00
|
|
|
|
#:use-module (ice-9 ftw)
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
#:use-module (ice-9 match)
|
|
|
|
|
#:use-module (srfi srfi-1)
|
2014-05-04 00:18:46 +02:00
|
|
|
|
#:use-module (srfi srfi-26)
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
#:export (activate-users+groups
|
|
|
|
|
activate-etc
|
2014-05-17 17:39:30 +02:00
|
|
|
|
activate-setuid-programs
|
2014-09-11 22:18:52 +02:00
|
|
|
|
activate-/bin/sh
|
2014-11-02 23:06:17 +01:00
|
|
|
|
activate-modprobe
|
2014-11-11 22:42:15 +01:00
|
|
|
|
activate-firmware
|
2015-04-12 15:33:42 +02:00
|
|
|
|
activate-ptrace-attach
|
2014-05-17 17:39:30 +02:00
|
|
|
|
activate-current-system))
|
2014-04-30 15:44:59 +02:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
;;;
|
|
|
|
|
;;; This module provides "activation" helpers. Activation is the process that
|
|
|
|
|
;;; consists in setting up system-wide files and directories so that an
|
|
|
|
|
;;; 'operating-system' configuration becomes active.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2015-04-08 21:23:45 +02:00
|
|
|
|
(define (enumerate thunk)
|
|
|
|
|
"Return the list of values returned by THUNK until it returned #f."
|
|
|
|
|
(let loop ((entry (thunk))
|
|
|
|
|
(result '()))
|
|
|
|
|
(if (not entry)
|
|
|
|
|
(reverse result)
|
|
|
|
|
(loop (thunk) (cons entry result)))))
|
|
|
|
|
|
|
|
|
|
(define (current-users)
|
|
|
|
|
"Return the passwd entries for all the currently defined user accounts."
|
|
|
|
|
(setpw)
|
|
|
|
|
(enumerate getpwent))
|
|
|
|
|
|
|
|
|
|
(define (current-groups)
|
|
|
|
|
"Return the group entries for all the currently defined user groups."
|
|
|
|
|
(setgr)
|
|
|
|
|
(enumerate getgrent))
|
|
|
|
|
|
2014-07-25 00:12:35 +02:00
|
|
|
|
(define* (add-group name #:key gid password system?
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
(log-port (current-error-port)))
|
|
|
|
|
"Add NAME as a user group, with the given numeric GID if specified."
|
|
|
|
|
;; Use 'groupadd' from the Shadow package.
|
|
|
|
|
(format log-port "adding group '~a'...~%" name)
|
|
|
|
|
(let ((args `(,@(if gid `("-g" ,(number->string gid)) '())
|
|
|
|
|
,@(if password `("-p" ,password) '())
|
2014-07-25 00:12:35 +02:00
|
|
|
|
,@(if system? `("--system") '())
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
,name)))
|
|
|
|
|
(zero? (apply system* "groupadd" args))))
|
|
|
|
|
|
2014-12-13 22:30:44 +01:00
|
|
|
|
(define %skeleton-directory
|
|
|
|
|
;; Directory containing skeleton files for new accounts.
|
|
|
|
|
;; Note: keep the trailing '/' so that 'scandir' enters it.
|
|
|
|
|
"/etc/skel/")
|
|
|
|
|
|
|
|
|
|
(define (dot-or-dot-dot? file)
|
|
|
|
|
(member file '("." "..")))
|
|
|
|
|
|
2015-05-05 23:46:54 +02:00
|
|
|
|
(define (make-file-writable file)
|
|
|
|
|
"Make FILE writable for its owner.."
|
|
|
|
|
(let ((stat (lstat file))) ;XXX: symlinks
|
|
|
|
|
(chmod file (logior #o600 (stat:perms stat)))))
|
|
|
|
|
|
2014-12-13 22:30:44 +01:00
|
|
|
|
(define* (copy-account-skeletons home
|
|
|
|
|
#:optional (directory %skeleton-directory))
|
|
|
|
|
"Copy the account skeletons from DIRECTORY to HOME."
|
|
|
|
|
(let ((files (scandir directory (negate dot-or-dot-dot?)
|
|
|
|
|
string<?)))
|
|
|
|
|
(mkdir-p home)
|
|
|
|
|
(for-each (lambda (file)
|
2015-05-05 23:46:54 +02:00
|
|
|
|
(let ((target (string-append home "/" file)))
|
2016-03-20 15:02:38 +01:00
|
|
|
|
(copy-recursively (string-append directory "/" file)
|
|
|
|
|
target)
|
2015-05-05 23:46:54 +02:00
|
|
|
|
(make-file-writable target)))
|
|
|
|
|
files)))
|
|
|
|
|
|
|
|
|
|
(define* (make-skeletons-writable home
|
|
|
|
|
#:optional (directory %skeleton-directory))
|
|
|
|
|
"Make sure that the files that have been copied from DIRECTORY to HOME are
|
|
|
|
|
owner-writable in HOME."
|
|
|
|
|
(let ((files (scandir directory (negate dot-or-dot-dot?)
|
|
|
|
|
string<?)))
|
|
|
|
|
(for-each (lambda (file)
|
|
|
|
|
(let ((target (string-append home "/" file)))
|
|
|
|
|
(when (file-exists? target)
|
|
|
|
|
(make-file-writable target))))
|
2014-12-13 22:30:44 +01:00
|
|
|
|
files)))
|
|
|
|
|
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
(define* (add-user name group
|
2014-06-27 18:57:33 +02:00
|
|
|
|
#:key uid comment home shell password system?
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
(supplementary-groups '())
|
|
|
|
|
(log-port (current-error-port)))
|
|
|
|
|
"Create an account for user NAME part of GROUP, with the specified
|
|
|
|
|
properties. Return #t on success."
|
|
|
|
|
(format log-port "adding user '~a'...~%" name)
|
|
|
|
|
|
|
|
|
|
(if (and uid (zero? uid))
|
|
|
|
|
|
|
|
|
|
;; 'useradd' fails with "Cannot determine your user name" if the root
|
|
|
|
|
;; account doesn't exist. Thus, for bootstrapping purposes, create that
|
|
|
|
|
;; one manually.
|
|
|
|
|
(begin
|
|
|
|
|
(call-with-output-file "/etc/shadow"
|
|
|
|
|
(cut format <> "~a::::::::~%" name))
|
|
|
|
|
(call-with-output-file "/etc/passwd"
|
|
|
|
|
(cut format <> "~a:x:~a:~a:~a:~a:~a~%"
|
|
|
|
|
name "0" "0" comment home shell))
|
|
|
|
|
(chmod "/etc/shadow" #o600)
|
2014-12-13 22:30:44 +01:00
|
|
|
|
(copy-account-skeletons (or home "/root"))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
#t)
|
|
|
|
|
|
|
|
|
|
;; Use 'useradd' from the Shadow package.
|
|
|
|
|
(let ((args `(,@(if uid `("-u" ,(number->string uid)) '())
|
|
|
|
|
"-g" ,(if (number? group) (number->string group) group)
|
|
|
|
|
,@(if (pair? supplementary-groups)
|
|
|
|
|
`("-G" ,(string-join supplementary-groups ","))
|
|
|
|
|
'())
|
|
|
|
|
,@(if comment `("-c" ,comment) '())
|
2014-05-14 19:05:21 +02:00
|
|
|
|
,@(if home
|
|
|
|
|
(if (file-exists? home)
|
|
|
|
|
`("-d" ,home) ; avoid warning from 'useradd'
|
|
|
|
|
`("-d" ,home "--create-home"))
|
|
|
|
|
'())
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
,@(if shell `("-s" ,shell) '())
|
|
|
|
|
,@(if password `("-p" ,password) '())
|
2014-06-27 18:57:33 +02:00
|
|
|
|
,@(if system? '("--system") '())
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
,name)))
|
2015-05-05 23:46:54 +02:00
|
|
|
|
(and (zero? (apply system* "useradd" args))
|
|
|
|
|
(begin
|
|
|
|
|
;; Since /etc/skel is a link to a directory in the store where
|
|
|
|
|
;; all files have the writable bit cleared, and since 'useradd'
|
|
|
|
|
;; preserves permissions when it copies them, explicitly make
|
|
|
|
|
;; them writable.
|
|
|
|
|
(make-skeletons-writable home)
|
|
|
|
|
#t)))))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
|
2014-09-22 10:10:08 +02:00
|
|
|
|
(define* (modify-user name group
|
|
|
|
|
#:key uid comment home shell password system?
|
|
|
|
|
(supplementary-groups '())
|
|
|
|
|
(log-port (current-error-port)))
|
|
|
|
|
"Modify user account NAME to have all the given settings."
|
|
|
|
|
;; Use 'usermod' from the Shadow package.
|
|
|
|
|
(let ((args `(,@(if uid `("-u" ,(number->string uid)) '())
|
|
|
|
|
"-g" ,(if (number? group) (number->string group) group)
|
|
|
|
|
,@(if (pair? supplementary-groups)
|
|
|
|
|
`("-G" ,(string-join supplementary-groups ","))
|
|
|
|
|
'())
|
|
|
|
|
,@(if comment `("-c" ,comment) '())
|
|
|
|
|
;; Don't use '--move-home', so ignore HOME.
|
|
|
|
|
,@(if shell `("-s" ,shell) '())
|
|
|
|
|
,name)))
|
|
|
|
|
(zero? (apply system* "usermod" args))))
|
|
|
|
|
|
2015-04-08 21:23:45 +02:00
|
|
|
|
(define* (delete-user name #:key (log-port (current-error-port)))
|
|
|
|
|
"Remove user account NAME. Return #t on success. This may fail if NAME is
|
|
|
|
|
logged in."
|
|
|
|
|
(format log-port "deleting user '~a'...~%" name)
|
|
|
|
|
(zero? (system* "userdel" name)))
|
|
|
|
|
|
|
|
|
|
(define* (delete-group name #:key (log-port (current-error-port)))
|
|
|
|
|
"Remove group NAME. Return #t on success."
|
|
|
|
|
(format log-port "deleting group '~a'...~%" name)
|
|
|
|
|
(zero? (system* "groupdel" name)))
|
|
|
|
|
|
2014-09-22 10:10:08 +02:00
|
|
|
|
(define* (ensure-user name group
|
|
|
|
|
#:key uid comment home shell password system?
|
|
|
|
|
(supplementary-groups '())
|
|
|
|
|
(log-port (current-error-port))
|
|
|
|
|
#:rest rest)
|
|
|
|
|
"Make sure user NAME exists and has the relevant settings."
|
|
|
|
|
(if (false-if-exception (getpwnam name))
|
|
|
|
|
(apply modify-user name group rest)
|
|
|
|
|
(apply add-user name group rest)))
|
|
|
|
|
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
(define (activate-users+groups users groups)
|
|
|
|
|
"Make sure the accounts listed in USERS and the user groups listed in GROUPS
|
|
|
|
|
are all available.
|
|
|
|
|
|
|
|
|
|
Each item in USERS is a list of all the characteristics of a user account;
|
|
|
|
|
each item in GROUPS is a tuple with the group name, group password or #f, and
|
|
|
|
|
numeric gid or #f."
|
|
|
|
|
(define (touch file)
|
2014-06-26 23:31:17 +02:00
|
|
|
|
(close-port (open-file file "a0b")))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
|
|
|
|
|
(define activate-user
|
|
|
|
|
(match-lambda
|
2014-06-27 18:57:33 +02:00
|
|
|
|
((name uid group supplementary-groups comment home shell password system?)
|
2014-09-22 10:10:08 +02:00
|
|
|
|
(let ((profile-dir (string-append "/var/guix/profiles/per-user/"
|
|
|
|
|
name)))
|
|
|
|
|
(ensure-user name group
|
|
|
|
|
#:uid uid
|
|
|
|
|
#:system? system?
|
|
|
|
|
#:supplementary-groups supplementary-groups
|
|
|
|
|
#:comment comment
|
|
|
|
|
#:home home
|
|
|
|
|
#:shell shell
|
|
|
|
|
#:password password)
|
|
|
|
|
|
|
|
|
|
(unless system?
|
|
|
|
|
;; Create the profile directory for the new account.
|
|
|
|
|
(let ((pw (getpwnam name)))
|
|
|
|
|
(mkdir-p profile-dir)
|
|
|
|
|
(chown profile-dir (passwd:uid pw) (passwd:gid pw))))))))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
|
|
|
|
|
;; 'groupadd' aborts if the file doesn't already exist.
|
|
|
|
|
(touch "/etc/group")
|
|
|
|
|
|
|
|
|
|
;; Create the root account so we can use 'useradd' and 'groupadd'.
|
|
|
|
|
(activate-user (find (match-lambda
|
|
|
|
|
((name (? zero?) _ ...) #t)
|
|
|
|
|
(_ #f))
|
|
|
|
|
users))
|
|
|
|
|
|
|
|
|
|
;; Then create the groups.
|
|
|
|
|
(for-each (match-lambda
|
2014-07-25 00:12:35 +02:00
|
|
|
|
((name password gid system?)
|
2014-06-04 23:08:09 +02:00
|
|
|
|
(unless (false-if-exception (getgrnam name))
|
2014-07-25 00:12:35 +02:00
|
|
|
|
(add-group name
|
|
|
|
|
#:gid gid #:password password
|
|
|
|
|
#:system? system?))))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
groups)
|
|
|
|
|
|
2015-04-08 21:23:45 +02:00
|
|
|
|
;; Create the other user accounts.
|
|
|
|
|
(for-each activate-user users)
|
|
|
|
|
|
|
|
|
|
;; Finally, delete extra user accounts and groups.
|
|
|
|
|
(for-each delete-user
|
|
|
|
|
(lset-difference string=?
|
|
|
|
|
(map passwd:name (current-users))
|
|
|
|
|
(match users
|
|
|
|
|
(((names . _) ...)
|
|
|
|
|
names))))
|
|
|
|
|
(for-each delete-group
|
|
|
|
|
(lset-difference string=?
|
|
|
|
|
(map group:name (current-groups))
|
|
|
|
|
(match groups
|
|
|
|
|
(((names . _) ...)
|
|
|
|
|
names)))))
|
system: Make accounts and groups at activation time.
* gnu/services/base.scm (guix-build-accounts): Remove #:gid parameter;
add #:group. Remove 'password' and 'gid' fields in 'user-account'
form, and add 'group'.
(guix-service): Remove #:build-user-gid parameter. Remove 'id' field
in 'user-group' form.
* gnu/system.scm (etc-directory): Remove #:groups and #:accounts. No
longer produce files "passwd", "shadow", and "group". Adjust caller
accordingly.
(%root-account): New variable.
(operating-system-accounts): Add 'users' variable. Add %ROOT-ACCOUNT
only of 'operating-system-users' doesn't already contain a root
account.
(user-group->gexp, user-account->gexp): New procedures.
(operating-system-boot-script): Add calls to 'setenv' and
'activate-users+groups' in gexp.
* gnu/system/linux.scm (base-pam-services): Add PAM services for
"user{add,del,mode}" and "group{add,del,mod}".
* gnu/system/shadow.scm (<user-account>)[gid]: Rename to...
[group]: ... this.
[supplementary-groups]: New field.
[uid, password]: Default to #f.
(<user-group>)[id]: Default to #f.
(group-file, passwd-file): Remove.
* gnu/system/vm.scm (operating-system-default-contents)[user-directories]:
Remove. Add "/home" to the directives.
* guix/build/activation.scm (add-group, add-user,
activate-users+groups): New procedures.
2014-05-11 22:41:01 +02:00
|
|
|
|
|
2014-04-30 15:44:59 +02:00
|
|
|
|
(define (activate-etc etc)
|
|
|
|
|
"Install ETC, a directory in the store, as the source of static files for
|
|
|
|
|
/etc."
|
|
|
|
|
|
|
|
|
|
;; /etc is a mixture of static and dynamic settings. Here is where we
|
|
|
|
|
;; initialize it from the static part.
|
|
|
|
|
|
2014-09-11 23:23:07 +02:00
|
|
|
|
(define (rm-f file)
|
|
|
|
|
(false-if-exception (delete-file file)))
|
|
|
|
|
|
2014-04-30 15:44:59 +02:00
|
|
|
|
(format #t "populating /etc from ~a...~%" etc)
|
2014-09-11 23:23:07 +02:00
|
|
|
|
|
2015-03-03 08:14:14 +01:00
|
|
|
|
;; Create the /etc/ssl -> /run/current-system/profile/etc/ssl symlink. This
|
|
|
|
|
;; symlink, to a target outside of the store, probably doesn't belong in the
|
|
|
|
|
;; static 'etc' store directory. However, if it were to be put there,
|
|
|
|
|
;; beware that if /run/current-system/profile/etc/ssl doesn't exist at the
|
|
|
|
|
;; time of activation (e.g. when installing a fresh system), the call to
|
|
|
|
|
;; 'file-is-directory?' below will fail because it uses 'stat', not 'lstat'.
|
|
|
|
|
(rm-f "/etc/ssl")
|
|
|
|
|
(symlink "/run/current-system/profile/etc/ssl" "/etc/ssl")
|
|
|
|
|
|
2014-09-11 23:23:07 +02:00
|
|
|
|
(rm-f "/etc/static")
|
|
|
|
|
(symlink etc "/etc/static")
|
|
|
|
|
(for-each (lambda (file)
|
|
|
|
|
(let ((target (string-append "/etc/" file))
|
|
|
|
|
(source (string-append "/etc/static/" file)))
|
|
|
|
|
(rm-f target)
|
|
|
|
|
|
|
|
|
|
;; Things such as /etc/sudoers must be regular files, not
|
|
|
|
|
;; symlinks; furthermore, they could be modified behind our
|
|
|
|
|
;; back---e.g., with 'visudo'. Thus, make a copy instead of
|
|
|
|
|
;; symlinking them.
|
|
|
|
|
(if (file-is-directory? source)
|
|
|
|
|
(symlink source target)
|
|
|
|
|
(copy-file source target))
|
|
|
|
|
|
|
|
|
|
;; XXX: Dirty hack to meet sudo's expectations.
|
|
|
|
|
(when (string=? (basename target) "sudoers")
|
|
|
|
|
(chmod target #o440))))
|
2014-12-13 22:30:44 +01:00
|
|
|
|
(scandir etc (negate dot-or-dot-dot?)
|
2014-09-11 23:23:07 +02:00
|
|
|
|
|
|
|
|
|
;; The default is 'string-locale<?', but we don't have
|
|
|
|
|
;; it when run from the initrd's statically-linked
|
|
|
|
|
;; Guile.
|
2014-12-05 00:19:39 +01:00
|
|
|
|
string<?)))
|
2014-04-30 15:44:59 +02:00
|
|
|
|
|
2014-04-30 22:17:56 +02:00
|
|
|
|
(define %setuid-directory
|
|
|
|
|
;; Place where setuid programs are stored.
|
|
|
|
|
"/run/setuid-programs")
|
|
|
|
|
|
2014-09-11 21:25:58 +02:00
|
|
|
|
(define (link-or-copy source target)
|
|
|
|
|
"Attempt to make TARGET a hard link to SOURCE; if it fails, fall back to
|
|
|
|
|
copy SOURCE to TARGET."
|
|
|
|
|
(catch 'system-error
|
|
|
|
|
(lambda ()
|
|
|
|
|
(link source target))
|
|
|
|
|
(lambda args
|
|
|
|
|
;; Perhaps SOURCE and TARGET live in a different file system, so copy
|
|
|
|
|
;; SOURCE.
|
|
|
|
|
(copy-file source target))))
|
|
|
|
|
|
2014-04-30 22:17:56 +02:00
|
|
|
|
(define (activate-setuid-programs programs)
|
|
|
|
|
"Turn PROGRAMS, a list of file names, into setuid programs stored under
|
|
|
|
|
%SETUID-DIRECTORY."
|
|
|
|
|
(define (make-setuid-program prog)
|
|
|
|
|
(let ((target (string-append %setuid-directory
|
|
|
|
|
"/" (basename prog))))
|
2014-09-11 21:25:58 +02:00
|
|
|
|
(link-or-copy prog target)
|
2014-04-30 22:17:56 +02:00
|
|
|
|
(chown target 0 0)
|
|
|
|
|
(chmod target #o6555)))
|
|
|
|
|
|
|
|
|
|
(format #t "setting up setuid programs in '~a'...~%"
|
|
|
|
|
%setuid-directory)
|
|
|
|
|
(if (file-exists? %setuid-directory)
|
2014-05-04 00:18:46 +02:00
|
|
|
|
(for-each (compose delete-file
|
|
|
|
|
(cut string-append %setuid-directory "/" <>))
|
2014-04-30 22:17:56 +02:00
|
|
|
|
(scandir %setuid-directory
|
|
|
|
|
(lambda (file)
|
|
|
|
|
(not (member file '("." ".."))))
|
|
|
|
|
string<?))
|
|
|
|
|
(mkdir-p %setuid-directory))
|
|
|
|
|
|
|
|
|
|
(for-each make-setuid-program programs))
|
|
|
|
|
|
2014-09-11 22:18:52 +02:00
|
|
|
|
(define (activate-/bin/sh shell)
|
|
|
|
|
"Change /bin/sh to point to SHELL."
|
|
|
|
|
(symlink shell "/bin/sh.new")
|
|
|
|
|
(rename-file "/bin/sh.new" "/bin/sh"))
|
|
|
|
|
|
2014-11-02 23:06:17 +01:00
|
|
|
|
(define (activate-modprobe modprobe)
|
|
|
|
|
"Tell the kernel to use MODPROBE to load modules."
|
|
|
|
|
(call-with-output-file "/proc/sys/kernel/modprobe"
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(display modprobe port))))
|
|
|
|
|
|
2014-11-11 22:42:15 +01:00
|
|
|
|
(define (activate-firmware directory)
|
|
|
|
|
"Tell the kernel to look for device firmware under DIRECTORY. This
|
|
|
|
|
mechanism bypasses udev: it allows Linux to handle firmware loading directly
|
|
|
|
|
by itself, without having to resort to a \"user helper\"."
|
|
|
|
|
(call-with-output-file "/sys/module/firmware_class/parameters/path"
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(display directory port))))
|
2015-04-12 15:33:42 +02:00
|
|
|
|
|
|
|
|
|
(define (activate-ptrace-attach)
|
|
|
|
|
"Allow users to PTRACE_ATTACH their own processes.
|
|
|
|
|
|
|
|
|
|
This works around a regression introduced in the default \"security\" policy
|
|
|
|
|
found in Linux 3.4 onward that prevents users from attaching to their own
|
|
|
|
|
processes--see Yama.txt in the Linux source tree for the rationale. This
|
|
|
|
|
sounds like an unacceptable restriction for little or no security
|
|
|
|
|
improvement."
|
2015-05-09 18:57:36 +02:00
|
|
|
|
(let ((file "/proc/sys/kernel/yama/ptrace_scope"))
|
|
|
|
|
(when (file-exists? file)
|
|
|
|
|
(call-with-output-file file
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(display 0 port))))))
|
2014-11-11 22:42:15 +01:00
|
|
|
|
|
|
|
|
|
|
2014-05-17 17:39:30 +02:00
|
|
|
|
(define %current-system
|
|
|
|
|
;; The system that is current (a symlink.) This is not necessarily the same
|
2014-05-24 15:51:57 +02:00
|
|
|
|
;; as the system we booted (aka. /run/booted-system) because we can re-build
|
|
|
|
|
;; a new system configuration and activate it, without rebooting.
|
2014-05-17 17:39:30 +02:00
|
|
|
|
"/run/current-system")
|
|
|
|
|
|
|
|
|
|
(define (boot-time-system)
|
|
|
|
|
"Return the '--system' argument passed on the kernel command line."
|
|
|
|
|
(find-long-option "--system" (linux-command-line)))
|
|
|
|
|
|
2014-09-12 17:41:06 +02:00
|
|
|
|
(define* (activate-current-system
|
|
|
|
|
#:optional (system (or (getenv "GUIX_NEW_SYSTEM")
|
|
|
|
|
(boot-time-system))))
|
2014-05-24 15:51:57 +02:00
|
|
|
|
"Atomically make SYSTEM the current system."
|
2014-09-12 17:41:06 +02:00
|
|
|
|
;; The 'GUIX_NEW_SYSTEM' environment variable is used as a way for 'guix
|
|
|
|
|
;; system reconfigure' to pass the file name of the new system.
|
|
|
|
|
|
2014-05-17 17:39:30 +02:00
|
|
|
|
(format #t "making '~a' the current system...~%" system)
|
|
|
|
|
|
|
|
|
|
;; Atomically make SYSTEM current.
|
|
|
|
|
(let ((new (string-append %current-system ".new")))
|
|
|
|
|
(symlink system new)
|
|
|
|
|
(rename-file new %current-system)))
|
|
|
|
|
|
2014-04-30 15:44:59 +02:00
|
|
|
|
;;; activation.scm ends here
|