guix system: 'docker-image' honors '--network'.
[jackhill/guix/guix.git] / gnu / system / pam.scm
index 4546c1a..85f7551 100644 (file)
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2019 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -50,6 +50,9 @@
             unix-pam-service
             base-pam-services
 
+            session-environment-service
+            session-environment-service-type
+
             pam-root-service-type
             pam-root-service))
 
@@ -204,34 +207,47 @@ dumped in /etc/pam.d/NAME, where NAME is the name of SERVICE."
         (env  (pam-entry ; to honor /etc/environment.
                (control "required")
                (module "pam_env.so"))))
-    (lambda* (name #:key allow-empty-passwords? motd)
+    (lambda* (name #:key allow-empty-passwords? (allow-root? #f) motd
+                   login-uid?)
       "Return a standard Unix-style PAM service for NAME.  When
-ALLOW-EMPTY-PASSWORDS? is true, allow empty passwords.  When MOTD is true, it
-should be a file-like object used as the message-of-the-day."
+ALLOW-EMPTY-PASSWORDS? is true, allow empty passwords.  When ALLOW-ROOT? is
+true, allow root to run the command without authentication.  When MOTD is
+true, it should be a file-like object used as the message-of-the-day.
+When LOGIN-UID? is true, require the 'pam_loginuid' module; that module sets
+/proc/self/loginuid, which the libc 'getlogin' function relies on."
       ;; See <http://www.linux-pam.org/Linux-PAM-html/sag-configuration-example.html>.
-      (let ((name* name))
-        (pam-service
-         (name name*)
-         (account (list unix))
-         (auth (list (if allow-empty-passwords?
-                         (pam-entry
-                          (control "required")
-                          (module "pam_unix.so")
-                          (arguments '("nullok")))
-                         unix)))
-         (password (list (pam-entry
-                          (control "required")
-                          (module "pam_unix.so")
-                          ;; Store SHA-512 encrypted passwords in /etc/shadow.
-                          (arguments '("sha512" "shadow")))))
-         (session (if motd
-                      (list env unix
-                            (pam-entry
-                             (control "optional")
-                             (module "pam_motd.so")
-                             (arguments
-                              (list #~(string-append "motd=" #$motd)))))
-                      (list env unix))))))))
+      (pam-service
+       (name name)
+       (account (list unix))
+       (auth (append (if allow-root?
+                         (list (pam-entry
+                                (control "sufficient")
+                                (module "pam_rootok.so")))
+                         '())
+                     (list (if allow-empty-passwords?
+                               (pam-entry
+                                (control "required")
+                                (module "pam_unix.so")
+                                (arguments '("nullok")))
+                               unix))))
+       (password (list (pam-entry
+                        (control "required")
+                        (module "pam_unix.so")
+                        ;; Store SHA-512 encrypted passwords in /etc/shadow.
+                        (arguments '("sha512" "shadow")))))
+       (session `(,@(if motd
+                        (list (pam-entry
+                               (control "optional")
+                               (module "pam_motd.so")
+                               (arguments
+                                (list #~(string-append "motd=" #$motd)))))
+                        '())
+                  ,@(if login-uid?
+                        (list (pam-entry       ;to fill in /proc/self/loginuid
+                               (control "required")
+                               (module "pam_loginuid.so")))
+                        '())
+                  ,env ,unix))))))
 
 (define (rootok-pam-service command)
   "Return a PAM service for COMMAND such that 'root' does not need to
@@ -256,7 +272,12 @@ authenticate to run COMMAND."
           ;; These programs are setuid-root.
           (map (cut unix-pam-service <>
                     #:allow-empty-passwords? allow-empty-passwords?)
-               '("su" "passwd" "sudo"))
+               '("passwd" "sudo"))
+          ;; This is setuid-root, as well.  Allow root to run "su" without
+          ;; authenticating.
+          (list (unix-pam-service "su"
+                                  #:allow-empty-passwords? allow-empty-passwords?
+                                  #:allow-root? #t))
 
           ;; These programs are not setuid-root, and we want root to be able
           ;; to run them without having to authenticate (notably because
@@ -266,6 +287,48 @@ authenticate to run COMMAND."
                  "groupadd" "groupdel" "groupmod"))))
 
 \f
+;;;
+;;; System-wide environment variables.
+;;;
+
+(define (environment-variables->environment-file vars)
+  "Return a file for pam_env(8) that contains environment variables VARS."
+  (apply mixed-text-file "environment"
+         (append-map (match-lambda
+                       ((key . value)
+                        (list key "=" value "\n")))
+                     vars)))
+
+(define session-environment-service-type
+  (service-type
+   (name 'session-environment)
+   (extensions
+    (list (service-extension
+           etc-service-type
+           (lambda (vars)
+             (list `("environment"
+                     ,(environment-variables->environment-file vars)))))))
+   (compose concatenate)
+   (extend append)
+   (description
+    "Populate @file{/etc/environment}, which is honored by @code{pam_env},
+with the specified environment variables.  The value of this service is a list
+of name/value pairs for environments variables, such as:
+
+@example
+'((\"TZ\" . \"Canada/Pacific\"))
+@end example\n")))
+
+(define (session-environment-service vars)
+  "Return a service that builds the @file{/etc/environment}, which can be read
+by PAM-aware applications to set environment variables for sessions.
+
+VARS should be an association list in which both the keys and the values are
+strings or string-valued gexps."
+  (service session-environment-service-type vars))
+
+
+\f
 ;;;
 ;;; PAM root service.
 ;;;