summaryrefslogtreecommitdiffstats
path: root/utils/gssd/krb5_util.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2011-02-09 11:27:19 -0500
committerSteve Dickson <steved@redhat.com>2011-02-09 11:33:32 -0500
commit45e4597bd570ed40221f51887cde7d7f096f55e7 (patch)
tree195ae858569b1fcf4984a254b495e96c36f26800 /utils/gssd/krb5_util.c
parent730f6986f86873513fa021a450eb55ccd0f2fbff (diff)
downloadnfs-utils-45e4597bd570ed40221f51887cde7d7f096f55e7.tar.gz
nfs-utils-45e4597bd570ed40221f51887cde7d7f096f55e7.tar.xz
nfs-utils-45e4597bd570ed40221f51887cde7d7f096f55e7.zip
Support AD style kerberos automatically in rpc.gss
An Active Directory KDC will only grant a TGT for UPNs, getting a TGT for SPNs is not possible: $ kinit -k host/ib5@ADS.ORCORP.CA kinit: Client not found in Kerberos database while getting initial credentials The correct thing to do for machine credentials is to get a TGT for the computer UPN <HOSTNAME>$@REALM: $ kinit -k IB5\$ $ klist 12/22/10 11:43:47 12/22/10 21:43:47 krbtgt/ADS.ORCORP.CA@ADS.ORCORP.CA Samba automatically creates /etc/krb5.keytab entry for the computer UPN, this patch makes gssd_refresh_krb5_machine_credential prefer it above the SPNs if it is present. The net result is that nfs client works automatically out of the box if samba has been used to setup kerberos via 'net ads join' 'net ads keytab create' Tested using Windows Server 2003 R2 as the AD server. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'utils/gssd/krb5_util.c')
-rw-r--r--utils/gssd/krb5_util.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index f071600..4b13fa1 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -768,6 +768,7 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
krb5_error_code code;
char **realmnames = NULL;
char myhostname[NI_MAXHOST], targethostname[NI_MAXHOST];
+ char myhostad[NI_MAXHOST+1];
int i, j, retval;
char *default_realm = NULL;
char *realm;
@@ -789,6 +790,14 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
printerr(1, "%s while getting local hostname\n", k5err);
goto out;
}
+
+ /* Compute the active directory machine name HOST$ */
+ strcpy(myhostad, myhostname);
+ for (i = 0; myhostad[i] != 0; ++i)
+ myhostad[i] = toupper(myhostad[i]);
+ myhostad[i] = '$';
+ myhostad[i+1] = 0;
+
retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
if (retval)
goto out;
@@ -833,32 +842,47 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
if (strcmp(realm, default_realm) == 0)
tried_default = 1;
for (j = 0; svcnames[j] != NULL; j++) {
- code = krb5_build_principal_ext(context, &princ,
- strlen(realm),
- realm,
- strlen(svcnames[j]),
- svcnames[j],
- strlen(myhostname),
- myhostname,
- NULL);
+ char spn[300];
+
+ /*
+ * The special svcname "$" means 'try the active
+ * directory machine account'
+ */
+ if (strcmp(svcnames[j],"$") == 0) {
+ snprintf(spn, sizeof(spn), "%s@%s", myhostad, realm);
+ code = krb5_build_principal_ext(context, &princ,
+ strlen(realm),
+ realm,
+ strlen(myhostad),
+ myhostad,
+ NULL);
+ } else {
+ snprintf(spn, sizeof(spn), "%s/%s@%s",
+ svcnames[j], myhostname, realm);
+ code = krb5_build_principal_ext(context, &princ,
+ strlen(realm),
+ realm,
+ strlen(svcnames[j]),
+ svcnames[j],
+ strlen(myhostname),
+ myhostname,
+ NULL);
+ }
+
if (code) {
k5err = gssd_k5_err_msg(context, code);
- printerr(1, "%s while building principal for "
- "'%s/%s@%s'\n", k5err, svcnames[j],
- myhostname, realm);
+ printerr(1, "%s while building principal for '%s'\n",
+ k5err, spn);
continue;
}
code = krb5_kt_get_entry(context, kt, princ, 0, 0, kte);
krb5_free_principal(context, princ);
if (code) {
k5err = gssd_k5_err_msg(context, code);
- printerr(3, "%s while getting keytab entry for "
- "'%s/%s@%s'\n", k5err, svcnames[j],
- myhostname, realm);
+ printerr(3, "%s while getting keytab entry for '%s'\n",
+ k5err, spn);
} else {
- printerr(3, "Success getting keytab entry for "
- "'%s/%s@%s'\n",
- svcnames[j], myhostname, realm);
+ printerr(3, "Success getting keytab entry for '%s'\n",spn);
retval = 0;
goto out;
}
@@ -870,6 +894,8 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
*/
for (j = 0; svcnames[j] != NULL; j++) {
int found = 0;
+ if (strcmp(svcnames[j],"$") == 0)
+ continue;
code = gssd_search_krb5_keytab(context, kt, realm,
svcnames[j], &found, kte);
if (!code && found) {
@@ -1160,7 +1186,7 @@ gssd_refresh_krb5_machine_credential(char *hostname,
krb5_keytab kt = NULL;;
int retval = 0;
char *k5err = NULL;
- const char *svcnames[4] = { "root", "nfs", "host", NULL };
+ const char *svcnames[5] = { "$", "root", "nfs", "host", NULL };
/*
* If a specific service name was specified, use it.