s3:libads: Allow 'net ads keytab add' handle Windows SPN(s) part 1
authorNoel Power <noel.power@suse.com>
Mon, 29 Jan 2018 18:30:33 +0000 (18:30 +0000)
committerAndreas Schneider <asn@cryptomilk.org>
Fri, 2 Mar 2018 13:07:14 +0000 (14:07 +0100)
This patch addresses how the windows SPN is converted into a kerberos
priniciple to be written to the keytab file. A followup patch will
deal with writing Window SPN(s) to the AD.

Before this change 'net ads keytab add' handled three scenarios

a) 'net ads keytab add param' is passed a fully qualified kerberos principal
   (identified by the presence of '@' in param) In this scenario the keytab
   file alone is updated with the principal contained in 'param'.
b) 'net ads keytab add param'; is passed a machine name (identified by
   the paramater ending with '$'). In this case the machine name
   is converted to a kerberos principal with according to the recipe
   'param@realm' where realm is determined by lp_realm().
c) 'net ads keytab add param' is passed a service (e.g. nfs, http etc.)
   In this scenario the param containing the service is first converted to
   into 2 kerberos principals (long and short forms) according to the
   following recipe
      i) long form:  'param/fully_qualified_dns@realm'
     ii) short form: 'param/netbios_name@realm'
     where 'fully_qualified_dns is retrieved from 'dNSHostName' attribute of
     'this' machines computer account on the AD.
     The principals are written to the keytab file
   Secondly 2 windows SPNs are generated from 'param' as follows
      i) long form 'param/full_qualified_dns'
     ii) short form 'param/netbios_name'
   These SPNs are written to the AD computer account object

After this change a) & b) & c) will retain legacy behaviour except
in the case of c) where if the 'param' passed to c) is a Windows SPN
(e.g. conforming to format 'serviceclass/host:port'
  i) 'param' will get converted to a kerberos principal (just a single one)
     with the following recipe: 'serviceclass/host@realm' which will
     be written to the keytab file. The SPN written to the AD is created
     as before and the legacy behaviour is preserved.

Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libads/kerberos_keytab.c

index fbb03402848a604bad7997ab810bd3597778f280..bcfeadc880a7d9d072d0c1d2a52d2790a624962e 100644 (file)
@@ -159,6 +159,59 @@ static bool ads_set_machine_account_spns(TALLOC_CTX *ctx,
        return true;
 }
 
+/*
+ * Create kerberos principal(s) from SPN or service name.
+ */
+static bool service_or_spn_to_kerberos_princ(TALLOC_CTX *ctx,
+                                            const char *service_or_spn,
+                                            const char *my_fqdn,
+                                            char **p_princ_s,
+                                            char **p_short_princ_s)
+{
+       char *princ_s = NULL;
+       char *short_princ_s = NULL;
+       const char *service = service_or_spn;
+       const char *host = my_fqdn;
+       struct spn_struct* spn_struct = NULL;
+       char *tmp = NULL;
+       bool ok = true;
+
+       /* SPN should have '/' */
+       tmp = strchr_m(service_or_spn, '/');
+       if (tmp != NULL) {
+               spn_struct = parse_spn(ctx, service_or_spn);
+               if (spn_struct == NULL) {
+                       ok = false;
+                       goto out;
+               }
+       }
+       if (spn_struct != NULL) {
+               service = spn_struct->serviceclass;
+               host = spn_struct->host;
+       }
+       princ_s = talloc_asprintf(ctx, "%s/%s@%s",
+                                 service,
+                                 host, lp_realm());
+       if (princ_s == NULL) {
+               ok = false;
+               goto out;
+       }
+
+       if (spn_struct == NULL) {
+               short_princ_s = talloc_asprintf(ctx, "%s/%s@%s",
+                                       service, lp_netbios_name(),
+                                       lp_realm());
+               if (short_princ_s == NULL) {
+                       ok = false;
+                       goto out;
+               }
+       }
+       *p_princ_s = princ_s;
+       *p_short_princ_s = short_princ_s;
+out:
+       return ok;
+}
+
 /**********************************************************************
  Adds a single service principal, i.e. 'host' to the system keytab
 ***********************************************************************/
@@ -264,16 +317,11 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
                 * can obtain credentials for it and double-check the salt value
                 * used to generate the service's keys. */
 
-               princ_s = talloc_asprintf(tmpctx, "%s/%s@%s",
-                                         srvPrinc, my_fqdn, lp_realm());
-               if (!princ_s) {
-                       ret = -1;
-                       goto out;
-               }
-               short_princ_s = talloc_asprintf(tmpctx, "%s/%s@%s",
-                                               srvPrinc, lp_netbios_name(),
-                                               lp_realm());
-               if (short_princ_s == NULL) {
+               if (!service_or_spn_to_kerberos_princ(tmpctx,
+                                                     srvPrinc,
+                                                     my_fqdn,
+                                                     &princ_s,
+                                                     &short_princ_s)) {
                        ret = -1;
                        goto out;
                }