From: Noel Power Date: Mon, 29 Jan 2018 18:30:33 +0000 (+0000) Subject: s3:libads: Allow 'net ads keytab add' handle Windows SPN(s) part 1 X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=efabfb1c17b02c2e567e8e351e52aa8ba69d7c34;p=metze%2Fsamba%2Fwip.git s3:libads: Allow 'net ads keytab add' handle Windows SPN(s) part 1 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 Reviewed-by: Jeremy Allison Reviewed-by: Andreas Schneider --- diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c index fbb03402848a..bcfeadc880a7 100644 --- a/source3/libads/kerberos_keytab.c +++ b/source3/libads/kerberos_keytab.c @@ -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; }