gnu: services: Fix the NFS service.
[jackhill/guix/guix.git] / gnu / services / authentication.scm
CommitLineData
7f93bbd5
DM
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2018 Danny Milosavljevic <dannym@scratchpost.org>
c16423f1 3;;; Copyright © 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
7f93bbd5
DM
4;;;
5;;; This file is part of GNU Guix.
6;;;
7;;; GNU Guix is free software; you can redistribute it and/or modify it
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
12;;; GNU Guix is distributed in the hope that it will be useful, but
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
812f6bd8 20(define-module (gnu services authentication)
7f93bbd5 21 #:use-module (gnu services)
c16423f1
RW
22 #:use-module (gnu services base)
23 #:use-module (gnu services configuration)
7f93bbd5 24 #:use-module (gnu services dbus)
c16423f1
RW
25 #:use-module (gnu services shepherd)
26 #:use-module (gnu system pam)
27 #:use-module (gnu system shadow)
28 #:use-module (gnu packages admin)
7f93bbd5 29 #:use-module (gnu packages freedesktop)
c16423f1 30 #:use-module (gnu packages openldap)
7f93bbd5
DM
31 #:use-module (guix gexp)
32 #:use-module (guix records)
c16423f1
RW
33 #:use-module (guix packages)
34 #:use-module (ice-9 match)
35 #:use-module (srfi srfi-1)
36 #:use-module (srfi srfi-26)
7f93bbd5
DM
37 #:export (fprintd-configuration
38 fprintd-configuration?
c16423f1
RW
39 fprintd-service-type
40
41 nslcd-configuration
42 nslcd-configuration?
43 nslcd-service-type))
7f93bbd5 44
dc019782
DM
45(define-configuration fprintd-configuration
46 (fprintd (package fprintd)
47 "The fprintd package"))
7f93bbd5 48
0682f084
DM
49(define (fprintd-dbus-service config)
50 (list (fprintd-configuration-fprintd config)))
51
7f93bbd5
DM
52(define fprintd-service-type
53 (service-type (name 'fprintd)
54 (extensions
55 (list (service-extension dbus-root-service-type
9374cbd1
DM
56 fprintd-dbus-service)
57 (service-extension polkit-service-type
0682f084
DM
58 fprintd-dbus-service)))
59 (default-value (fprintd-configuration))
7f93bbd5
DM
60 (description
61 "Run fprintd, a fingerprint management daemon.")))
c16423f1
RW
62
63\f
64;;;
65;;; NSS Pam LDAP service (nslcd)
66;;;
67
68(define (uglify-field-name name)
69 (match name
70 ('filters "filter")
71 ('maps "map")
72 (_ (string-map (match-lambda
73 (#\- #\_)
74 (chr chr))
75 (symbol->string name)))))
76
77(define (value->string val)
78 (cond
79 ((boolean? val)
80 (if val "on" "off"))
81 ((number? val)
82 (number->string val))
83 ((symbol? val)
84 (string-map (match-lambda
85 (#\- #\_)
86 (chr chr))
87 (symbol->string val)))
88 (else val)))
89
90(define (serialize-field field-name val)
91 (if (eq? field-name 'pam-services)
92 #t
93 (format #t "~a ~a\n"
94 (uglify-field-name field-name)
95 (value->string val))))
96
97(define serialize-string serialize-field)
98(define serialize-boolean serialize-field)
99(define serialize-number serialize-field)
100(define (serialize-list field-name val)
101 (map (cut serialize-field field-name <>) val))
102(define-maybe string)
103(define-maybe boolean)
104(define-maybe number)
105
106(define (ssl-option? val)
107 (or (boolean? val)
108 (eq? val 'start-tls)))
109(define serialize-ssl-option serialize-field)
110(define-maybe ssl-option)
111
112(define (tls-reqcert-option? val)
113 (member val '(never allow try demand hard)))
114(define serialize-tls-reqcert-option serialize-field)
115(define-maybe tls-reqcert-option)
116
117(define (deref-option? val)
118 (member val '(never searching finding always)))
119(define serialize-deref-option serialize-field)
120(define-maybe deref-option)
121
122(define (comma-separated-list-of-strings? val)
123 (and (list? val)
124 (every string? val)))
125(define (ignore-users-option? val)
126 (or (comma-separated-list-of-strings? val)
127 (eq? 'all-local val)))
128(define (serialize-ignore-users-option field-name val)
129 (serialize-field field-name (if (eq? 'all-local val)
130 val
131 (string-join val ","))))
132(define-maybe ignore-users-option)
133
134(define (log-option? val)
135 (let ((valid-scheme? (lambda (scheme)
136 (or (string? scheme)
137 (member scheme '(none syslog))))))
138 (match val
139 ((scheme level)
140 (and (valid-scheme? scheme)
141 (member level '(crit error warning notice info debug))))
142 ((scheme)
143 (valid-scheme? scheme)))))
144(define (serialize-log-option field-name val)
145 (serialize-field field-name
146 (string-join (map (cut format #f "~a" <>) val))))
147
148(define (valid-map? val)
149 "Is VAL a supported map name?"
150 (member val
151 '(alias aliases ether ethers group host hosts netgroup network networks
152 passwd protocol protocols rpc service services shadow)))
153
154(define (scope-option? val)
155 (let ((valid-scopes '(subtree onelevel base children)))
156 (match val
157 ((map-name scope)
158 (and (valid-map? map-name)
159 (member scope valid-scopes)))
160 ((scope)
161 (member scope valid-scopes)))))
162(define (serialize-scope-option field-name val)
163 (serialize-field field-name
164 (string-join (map (cut format #f "~a" <>) val))))
165
166(define (map-entry? val)
167 (match val
168 (((? valid-map? map-name)
169 (? string? attribute)
170 (? string? new-attribute)) #t)
171 (_ #f)))
172
173(define (list-of-map-entries? val)
174 (and (list? val)
175 (every map-entry? val)))
176
177(define (filter-entry? val)
178 (match val
179 (((? valid-map? map-name)
180 (? string? filter-expression)) #t)
181 (_ #f)))
182
183(define (list-of-filter-entries? val)
184 (and (list? val)
185 (every filter-entry? val)))
186
187(define (serialize-filter-entry field-name val)
188 (serialize-field 'filter
189 (match val
190 (((? valid-map? map-name)
191 (? string? filter-expression))
192 (string-append (symbol->string map-name)
193 " " filter-expression)))))
194
195(define (serialize-list-of-filter-entries field-name val)
196 (for-each (cut serialize-filter-entry field-name <>) val))
197
198(define (serialize-map-entry field-name val)
199 (serialize-field 'map
200 (match val
201 (((? valid-map? map-name)
202 (? string? attribute)
203 (? string? new-attribute))
204 (string-append (symbol->string map-name)
205 " " attribute
206 " " new-attribute)))))
207
208(define (serialize-list-of-map-entries field-name val)
209 (for-each (cut serialize-map-entry field-name <>) val))
210
211\f
212(define-configuration nslcd-configuration
213 (nss-pam-ldapd
214 (package nss-pam-ldapd)
215 "The NSS-PAM-LDAPD package to use.")
216
217 ;; Runtime options
218 (threads
219 (maybe-number 'disabled)
220 "The number of threads to start that can handle requests and perform LDAP
221queries. Each thread opens a separate connection to the LDAP server. The
222default is to start 5 threads.")
223 (uid
224 (string "nslcd")
225 "This specifies the user id with which the daemon should be run.")
226 (gid
227 (string "nslcd")
228 "This specifies the group id with which the daemon should be run.")
229 (log
230 (log-option '("/var/log/nslcd" info))
231 "This option controls the way logging is done via a list containing SCHEME
232and LEVEL. The SCHEME argument may either be the symbols \"none\" or
233\"syslog\", or an absolute file name. The LEVEL argument is optional and
234specifies the log level. The log level may be one of the following symbols:
235\"crit\", \"error\", \"warning\", \"notice\", \"info\" or \"debug\". All
236messages with the specified log level or higher are logged.")
237
238 ;; LDAP connection settings
239 (uri
240 (list '("ldap://localhost:389/"))
241 "The list of LDAP server URIs. Normally, only the first server will be
242used with the following servers as fall-back.")
243 (ldap-version
244 (maybe-string 'disabled)
245 "The version of the LDAP protocol to use. The default is to use the
246maximum version supported by the LDAP library.")
247 (binddn
248 (maybe-string 'disabled)
249 "Specifies the distinguished name with which to bind to the directory
250server for lookups. The default is to bind anonymously.")
251 (bindpw
252 (maybe-string 'disabled)
253 "Specifies the credentials with which to bind. This option is only
254applicable when used with binddn.")
255 (rootpwmoddn
256 (maybe-string 'disabled)
257 "Specifies the distinguished name to use when the root user tries to modify
258a user's password using the PAM module.")
259 (rootpwmodpw
260 (maybe-string 'disabled)
261 "Specifies the credentials with which to bind if the root user tries to
262change a user's password. This option is only applicable when used with
263rootpwmoddn")
264
265 ;; SASL authentication options
266 (sasl-mech
267 (maybe-string 'disabled)
268 "Specifies the SASL mechanism to be used when performing SASL
269authentication.")
270 (sasl-realm
271 (maybe-string 'disabled)
272 "Specifies the SASL realm to be used when performing SASL authentication.")
273 (sasl-authcid
274 (maybe-string 'disabled)
275 "Specifies the authentication identity to be used when performing SASL
276authentication.")
277 (sasl-authzid
278 (maybe-string 'disabled)
279 "Specifies the authorization identity to be used when performing SASL
280authentication.")
281 (sasl-canonicalize?
282 (maybe-boolean 'disabled)
283 "Determines whether the LDAP server host name should be canonicalised. If
284this is enabled the LDAP library will do a reverse host name lookup. By
285default, it is left up to the LDAP library whether this check is performed or
286not.")
287
288 ;; Kerberos authentication options
289 (krb5-ccname
290 (maybe-string 'disabled)
291 "Set the name for the GSS-API Kerberos credentials cache.")
292
293 ;; Search / mapping options
294 (base
295 (string "dc=example,dc=com")
296 "The directory search base.")
297 (scope
298 (scope-option '(subtree))
299 "Specifies the search scope (subtree, onelevel, base or children). The
300default scope is subtree; base scope is almost never useful for name service
301lookups; children scope is not supported on all servers.")
302 (deref
303 (maybe-deref-option 'disabled)
304 "Specifies the policy for dereferencing aliases. The default policy is to
305never dereference aliases.")
306 (referrals
307 (maybe-boolean 'disabled)
308 "Specifies whether automatic referral chasing should be enabled. The
309default behaviour is to chase referrals.")
310 (maps
311 (list-of-map-entries '())
312 "This option allows for custom attributes to be looked up instead of the
313default RFC 2307 attributes. It is a list of maps, each consisting of the
314name of a map, the RFC 2307 attribute to match and the query expression for
315the attribute as it is available in the directory.")
316 (filters
317 (list-of-filter-entries '())
318 "A list of filters consisting of the name of a map to which the filter
319applies and an LDAP search filter expression.")
320
321 ;; Timing / reconnect options
322 (bind-timelimit
323 (maybe-number 'disabled)
324 "Specifies the time limit in seconds to use when connecting to the
325directory server. The default value is 10 seconds.")
326 (timelimit
327 (maybe-number 'disabled)
328 "Specifies the time limit (in seconds) to wait for a response from the LDAP
329server. A value of zero, which is the default, is to wait indefinitely for
330searches to be completed.")
331 (idle-timelimit
332 (maybe-number 'disabled)
333 "Specifies the period if inactivity (in seconds) after which the con‐
334nection to the LDAP server will be closed. The default is not to time out
335connections.")
336 (reconnect-sleeptime
337 (maybe-number 'disabled)
338 "Specifies the number of seconds to sleep when connecting to all LDAP
339servers fails. By default one second is waited between the first failure and
340the first retry.")
341 (reconnect-retrytime
342 (maybe-number 'disabled)
343 "Specifies the time after which the LDAP server is considered to be
344permanently unavailable. Once this time is reached retries will be done only
345once per this time period. The default value is 10 seconds.")
346
347 ;; TLS options
348 (ssl
349 (maybe-ssl-option 'disabled)
350 "Specifies whether to use SSL/TLS or not (the default is not to). If
351'start-tls is specified then StartTLS is used rather than raw LDAP over SSL.")
352 (tls-reqcert
353 (maybe-tls-reqcert-option 'disabled)
354 "Specifies what checks to perform on a server-supplied certificate.
355The meaning of the values is described in the ldap.conf(5) manual page.")
356 (tls-cacertdir
357 (maybe-string 'disabled)
358 "Specifies the directory containing X.509 certificates for peer authen‐
359tication. This parameter is ignored when using GnuTLS.")
360 (tls-cacertfile
361 (maybe-string 'disabled)
362 "Specifies the path to the X.509 certificate for peer authentication.")
363 (tls-randfile
364 (maybe-string 'disabled)
365 "Specifies the path to an entropy source. This parameter is ignored when
366using GnuTLS.")
367 (tls-ciphers
368 (maybe-string 'disabled)
369 "Specifies the ciphers to use for TLS as a string.")
370 (tls-cert
371 (maybe-string 'disabled)
372 "Specifies the path to the file containing the local certificate for client
373TLS authentication.")
374 (tls-key
375 (maybe-string 'disabled)
376 "Specifies the path to the file containing the private key for client TLS
377authentication.")
378
379 ;; Other options
380 (pagesize
381 (maybe-number 'disabled)
382 "Set this to a number greater than 0 to request paged results from the LDAP
383server in accordance with RFC2696. The default (0) is to not request paged
384results.")
385 (nss-initgroups-ignoreusers
386 (maybe-ignore-users-option 'disabled)
387 "This option prevents group membership lookups through LDAP for the
388specified users. Alternatively, the value 'all-local may be used. With that
389value nslcd builds a full list of non-LDAP users on startup.")
390 (nss-min-uid
391 (maybe-number 'disabled)
392 "This option ensures that LDAP users with a numeric user id lower than the
393specified value are ignored.")
394 (nss-uid-offset
395 (maybe-number 'disabled)
396 "This option specifies an offset that is added to all LDAP numeric user
397ids. This can be used to avoid user id collisions with local users.")
398 (nss-gid-offset
399 (maybe-number 'disabled)
400 "This option specifies an offset that is added to all LDAP numeric group
401ids. This can be used to avoid user id collisions with local groups.")
402 (nss-nested-groups
403 (maybe-boolean 'disabled)
404 "If this option is set, the member attribute of a group may point to
405another group. Members of nested groups are also returned in the higher level
406group and parent groups are returned when finding groups for a specific user.
407The default is not to perform extra searches for nested groups.")
408 (nss-getgrent-skipmembers
409 (maybe-boolean 'disabled)
410 "If this option is set, the group member list is not retrieved when looking
411up groups. Lookups for finding which groups a user belongs to will remain
412functional so the user will likely still get the correct groups assigned on
413login.")
414 (nss-disable-enumeration
415 (maybe-boolean 'disabled)
416 "If this option is set, functions which cause all user/group entries to be
417loaded from the directory will not succeed in doing so. This can dramatically
418reduce LDAP server load in situations where there are a great number of users
419and/or groups. This option is not recommended for most configurations.")
420 (validnames
421 (maybe-string 'disabled)
422 "This option can be used to specify how user and group names are verified
423within the system. This pattern is used to check all user and group names
424that are requested and returned from LDAP.")
425 (ignorecase
426 (maybe-boolean 'disabled)
427 "This specifies whether or not to perform searches using case-insensitive
428matching. Enabling this could open up the system to authorization bypass
429vulnerabilities and introduce nscd cache poisoning vulnerabilities which allow
430denial of service.")
431 (pam-authc-ppolicy
432 (maybe-boolean 'disabled)
433 "This option specifies whether password policy controls are requested and
434handled from the LDAP server when performing user authentication.")
435 (pam-authc-search
436 (maybe-string 'disabled)
437 "By default nslcd performs an LDAP search with the user's credentials after
438BIND (authentication) to ensure that the BIND operation was successful. The
439default search is a simple check to see if the user's DN exists. A search
440filter can be specified that will be used instead. It should return at least
441one entry.")
442 (pam-authz-search
443 (maybe-string 'disabled)
444 "This option allows flexible fine tuning of the authorisation check that
445should be performed. The search filter specified is executed and if any
446entries match, access is granted, otherwise access is denied.")
447 (pam-password-prohibit-message
448 (maybe-string 'disabled)
449 "If this option is set password modification using pam_ldap will be denied
450and the specified message will be presented to the user instead. The message
451can be used to direct the user to an alternative means of changing their
452password.")
453
454 ;; Options for extension of pam-root-service-type.
455 (pam-services
456 (list '())
457 "List of pam service names for which LDAP authentication should suffice."))
458
459(define %nslcd-accounts
460 (list (user-group
461 (name "nslcd")
462 (system? #t))
463 (user-account
464 (name "nslcd")
465 (group "nslcd")
466 (comment "NSLCD service account")
467 (home-directory "/var/empty")
468 (shell (file-append shadow "/sbin/nologin"))
469 (system? #t))))
470
471(define (nslcd-config-file config)
472 "Return an NSLCD configuration file."
473 (plain-file "nslcd.conf"
474 (with-output-to-string
475 (lambda ()
476 (serialize-configuration config nslcd-configuration-fields)
477 ;; The file must end with a newline character.
478 (format #t "\n")))))
479
480;; XXX: The file should only be readable by root if it contains a "bindpw"
481;; declaration. Unfortunately, this etc-service-type extension does not
482;; support setting file modes, so we do this in the activation service.
483(define (nslcd-etc-service config)
484 `(("nslcd.conf" ,(nslcd-config-file config))))
485
486(define (nslcd-shepherd-service config)
487 (list (shepherd-service
488 (documentation "Run the nslcd service for resolving names from LDAP.")
489 (provision '(nslcd))
490 (requirement '(networking user-processes))
491 (start #~(make-forkexec-constructor
492 (list (string-append #$(nslcd-configuration-nss-pam-ldapd config)
493 "/sbin/nslcd")
494 "--nofork")
495 #:pid-file "/var/run/nslcd/nslcd.pid"
496 #:environment-variables
497 (list (string-append "LD_LIBRARY_PATH="
498 #$(nslcd-configuration-nss-pam-ldapd config)
499 "/lib"))))
500 (stop #~(make-kill-destructor)))))
501
502(define (pam-ldap-pam-service config)
503 "Return a PAM service for LDAP authentication."
504 (define pam-ldap-module
505 #~(string-append #$(nslcd-configuration-nss-pam-ldapd config)
506 "/lib/security/pam_ldap.so"))
507 (lambda (pam)
508 (if (member (pam-service-name pam)
509 (nslcd-configuration-pam-services config))
510 (let ((sufficient
511 (pam-entry
512 (control "sufficient")
513 (module pam-ldap-module))))
514 (pam-service
515 (inherit pam)
516 (auth (cons sufficient (pam-service-auth pam)))
517 (session (cons sufficient (pam-service-session pam)))
518 (account (cons sufficient (pam-service-account pam)))))
519 pam)))
520
521(define (pam-ldap-pam-services config)
522 (list (pam-ldap-pam-service config)))
523
524(define nslcd-service-type
525 (service-type
526 (name 'nslcd)
527 (description "Run the NSLCD service for looking up names from LDAP.")
528 (extensions
529 (list (service-extension account-service-type
530 (const %nslcd-accounts))
531 (service-extension etc-service-type
532 nslcd-etc-service)
533 (service-extension activation-service-type
534 (const #~(begin
535 (use-modules (guix build utils))
536 (let ((rundir "/var/run/nslcd")
537 (user (getpwnam "nslcd")))
538 (mkdir-p rundir)
539 (chown rundir (passwd:uid user) (passwd:gid user))
540 (chmod rundir #o755)
541 (when (file-exists? "/etc/nslcd.conf")
542 (chmod "/etc/nslcd.conf" #o400))))))
543 (service-extension pam-root-service-type
544 pam-ldap-pam-services)
545 (service-extension nscd-service-type
546 (const (list nss-pam-ldapd)))
547 (service-extension shepherd-root-service-type
548 nslcd-shepherd-service)))
549 (default-value (nslcd-configuration))))
550
551(define (generate-nslcd-documentation)
552 (generate-documentation
553 `((nslcd-configuration ,nslcd-configuration-fields))
554 'nslcd-configuration))