guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] gnu: Add Kerberos client service.


From: John Darrington
Subject: [PATCH] gnu: Add Kerberos client service.
Date: Tue, 29 Nov 2016 19:39:44 +0100

* doc/guix.texi (Kerberos Services)[Krb5 Service]: New subsubheading.
* gnu/services/kerberos.scm (krb5-service-type): New variable.
---
 doc/guix.texi                  |  87 ++++++++++
 gnu/services/configuration.scm |   4 +-
 gnu/services/kerberos.scm      | 366 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 454 insertions(+), 3 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 125e5f0..069bab2 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11536,6 +11536,93 @@ remote servers.  Run @command{man smtpd.conf} for more 
information.
 The @code{(gnu services kerberos)} module provides services relating to
 the authentication protocol @dfn{Kerberos}.
 
address@hidden Krb5 Service
+
+The krb5 service provides the configuration for Kerberos clients, using
+the MIT implementation of the Kerberos protocol address@hidden
+
address@hidden {Scheme Variable} krb5-service-type
+A service type for Kerberos 5 clients.
address@hidden defvr
+
address@hidden
+Here is an example of its use:
address@hidden
+(service krb5-service-type (krb5-configuration
+                               (default-realm "EXAMPLE.COM")
+                               (allow-weak-crypto? #t)
+                               (realms (list
+                                        (krb5-realm
+                                         (name "EXAMPLE.COM")
+                                         (admin-server "groucho.example.com")
+                                         (kdc "karl.example.com"))
+                                        (krb5-realm
+                                         (name "ARGRX.EDU")
+                                         (admin-server "kerb-admin.argrx.edu")
+                                         (kdc "keys.argrx.edu"))))))
address@hidden lisp
+
address@hidden
+This example provides a address@hidden client configuration which:
address@hidden
address@hidden Recognizes two realms, @i{viz:} ``EXAMPLE.COM'' and 
``ARGRX.EDU'', both
+of which have distinct administration servers and key distribution centers;
address@hidden Will default to the realm ``EXAMPLE.COM'' if the realm is not 
explicitly
+specified by clients;
address@hidden Accepts services which only support encryption types known to be 
weak.
address@hidden itemize
+
+The @code{krb5-realm} and @code{krb5-configuration} types have many fields.
+Only the most commonly used ones are described here.
+For a full list, and more detailed explanation of each, see the MIT
address@hidden://web.mit.edu/kerberos/krb5-devel/doc/admin/conf_files/krb5_conf.html,,krb5.conf}
+documentation.
+
+
address@hidden {Data Type} krb5-realm
address@hidden realm, kerberos
address@hidden @asis
address@hidden @code{name}
+This field is a string identifying the name of the realm.
+A common convention is to use the fully qualified DNS name of your 
organization,
+converted to upper case.
+
address@hidden @code{admin-server}
+This field is a string identifying the host where the administration server is
+running.
+
address@hidden @code{kdc}
+This field is a string identifying the key distribution center
+for the realm.
address@hidden table
address@hidden deftp
+
+
address@hidden {Data Type} krb5-configuration
+
address@hidden @asis
address@hidden @code{allow-weak-crypto?} (default: @code{#f})
+If this flag is @code{#t} then services which only offer encryption algorithms
+known to be weak will be accepted.
+
address@hidden @code{default-realm} (default: @code{#f})
+This field should be a string identifying the default Kerberos
+realm for the client.
+You should set this field to the name of your Kerberos realm.
+If this value is @code{#f}
+then a realm must be specified with every Kerberos principal when invoking 
programs
+such as @command{kinit}.
+
address@hidden @code{realms}
+This should be a non-empty list of @code{krb5-realm} objects, which clients may
+access.
+Normally, one of them will have a @code{name} field matching the 
@code{default-realm}
+field.
address@hidden table
address@hidden deftp
+
+
+
 @subsubheading PAM krb5 Service
 @cindex pam-krb5
 
diff --git a/gnu/services/configuration.scm b/gnu/services/configuration.scm
index 9f28aab..5c32cf7 100644
--- a/gnu/services/configuration.scm
+++ b/gnu/services/configuration.scm
@@ -30,6 +30,8 @@
             configuration-field-name
             configuration-missing-field
             configuration-field-error
+            configuration-field-getter
+            configuration-field-serializer
             serialize-configuration
             define-configuration
             validate-configuration
@@ -83,7 +85,7 @@
 (define (validate-configuration config fields)
   (for-each (lambda (field)
               (let ((val ((configuration-field-getter field) config)))
-                (unless ((configuration-field-predicate field) val)
+                (unless (or (not val) ((configuration-field-predicate field) 
val))
                   (configuration-field-error
                    (configuration-field-name field) val))))
             fields))
diff --git a/gnu/services/kerberos.scm b/gnu/services/kerberos.scm
index a56f630..059d371 100644
--- a/gnu/services/kerberos.scm
+++ b/gnu/services/kerberos.scm
@@ -17,14 +17,376 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu services kerberos)
-  #:use-module (gnu packages admin)
   #:use-module (gnu services)
+  #:use-module (gnu services configuration)
   #:use-module (gnu system pam)
   #:use-module (guix gexp)
   #:use-module (guix records)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-35)
+  #:use-module (ice-9 match)
   #:export (pam-krb5-configuration
             pam-krb5-configuration?
-            pam-krb5-service-type))
+            pam-krb5-service-type
+
+            krb5-realm
+            krb5-realm?
+
+            krb5-configuration
+            krb5-configuration?
+            krb5-service-type))
+
+
+
+(define (uglify-field-name field-name)
+  (let ((str (symbol->string field-name)))
+    (string-join (string-split (if (string-suffix? "?" str)
+                                   (substring str 0 (1- (string-length str)))
+                                   str)
+                               #\-)
+                 "_")))
+
+(define (serialize-field* field-name val)
+  (format #t "~a = ~a\n" (uglify-field-name field-name) val))
+
+(define (serialize-string field-name val)
+  (if val
+      (serialize-field* field-name val) ""))
+
+;; An end-point is an address such as "192.168.0.1"
+;; or an address port pair ("foo.example.com" . 109)
+(define (end-point? val)
+  (or (string? val)
+      (and (pair? val)
+           (string? (car val))
+           (integer? (cdr val)))))
+
+(define (serialize-end-point field-name val)
+  (serialize-field* field-name
+                   (if (string? val)
+                       ;; The [] are needed in the case of IPv6 addresses
+                       (format #f "[~a]" val)
+                       (format #f "[~a]:~a" (car val) (cdr val)))))
+
+
+(define (serialize-space-separated-string-list field-name val)
+  (if val
+      (serialize-field* field-name (string-join val " "))))
+
+(define (comma-separated-string-list? val)
+  (and (list? val)
+       (and-map (lambda (x)
+                  (and (string? x) (not (string-index x #\,))))
+                val)))
+
+(define (serialize-comma-separated-string-list field-name val)
+  (serialize-field* field-name (string-join val ",")))
+
+(define (comma-separated-integer-list? val)
+  (and (list? val)
+       (and-map (lambda (x) (integer? x))
+                val)))
+
+(define (serialize-comma-separated-integer-list field-name val)
+  (if val
+      (serialize-field* field-name
+                       (string-drop ; Drop the leading comma
+                        (fold
+                         (lambda (i prev)
+                           (string-append prev "," (number->string i)))
+                         "" val) 1))))
+
+(define (file-name? val)
+  (and (string? val)
+       (string-prefix? "/" val)))
+
+(define (serialize-file-name field-name val)
+  (serialize-string field-name val))
+
+
+(define (serialize-boolean field-name val)
+  (serialize-string field-name (if val "true" "false")))
+
+(define (non-negative-integer? val)
+  (and (exact-integer? val) (not (negative? val))))
+
+(define (serialize-non-negative-integer field-name val)
+  (if val
+      (serialize-field* field-name val)))
+
+(define (serialize-integer field-name val)
+  (if val
+      (serialize-field* field-name val)))
+
+(define (free-form-fields? val)
+  (match val
+    (() #t)
+    ((((? symbol?) . (? string)) . val) (free-form-fields? val))
+    (_ #f)))
+
+(define (serialize-free-form-fields field-name val)
+  (for-each (match-lambda ((k . v) (serialize-field* k v))) val))
+
+(define (realm-list? val)
+  (and (list? val)
+       (and-map (lambda (x) (krb5-realm? x)) val)))
+
+(define (serialize-realm-list field-name val)
+  (format #t "\n[~a]\n" field-name)
+  (for-each (lambda (realm)
+              (format #t "\n~a = {\n" (krb5-realm-name realm))
+              (for-each (lambda (field)
+                          (unless (eq? 'name (configuration-field-name field))
+                            ((configuration-field-serializer field)
+                             (configuration-field-name field)
+                             ((configuration-field-getter field)
+                              realm)))) krb5-realm-fields)
+
+              (format #t "}\n")) val))
+
+
+
+;; For a more detailed explanation of these fields see man 5 krb5.conf
+(define-configuration krb5-realm
+  (name
+   (string #f)
+   "The name of the realm.")
+
+  (kdc
+   (end-point #f)
+   "The host and port on which the realm's Key Distribution Server listens.")
+
+  (admin-server
+   (string #f)
+   "The Host running the administration server for the realm.")
+
+  (master-kdc
+   (string #f)
+   "If an attempt to get credentials fails because of an invalid password, 
+the client software will attempt to contact the master KDC.")
+
+  (kpasswd-server
+   (string #f)
+   "The server where password changes are performed.")
+
+  (auth-to-local
+   (free-form-fields '())
+   "Rules to map between principals and local users.")
+
+  (auth-to-local-names
+   (free-form-fields '())
+   "Explicit mappings between principal names and local user names.")
+
+  (http-anchors
+   (free-form-fields '())
+   "Useful only when http proxy is used to access KDC or KPASSWD.")
+
+  ;; The following are useful only for working with V4 services
+  (default-domain
+    (string #f)
+    "The domain used to expand host names when translating Kerberos 4 service
+principals to Kerberos 5 principals")
+
+  (v4-instance-convert
+   (free-form-fields '())
+   "Exceptions to the default-domain mapping rule.")
+
+  (v4-realm
+   (string #f)
+   "Used  when the V4 realm name and the V5 realm name are not the same, but
+still share the same principal names and passwords"))
+
+
+
+;; For a more detailed explanation of these fields see man 5 krb5.conf
+(define-configuration krb5-configuration
+  (allow-weak-crypto?
+   (boolean #f)
+   "If true, permits access to services which only offer weak encryption.")
+
+  (ap-req-checksum-type
+   (non-negative-integer #f)
+   "The type of the AP-REQ checksum.")
+
+  (canonicalize?
+   (boolean #f)
+   "Should principals in initial ticket requests be canonicalized?")
+
+  (ccache-type
+   (non-negative-integer #f)
+   "The format of the credential cache type.")
+
+  (clockskew
+   (non-negative-integer #f)
+   "Maximum allowable clock skew in seconds (default 300).")
+
+  (default-ccache-name
+    (file-name #f)
+    "The name of the default credential cache.")
+
+  (default-client-keytab-name
+    (file-name #f)
+    "The name of the default keytab for client credentials.")
+
+  (default-keytab-name
+    (file-name #f)
+    "The name of the default keytab file.")
+
+  (default-realm
+    (string #f)
+    "The realm to be accessed if not explicitly specified by clients.")
+
+  (default-tgs-enctypes
+    (free-form-fields '())
+    "Session key encryption types when making TGS-REQ requests.")
+
+  (default-tkt-enctypes
+    (free-form-fields '())
+    "Session key encryption types when making AS-REQ requests.")
+
+  (dns-canonicalize-hostname?
+   (boolean #t)
+   "Whether name lookups will be used to canonicalize host names for use in 
+service principal names.")
+
+  (dns-lookup-kdc?
+   (boolean #f)
+ "Should DNS SRV records should be used to locate the KDCs and other servers 
+not appearing in the realm specification")
+
+  (err-fmt
+   (string #f)
+   "Custom error message formatting. If not #f error messages will be 
formatted 
+by substituting a normal error message for %M and an error code for %C in the 
+value.")
+
+  (forwardable?
+   (boolean #f)
+   "Should initial tickets be forwardable by default?")
+
+  (ignore-acceptor-hostname?
+   (boolean #f)
+   "When accepting GSSAPI or krb5 security contexts for host-based service 
+principals, ignore any hostname passed by the calling application, and allow 
+clients to authenticate to any service principal in the keytab matching the 
+service name and realm name.")
+
+  (k5login-authoritative?
+   (boolean #t)
+   "If this flag is true, principals must be listed in a local user's k5login
+file to be granted login access, if a ~/.k5login file exists.")
+
+  (k5login-directory
+   (string #f)
+   "If not #f, the library will look for a local user's @file{k5login} file 
+within the named directory (instead of the user's home directory), with a 
+file name corresponding to the local user name.")
+
+  (kcm-mach-service
+   (string #f)
+   "The name of the bootstrap service used to contact the KCM daemon for the 
+KCM credential cache type.")
+
+  (kcm-socket
+   (file-name #f)
+ "Path to the Unix domain socket used to access the KCM daemon for the KCM 
+credential cache type.")
+
+  (kdc-default-options
+   (non-negative-integer #f)
+   "Default KDC options (logored for multiple values) when requesting initial 
+tickets.")
+
+  (kdc-timesync
+   (non-negative-integer #f)
+   "Attempt to compensate for clock skew between the KDC and client.")
+
+  (kdc-req-checksum-type
+   (non-negative-integer #f)
+   "The type of checksum to use for the KDC requests. Relevant only for DES 
+keys")
+
+  (noaddresses?
+   (boolean #t)
+   "If true, initial ticket requests will not be made with address 
restrictions.
+This enables their use across NATs.")
+
+  (permitted-enctypes
+   (space-separated-string-list #f)
+   "All encryption types that are permitted for use in session key 
encryption.")
+
+  (plugin-base-dir
+   (file-name #f)
+   "The directory where krb5 plugins are located.")
+
+  (preferred-preauth-types
+   (comma-separated-integer-list #f)
+   "The preferred pre-authentication types which the client will attempt 
before 
+others.")
+
+  (proxiable?
+   (boolean #f)
+   "Should initial tickets be proxiable by default?")
+
+  (rdns?
+   (boolean #t)
+   "Should reverse DNS lookup be used in addition to forward name lookup to 
+canonicalize host names for use in service principal names.")
+
+  (realm-try-domains
+   (integer #f)
+   "Should a host's domain components should be used to determine the Kerberos 
+realm of the host.")
+
+  (renew-lifetime
+   (non-negative-integer #f)
+   "The default renewable lifetime for initial ticket requests.")
+
+  (safe-checksum-type
+   (non-negative-integer #f)
+   "The type of checksum to use for the KRB-SAFE requests.")
+
+  (ticket-lifetime
+   (non-negative-integer #f)
+   "The default lifetime for initial ticket requests.")
+
+  (udp-preference-limit
+   (non-negative-integer #f)
+   "When sending messages to the KDC, the library will try using TCP
+before UDP if the size of the message greater than this limit.")
+
+  (verify-ap-req-nofail?
+   (boolean #f)
+ "If true, then attempts to verify initial credentials will fail if the client
+machine does not have a keytab.")
+
+  (realms
+   (realm-list '())
+   "The list of realms which clients may access."))
+
+
+(define (krb5-configuration-file config)
+  "Create a Kerberos 5 configuration file based on CONFIG"
+  (mixed-text-file "krb5.conf"
+                   "[libdefaults]\n\n"
+                   (with-output-to-string
+                     (lambda ()
+                       (serialize-configuration config
+                                                krb5-configuration-fields)))))
+
+(define (krb5-etc-service config)
+  (list `("krb5.conf" ,(krb5-configuration-file config))))
+
+
+(define krb5-service-type
+  (service-type (name 'krb5)
+                (extensions
+                 (list (service-extension etc-service-type
+                                          krb5-etc-service)))))
+
+
+
 
 (define-record-type* <pam-krb5-configuration>
   pam-krb5-configuration  make-pam-krb5-configuration
-- 
2.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]