@@ -503,9 +503,6 @@ (define (nslcd-shepherd-service config)
(define (pam-ldap-pam-service config)
"Return a PAM service for LDAP authentication."
- (define pam-ldap-module
- (file-append (nslcd-configuration-nss-pam-ldapd config)
- "/lib/security/pam_ldap.so"))
(pam-extension
(transformer
(lambda (pam)
@@ -514,7 +511,11 @@ (define (pam-ldap-pam-service config)
(let ((sufficient
(pam-entry
(control "sufficient")
- (module pam-ldap-module))))
+ (module "pam_ldap.so")
+ (foreign-library-path
+ (list
+ (file-append (nslcd-configuration-nss-pam-ldapd config)
+ "/lib/security"))))))
(pam-service
(inherit pam)
(auth (cons sufficient (pam-service-auth pam)))
@@ -61,8 +61,8 @@ (define-module (gnu services base)
#:use-module (gnu packages admin)
#:use-module ((gnu packages linux)
#:select (alsa-utils btrfs-progs crda eudev
- e2fsprogs f2fs-tools fuse gpm kbd lvm2 rng-tools
- util-linux xfsprogs))
+ e2fsprogs f2fs-tools fuse gpm kbd linux-pam
+ lvm2 rng-tools util-linux xfsprogs))
#:use-module (gnu packages bash)
#:use-module ((gnu packages base)
#:select (coreutils glibc glibc/hurd
@@ -1731,7 +1731,10 @@ (define pam-limits-service-type
(control "required")
(module "pam_limits.so")
(arguments
- (list #~(string-append "conf=" #$limits-file))))))
+ (list #~(string-append "conf=" #$limits-file)))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(if (member (pam-service-name pam)
'("login" "greetd" "su" "slim" "gdm-password"
"sddm" "lightdm" "sudo" "sshd"))
@@ -4032,8 +4035,11 @@ (define (greetd-pam-service config)
(define optional-pam-mount
(pam-entry
(control "optional")
- (module (file-append greetd-pam-mount "/lib/security/pam_mount.so"))
- (arguments '("disable_interactive"))))
+ (module "pam_mount.so")
+ (arguments '("disable_interactive"))
+ (foreign-library-path
+ (list
+ (file-append greetd-pam-mount "/lib/security")))))
(list
(unix-pam-service "greetd"
@@ -1494,8 +1494,10 @@ (define (pam-extension-procedure config)
(define pam-elogind
(pam-entry
(control "required")
- (module (file-append (elogind-configuration-elogind config)
- "/lib/security/pam_elogind.so"))))
+ (module "pam_elogind.so")
+ (foreign-library-path
+ (list
+ (file-append (elogind-configuration-elogind config) "/lib/security")))))
(list (pam-extension
(transformer
@@ -1712,9 +1714,11 @@ (define (pam-gnome-keyring config)
(define (%pam-keyring-entry . arguments)
(pam-entry
(control "optional")
- (module (file-append (gnome-keyring-package config)
- "/lib/security/pam_gnome_keyring.so"))
- (arguments arguments)))
+ (module ("pam_gnome_keyring.so"))
+ (arguments arguments)
+ (foreign-library-path
+ (list
+ (file-append (gnome-keyring-package config) "/lib/security")))))
(list
(pam-extension
@@ -431,18 +431,18 @@ (define (pam-krb5-pam-service config)
(pam-extension
(transformer
(lambda (pam)
- (define pam-krb5-module
- (file-append (pam-krb5-configuration-pam-krb5 config)
- "/lib/security/pam_krb5.so"))
-
(let ((pam-krb5-sufficient
(pam-entry
(control "sufficient")
- (module pam-krb5-module)
+ (module "pam_krb5.so")
(arguments
(list
(format #f "minimum_uid=~a"
- (pam-krb5-configuration-minimum-uid config)))))))
+ (pam-krb5-configuration-minimum-uid config))))
+ (foreign-library-path
+ (list
+ (file-append (pam-krb5-configuration-pam-krb5 config)
+ "/lib/security"))))))
(pam-service
(inherit pam)
(auth (cons* pam-krb5-sufficient
@@ -24,6 +24,7 @@ (define-module (gnu services lightdm)
#:use-module (gnu packages display-managers)
#:use-module (gnu packages freedesktop)
#:use-module (gnu packages gnome)
+ #:use-module ((gnu packages linux) #:select (linux-pam))
#:use-module (gnu packages vnc)
#:use-module (gnu packages xorg)
#:use-module (gnu services configuration)
@@ -546,15 +547,35 @@ (define (lightdm-greeter-pam-service)
(name "lightdm-greeter")
(auth (list
;; Load environment from /etc/environment and ~/.pam_environment.
- (pam-entry (control "required") (module "pam_env.so"))
+ (pam-entry (control "required")
+ (module "pam_env.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
;; Always let the greeter start without authentication.
- (pam-entry (control "required") (module "pam_permit.so"))))
+ (pam-entry (control "required")
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; No action required for account management
- (account (list (pam-entry (control "required") (module "pam_permit.so"))))
+ (account (list (pam-entry (control "required")
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; Prohibit changing password.
- (password (list (pam-entry (control "required") (module "pam_deny.so"))))
+ (password (list (pam-entry (control "required")
+ (module "pam_deny.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; Setup session.
- (session (list (pam-entry (control "required") (module "pam_unix.so"))))))
+ (session (list (pam-entry (control "required")
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))))
(define (lightdm-autologin-pam-service)
"Return a PAM service for @command{lightdm-autologin}}."
@@ -563,17 +584,41 @@ (define (lightdm-autologin-pam-service)
(auth
(list
;; Block login if user is globally disabled.
- (pam-entry (control "required") (module "pam_nologin.so"))
- (pam-entry (control "required") (module "pam_succeed_if.so")
- (arguments (list "uid >= 1000")))
+ (pam-entry (control "required")
+ (module "pam_nologin.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
+ (pam-entry (control "required")
+ (module "pam_succeed_if.so")
+ (arguments (list "uid >= 1000"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
;; Allow access without authentication.
- (pam-entry (control "required") (module "pam_permit.so"))))
+ (pam-entry (control "required")
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; Stop autologin if account requires action.
- (account (list (pam-entry (control "required") (module "pam_unix.so"))))
+ (account (list (pam-entry (control "required")
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; Prohibit changing password.
- (password (list (pam-entry (control "required") (module "pam_deny.so"))))
+ (password (list (pam-entry (control "required")
+ (module "pam_deny.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
;; Setup session.
- (session (list (pam-entry (control "required") (module "pam_unix.so"))))))
+ (session (list (pam-entry (control "required")
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))))
(define (lightdm-pam-services config)
(list (lightdm-pam-service config)
@@ -94,7 +94,10 @@ (define (pam-mount-pam-service config)
(define optional-pam-mount
(pam-entry
(control "optional")
- (module (file-append pam-mount "/lib/security/pam_mount.so"))))
+ (module "pam_mount.so")
+ (foreign-library-path
+ (list
+ (file-append pam-mount "/lib/security")))))
(list
(pam-extension
(transformer
@@ -24,6 +24,7 @@ (define-module (gnu services sddm)
#:use-module (gnu packages admin)
#:use-module (gnu packages display-managers)
#:use-module (gnu packages freedesktop)
+ #:use-module ((gnu packages linux) #:select (linux-pam))
#:use-module (gnu packages xorg)
#:use-module (gnu services)
#:use-module (gnu services shepherd)
@@ -206,40 +207,61 @@ (define (sddm-pam-service config)
(list
(pam-entry
(control "requisite")
- (module "pam_nologin.so"))
+ (module "pam_nologin.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
(pam-entry
(control "required")
- (module "pam_env.so"))
+ (module "pam_env.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
(pam-entry
(control "required")
(module "pam_succeed_if.so")
(arguments (list (string-append "uid >= "
(number->string (sddm-configuration-minimum-uid config)))
- "quiet")))
+ "quiet"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
;; should be factored out into system-auth
(pam-entry
(control "required")
- (module "pam_unix.so"))))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(account
(list
;; should be factored out into system-account
(pam-entry
(control "required")
- (module "pam_unix.so"))))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(password
(list
;; should be factored out into system-password
(pam-entry
(control "required")
(module "pam_unix.so")
- (arguments (list "sha512" "shadow" "try_first_pass")))))
+ (arguments (list "sha512" "shadow" "try_first_pass"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(session
(list
;; lfs has a required pam_limits.so
;; should be factored out into system-session
(pam-entry
(control "required")
- (module "pam_unix.so"))))))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))))
(define (sddm-greeter-pam-service)
"Return a PAM service for @command{sddm-greeter}."
@@ -250,29 +272,44 @@ (define (sddm-greeter-pam-service)
;; Load environment from /etc/environment and ~/.pam_environment
(pam-entry
(control "required")
- (module "pam_env.so"))
+ (module "pam_env.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
;; Always let the greeter start without authentication
(pam-entry
(control "required")
- (module "pam_permit.so"))))
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(account
(list
;; No action required for account management
(pam-entry
(control "required")
- (module "pam_permit.so"))))
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(password
(list
;; Can't change password
(pam-entry
(control "required")
- (module "pam_deny.so"))))
+ (module "pam_deny.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(session
(list
;; Setup session
(pam-entry
(control "required")
- (module "pam_unix.so"))))))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))))
(define (sddm-autologin-pam-service config)
"Return a PAM service for @command{sddm-autologin}"
@@ -282,31 +319,37 @@ (define (sddm-autologin-pam-service config)
(list
(pam-entry
(control "requisite")
- (module "pam_nologin.so"))
+ (module "pam_nologin.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
(pam-entry
(control "required")
(module "pam_succeed_if.so")
(arguments (list (string-append "uid >= "
(number->string (sddm-configuration-minimum-uid config)))
- "quiet")))
+ "quiet"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
(pam-entry
(control "required")
- (module "pam_permit.so"))))
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(account
- (list
- (pam-entry
- (control "include")
- (module "sddm"))))
+ (pam-service-account (sddm-pam-service config)))
(password
(list
(pam-entry
(control "required")
- (module "pam_deny.so"))))
+ (module "pam_deny.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(session
- (list
- (pam-entry
- (control "include")
- (module "sddm"))))))
+ (pam-service-session (sddm-pam-service config)))))
(define (sddm-pam-services config)
(list (sddm-pam-service config)
@@ -1236,16 +1236,25 @@ (define (gdm-pam-service config)
#:login-uid? #t))
(auth (list (pam-entry
(control "optional")
- (module (file-append (gdm-configuration-gdm config)
- "/lib/security/pam_gdm.so")))
+ (module "pam_gdm.so")
+ (foreign-library-path
+ (list
+ (file-append (gdm-configuration-gdm config)
+ "/lib/security/"))))
(pam-entry
(control "sufficient")
- (module "pam_permit.so")))))
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))))
(pam-service
(inherit (unix-pam-service "gdm-launch-environment"))
(auth (list (pam-entry
(control "required")
- (module "pam_permit.so")))))
+ (module "pam_permit.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))))
(unix-pam-service "gdm-password"
#:login-uid? #t
#:allow-empty-passwords?
@@ -32,7 +32,9 @@ (define-module (gnu system pam)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module ((guix utils) #:select (%current-system))
+ #:use-module (gnu packages guile)
#:use-module (gnu packages linux)
+ #:use-module (gnu packages mes)
#:export (pam-service
pam-service?
pam-service-name
@@ -46,6 +48,8 @@ (define-module (gnu system pam)
pam-entry-control
pam-entry-module
pam-entry-arguments
+ pam-entry-guile-inputs
+ pam-entry-foreign-library-path
pam-limits-entry
pam-limits-entry?
@@ -95,10 +99,16 @@ (define-record-type* <pam-service> pam-service
(define-record-type* <pam-entry> pam-entry
make-pam-entry
pam-entry?
- (control pam-entry-control) ; string
+ (control pam-entry-control) ; string, symbol or g-expression
(module pam-entry-module) ; file name
(arguments pam-entry-arguments ; list of string-valued g-expressions
- (default '())))
+ (default '()))
+ (guile-inputs pam-entry-guile-inputs ; list of package variables
+ (default '()))
+ (foreign-library-path pam-entry-foreign-library-path ; list of file-like folders
+ ;; courtesy for historical usage
+ (default (list
+ (file-append linux-pam "/lib/security")))))
;; PAM limits entries are used by the pam_limits PAM module to set or override
;; limits on system resources for user sessions. The format is specified
@@ -153,35 +163,80 @@ (define (pam-limits-entry->string entry)
(number->string value))))
" "))))
-(define (pam-service->configuration service)
+(define (pam-service->configuration service shared-object environment-file pamda-file)
"Return the derivation building the configuration file for SERVICE, to be
dumped in /etc/pam.d/NAME, where NAME is the name of SERVICE."
- (define (entry->gexp type entry)
- (match entry
- (($ <pam-entry> control module (arguments ...))
- #~(format #t "~a ~a ~a ~a~%"
- #$type #$control #$module
- (string-join (list #$@arguments))))))
-
- (match service
- (($ <pam-service> name account auth password session)
- (define builder
- #~(begin
- (with-output-to-file #$output
- (lambda ()
- #$@(append (map (cut entry->gexp "account" <>) account)
- (map (cut entry->gexp "auth" <>) auth)
- (map (cut entry->gexp "password" <>) password)
- (map (cut entry->gexp "session" <>) session))
- #t))))
-
- (computed-file name builder))))
-
-(define (pam-services->directory services)
+ (mixed-text-file (pam-service-name service)
+ "account required " shared-object " " environment-file " " pamda-file "\n"
+ "auth required " shared-object " " environment-file " " pamda-file "\n"
+ "password required " shared-object " " environment-file " " pamda-file "\n"
+ "session required " shared-object " " environment-file " " pamda-file "\n"))
+
+(define (intersperse a xs)
+ (if (null? xs)
+ '()
+ [cons (car xs)
+ (if (null? (cdr xs))
+ (cdr xs)
+ (cons a (intersperse a (cdr xs))))]))
+
+;; should include locale, but keeping effects of pam_env.so
+(define* (make-environment-file #:key
+ (guile-auto-compile? #f)
+ (guile-extensions-path '())
+ (guile-install-locale? #f)
+ (guile-jit-log-level 0)
+ (guile-jit-pause-when-stopping? #f)
+ (guile-jit-stop-after -1)
+ (guile-jit-threshold 1000)
+ (guile-load-compiled-path '())
+ (guile-load-path '())
+ (guile-warn-deprecated "yes")
+ (ld-library-path '())
+ (ltdl-library-path '()))
+ (let* ((lines `(("GUILE_AUTO_COMPILE=" ,(if guile-auto-compile? "1" "0"))
+ ("GUILE_EXTENSIONS_PATH=" ,@(intersperse ":" guile-extensions-path))
+ ("GUILE_INSTALL_LOCALE=" ,(if guile-install-locale? "1" "0"))
+ ("GUILE_JIT_LOG=" ,(number->string guile-jit-log-level))
+ ("GUILE_JIT_PAUSE_WHEN_STOPPING=" ,(if guile-jit-pause-when-stopping? "1" "0"))
+ ("GUILE_JIT_STOP_AFTER=" ,(number->string guile-jit-stop-after))
+ ("GUILE_JIT_THRESHOLD=" ,(number->string guile-jit-threshold))
+ ("GUILE_LOAD_COMPILED_PATH=" ,@(intersperse ":" guile-load-compiled-path))
+ ("GUILE_LOAD_PATH=" ,@(intersperse ":" guile-load-path))
+ ("GUILE_WARN_DEPRECATED=" ,guile-warn-deprecated)
+ ("LD_LIBRARY_PATH=" ,@(intersperse ":" ld-library-path))
+ ("LTDL_LIBRARY_PATH=" ,@(intersperse ":" ltdl-library-path))))
+ (terminated (map (lambda (line)
+ (append line '("\0")))
+ lines))
+ (flattened (fold (lambda (right left)
+ (append left right))
+ '()
+ terminated)))
+ (apply mixed-text-file "guile-pam-environment" flattened)))
+
+(define (pam-services->directory shared-object
+ guile-inputs
+ foreign-library-path
+ folder
+ services)
"Return the derivation to build the configuration directory to be used as
/etc/pam.d for SERVICES."
- (let ((names (map pam-service-name services))
- (files (map pam-service->configuration services)))
+ (let* ((names (map pam-service-name services))
+ (load-path (map (lambda (package)
+ (file-append package "/share/guile/site/3.0"))
+ guile-inputs))
+ (load-compiled-path (map (lambda (package)
+ (file-append package "/lib/guile/3.0/site-ccache"))
+ guile-inputs))
+ (environment-file (make-environment-file #:guile-extensions-path foreign-library-path
+ #:ld-library-path foreign-library-path
+ #:guile-load-path load-path
+ #:guile-load-compiled-path load-compiled-path))
+ (pamda-file (make-pam-stack folder services))
+ (files (map (cut pam-service->configuration <>
+ shared-object environment-file pamda-file)
+ services)))
(define builder
#~(begin
(use-modules (ice-9 match)
@@ -198,14 +253,17 @@ (define (pam-services->directory services)
;; instead. See <http://bugs.gnu.org/20037>.
(delete-duplicates '#$(zip names files)))))
- (computed-file "pam.d" builder)))
+ (computed-file folder builder)))
(define %pam-other-services
;; The "other" PAM configuration, which denies everything (see
;; <http://www.linux-pam.org/Linux-PAM-html/sag-configuration-example.html>.)
(let ((deny (pam-entry
(control "required")
- (module "pam_deny.so"))))
+ (module "pam_deny.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(pam-service
(name "other")
(account (list deny))
@@ -216,12 +274,18 @@ (define %pam-other-services
(define unix-pam-service
(let ((unix (pam-entry
(control "required")
- (module "pam_unix.so")))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))
(env (pam-entry ; to honor /etc/environment.
(control "required")
- (module "pam_env.so"))))
+ (module "pam_env.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(lambda* (name #:key allow-empty-passwords? allow-root? motd
- login-uid? gnupg?)
+ login-uid? gnupg?)
"Return a standard Unix-style PAM service for NAME. When
ALLOW-EMPTY-PASSWORDS? is true, allow empty passwords. When ALLOW-ROOT? is
true, allow root to run the command without authentication. When MOTD is
@@ -237,40 +301,61 @@ (define unix-pam-service
(auth (append (if allow-root?
(list (pam-entry
(control "sufficient")
- (module "pam_rootok.so")))
+ (module "pam_rootok.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))
'())
(list (if allow-empty-passwords?
(pam-entry
(control "required")
(module "pam_unix.so")
- (arguments '("nullok")))
+ (arguments '("nullok"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))
unix))
(if gnupg?
(list (pam-entry
(control "required")
- (module (file-append pam-gnupg "/lib/security/pam_gnupg.so"))))
+ (module "pam_gnupg.so")
+ (foreign-library-path
+ (list
+ (file-append pam-gnupg "/lib/security")))))
'())))
(password (list (pam-entry
(control "required")
(module "pam_unix.so")
;; Store SHA-512 encrypted passwords in /etc/shadow.
- (arguments '("sha512" "shadow")))))
+ (arguments '("sha512" "shadow"))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(session `(,@(if motd
(list (pam-entry
(control "optional")
(module "pam_motd.so")
(arguments
- (list #~(string-append "motd=" #$motd)))))
+ (list #~(string-append "motd=" #$motd)))
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))
'())
,@(if login-uid?
(list (pam-entry ;to fill in /proc/self/loginuid
(control "required")
- (module "pam_loginuid.so")))
+ (module "pam_loginuid.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security")))))
'())
,@(if gnupg?
(list (pam-entry
(control "required")
- (module (file-append pam-gnupg "/lib/security/pam_gnupg.so"))))
+ (module "pam_gnupg.so")
+ (foreign-library-path
+ (list
+ (file-append pam-gnupg "/lib/security")))))
'())
,env ,unix))))))
@@ -279,13 +364,19 @@ (define (rootok-pam-service command)
authenticate to run COMMAND."
(let ((unix (pam-entry
(control "required")
- (module "pam_unix.so"))))
+ (module "pam_unix.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(pam-service
(name command)
(account (list unix))
(auth (list (pam-entry
(control "sufficient")
- (module "pam_rootok.so"))))
+ (module "pam_rootok.so")
+ (foreign-library-path
+ (list
+ (file-append linux-pam "/lib/security"))))))
(password (list unix))
(session (list unix)))))
@@ -377,21 +468,114 @@ (define-record-type* <pam-configuration>
(services pam-configuration-services)
;list of procedures <pam-entry> -> <pam-entry>
(transformers pam-configuration-transformers)
+ ;; file-like shared module
+ (shared-object pam-configuration-shared-object)
+ ;; list of package variables
+ (guile-inputs pam-configuration-guile-inputs)
+ ;; list of file-like folders
+ (foreign-library-path pam-configuration-foreign-library-path)
;list of symbols
(shepherd-requirements pam-configuration-shepherd-requirements))
+(define (make-pam-stack folder services)
+ (define* (entry->gate entry
+ #:key
+ only-actions
+ only-services)
+ (match entry
+ (($ <pam-entry> control module (options ...))
+ ;; adapted from (pam legacy configuration)
+ (cond
+ ((string=? "include" control)
+ (error "PAM include not implemented; send list of <pam-entry> instead"
+ control module options entry))
+ ((string=? "substack" control)
+ ;; this probably differs a little bit from Linux-PAM
+ #~(gate required (stack-pamda
+ (configuration-file->gates #$folder #$module
+ #:only-actions '#$only-actions
+ #:only-services '#$only-services))
+ #:only-actions '#$only-actions
+ #:only-services '#$only-services))
+ (else
+ #~(gate (control-string->plan #$control)
+ (shared-object-or-pamda #$module)
+ #:options (list #$@options)
+ #:only-actions '#$only-actions
+ #:only-services '#$only-services))))))
+
+ (define (service->gates service)
+ (match service
+ (($ <pam-service> name account auth password session)
+ (append (map (cut entry->gate <>
+ #:only-actions '(pam_sm_acct_mgmt)
+ #:only-services (list name))
+ account)
+ (map (cut entry->gate <>
+ #:only-actions '(pam_sm_authenticate
+ pam_sm_setcred)
+ #:only-services (list name))
+ auth)
+ (map (cut entry->gate <>
+ #:only-actions '(pam_sm_chauthtok)
+ #:only-services (list name))
+ password)
+ (map (cut entry->gate <>
+ #:only-actions '(pam_sm_open_session
+ pam_sm_close_session)
+ #:only-services (list name))
+ session)))))
+
+ (let* ((gates (append-map service->gates services)))
+ (scheme-file
+ "guile-pam-stack.scm"
+ #~(begin
+ (use-modules (pam stack)
+ (pam legacy configuration)
+ (pam legacy module)
+ (pam legacy stack))
+ (stack-pamda (list #$@gates))))))
+
(define (/etc-entry config)
"Return the /etc/pam.d entry corresponding to CONFIG."
+ (define (service->pam-entries service)
+ (match service
+ (($ <pam-service> name account auth password session)
+ (append account auth password session))))
(match config
- (($ <pam-configuration> services transformers shepherd-requirements)
- (let ((services (map (apply compose identity transformers)
- services)))
- `(("pam.d" ,(pam-services->directory services)))))))
+ (($ <pam-configuration> services
+ transformers
+ shared-object
+ guile-inputs
+ foreign-library-path
+ shepherd-requirements)
+ (let* ((services (map (apply compose identity transformers)
+ services))
+ (all-entries (append-map service->pam-entries
+ services))
+ (combined-inputs (delete-duplicates
+ (append guile-inputs
+ (append-map pam-entry-guile-inputs
+ all-entries))))
+ (combined-library-path (delete-duplicates
+ (append foreign-library-path
+ (append-map pam-entry-foreign-library-path
+ all-entries)))))
+ `(("pam.d" ,(pam-services->directory shared-object
+ combined-inputs
+ combined-library-path
+ "pam.d"
+ services)))))))
(define (pam-shepherd-service config)
"Return the PAM synchronization shepherd service corresponding to CONFIG."
(match config
- (($ <pam-configuration> services transformers shepherd-requirements)
+ (($ <pam-configuration> services
+ transformers
+ shared-object
+ guile-inputs
+ foreign-library-path
+ shepherd-requirements)
(list (shepherd-service
(documentation "Synchronization point for services that need to be
started for PAM to work.")
@@ -420,6 +604,9 @@ (define (extend-configuration initial extensions)
services))
(transformers (append (pam-configuration-transformers initial)
(map pam-extension-transformer pam-extensions)))
+ (shared-object (pam-configuration-shared-object initial))
+ (guile-inputs (pam-configuration-guile-inputs initial))
+ (foreign-library-path (pam-configuration-foreign-library-path initial))
(shepherd-requirements
(append (pam-configuration-shepherd-requirements initial)
(append-map pam-extension-shepherd-requirements pam-extensions))))))
@@ -445,8 +632,18 @@ (define pam-root-service-type
such as @command{login} or @command{sshd}, and specifies for instance how the
program may authenticate users or what it should do when opening a new
session.")))
-
-(define* (pam-root-service base #:key (transformers '()) (shepherd-requirements '()))
+(define* (pam-root-service base
+ #:key
+ (transformers '())
+ (shared-object
+ (file-append guile-pam "/lib/security/pam_guile.so"))
+ (guile-inputs
+ (list guile-3.0
+ guile-pam ;for (pam) and (ffi pam)
+ nyacc-2.01)) ;for (nyacc foreign cdata)
+ (foreign-library-path
+ (list (file-append linux-pam "/lib"))) ;for libpam.so
+ (shepherd-requirements '()))
"The \"root\" PAM service, which collects <pam-service> instance and turns
them into a /etc/pam.d directory, including the <pam-service> listed in BASE.
TRANSFORM is a procedure that takes a <pam-service> and returns a
@@ -455,6 +652,9 @@ (define* (pam-root-service base #:key (transformers '()) (shepherd-requirements
(service pam-root-service-type
(pam-configuration (services base)
(transformers transformers)
+ (shared-object shared-object)
+ (guile-inputs guile-inputs)
+ (foreign-library-path foreign-library-path)
(shepherd-requirements shepherd-requirements))))