All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Support AD style kerberos automatically in rpc.gss
@ 2010-12-22 19:22 Jason Gunthorpe
  2010-12-23 10:55 ` Timo Aaltonen
  2011-02-09 16:34 ` Steve Dickson
  0 siblings, 2 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2010-12-22 19:22 UTC (permalink / raw)
  To: linux-nfs

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>
---
 utils/gssd/gssd.man    |    5 ++++
 utils/gssd/krb5_util.c |   62 ++++++++++++++++++++++++++++++++++--------------
 2 files changed, 49 insertions(+), 18 deletions(-)

I'm still looking into what to do for AD in the server case when
process_krb5_upcall is called with service == nfs. Some references
suggest setting AD's userPrincipalName to the nfs SPN, but it would be
really nice if that wasn't necessary.

Shouldn't it be possible to use the a ticket provided from the client
to send back an unsolicted reply??

Thanks,
Jason

diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
index 0a23cd6..073379d 100644
--- a/utils/gssd/gssd.man
+++ b/utils/gssd/gssd.man
@@ -53,6 +53,8 @@ To be more consistent with other implementations, we now look for
 specific keytab entries.  The search order for keytabs to be used
 for "machine credentials" is now:
 .br
+  <HOSTNAME>$@<REALM>
+.br
   root/<hostname>@<REALM>
 .br
   nfs/<hostname>@<REALM>
@@ -64,6 +66,9 @@ for "machine credentials" is now:
   nfs/<anyname>@<REALM>
 .br
   host/<anyname>@<REALM>
+.IP
+If this search order does not use the correct key then provide a
+keytab file that contains only correct keys.
 .TP
 .B -p path
 Tells
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.
-- 
1.7.1



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] Support AD style kerberos automatically in rpc.gss
  2010-12-22 19:22 [PATCH] Support AD style kerberos automatically in rpc.gss Jason Gunthorpe
@ 2010-12-23 10:55 ` Timo Aaltonen
  2011-01-04 21:32   ` Jason Gunthorpe
  2011-02-09 16:34 ` Steve Dickson
  1 sibling, 1 reply; 5+ messages in thread
From: Timo Aaltonen @ 2010-12-23 10:55 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: linux-nfs

On Wed, 22 Dec 2010, Jason Gunthorpe wrote:

> 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.

This is basically what I did earlier, see:

http://marc.info/?l=linux-nfs&m=128108638228797&w=2

though I still haven't cleaned it up as promised..


> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
> utils/gssd/gssd.man    |    5 ++++
> utils/gssd/krb5_util.c |   62 ++++++++++++++++++++++++++++++++++--------------
> 2 files changed, 49 insertions(+), 18 deletions(-)
>
> I'm still looking into what to do for AD in the server case when
> process_krb5_upcall is called with service == nfs. Some references
> suggest setting AD's userPrincipalName to the nfs SPN, but it would be
> really nice if that wasn't necessary.
>
> Shouldn't it be possible to use the a ticket provided from the client
> to send back an unsolicted reply??
>
> Thanks,
> Jason
>
> diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
> index 0a23cd6..073379d 100644
> --- a/utils/gssd/gssd.man
> +++ b/utils/gssd/gssd.man
> @@ -53,6 +53,8 @@ To be more consistent with other implementations, we now look for
> specific keytab entries.  The search order for keytabs to be used
> for "machine credentials" is now:
> .br
> +  <HOSTNAME>$@<REALM>
> +.br
>   root/<hostname>@<REALM>
> .br
>   nfs/<hostname>@<REALM>
> @@ -64,6 +66,9 @@ for "machine credentials" is now:
>   nfs/<anyname>@<REALM>
> .br
>   host/<anyname>@<REALM>
> +.IP
> +If this search order does not use the correct key then provide a
> +keytab file that contains only correct keys.
> .TP
> .B -p path
> Tells
> 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.
> -- 
> 1.7.1
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

-- 
Timo Aaltonen
Systems Specialist, Aalto IT

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Support AD style kerberos automatically in rpc.gss
  2010-12-23 10:55 ` Timo Aaltonen
@ 2011-01-04 21:32   ` Jason Gunthorpe
  2011-01-06 13:12     ` Steve Dickson
  0 siblings, 1 reply; 5+ messages in thread
From: Jason Gunthorpe @ 2011-01-04 21:32 UTC (permalink / raw)
  To: Timo Aaltonen; +Cc: linux-nfs, Steve Dickson

On Thu, Dec 23, 2010 at 12:55:16PM +0200, Timo Aaltonen wrote:
> On Wed, 22 Dec 2010, Jason Gunthorpe wrote:
> 
> >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.
> 
> This is basically what I did earlier, see:
> 
> http://marc.info/?l=linux-nfs&m=128108638228797&w=2
> 
> though I still haven't cleaned it up as promised..

Right, mine is a bit more complete (man page updated, etc) but it does
the same thing.

Maybe we can get a nfs-utils maintainer to comment this time?

Jason
 
> >Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> >utils/gssd/gssd.man    |    5 ++++
> >utils/gssd/krb5_util.c |   62 ++++++++++++++++++++++++++++++++++--------------
> >2 files changed, 49 insertions(+), 18 deletions(-)
> >
> >I'm still looking into what to do for AD in the server case when
> >process_krb5_upcall is called with service == nfs. Some references
> >suggest setting AD's userPrincipalName to the nfs SPN, but it would be
> >really nice if that wasn't necessary.
> >
> >Shouldn't it be possible to use the a ticket provided from the client
> >to send back an unsolicted reply??
> >
> >Thanks,
> >Jason
> >
> >diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
> >index 0a23cd6..073379d 100644
> >+++ b/utils/gssd/gssd.man
> >@@ -53,6 +53,8 @@ To be more consistent with other implementations, we now look for
> >specific keytab entries.  The search order for keytabs to be used
> >for "machine credentials" is now:
> >.br
> >+  <HOSTNAME>$@<REALM>
> >+.br
> >  root/<hostname>@<REALM>
> >.br
> >  nfs/<hostname>@<REALM>
> >@@ -64,6 +66,9 @@ for "machine credentials" is now:
> >  nfs/<anyname>@<REALM>
> >.br
> >  host/<anyname>@<REALM>
> >+.IP
> >+If this search order does not use the correct key then provide a
> >+keytab file that contains only correct keys.
> >.TP
> >.B -p path
> >Tells
> >diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
> >index f071600..4b13fa1 100644
> >+++ 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.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Support AD style kerberos automatically in rpc.gss
  2011-01-04 21:32   ` Jason Gunthorpe
@ 2011-01-06 13:12     ` Steve Dickson
  0 siblings, 0 replies; 5+ messages in thread
From: Steve Dickson @ 2011-01-06 13:12 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Timo Aaltonen, linux-nfs



On 01/04/2011 04:32 PM, Jason Gunthorpe wrote:
> On Thu, Dec 23, 2010 at 12:55:16PM +0200, Timo Aaltonen wrote:
>> On Wed, 22 Dec 2010, Jason Gunthorpe wrote:
>>
>>> 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.
>>
>> This is basically what I did earlier, see:
>>
>> http://marc.info/?l=linux-nfs&m=128108638228797&w=2
>>
>> though I still haven't cleaned it up as promised..
> 
> Right, mine is a bit more complete (man page updated, etc) but it does
> the same thing.
> 
> Maybe we can get a nfs-utils maintainer to comment this time?
Sorry for the delay.... I'll trying to get to this asap... 

steved.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Support AD style kerberos automatically in rpc.gss
  2010-12-22 19:22 [PATCH] Support AD style kerberos automatically in rpc.gss Jason Gunthorpe
  2010-12-23 10:55 ` Timo Aaltonen
@ 2011-02-09 16:34 ` Steve Dickson
  1 sibling, 0 replies; 5+ messages in thread
From: Steve Dickson @ 2011-02-09 16:34 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: linux-nfs

My apologies for taking so long with this... 

On 12/22/2010 02:22 PM, Jason Gunthorpe wrote:
> 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>
Committed... 

steved.
> ---
>  utils/gssd/gssd.man    |    5 ++++
>  utils/gssd/krb5_util.c |   62 ++++++++++++++++++++++++++++++++++--------------
>  2 files changed, 49 insertions(+), 18 deletions(-)
> 
> I'm still looking into what to do for AD in the server case when
> process_krb5_upcall is called with service == nfs. Some references
> suggest setting AD's userPrincipalName to the nfs SPN, but it would be
> really nice if that wasn't necessary.
> 
> Shouldn't it be possible to use the a ticket provided from the client
> to send back an unsolicted reply??
> 
> Thanks,
> Jason
> 
> diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
> index 0a23cd6..073379d 100644
> --- a/utils/gssd/gssd.man
> +++ b/utils/gssd/gssd.man
> @@ -53,6 +53,8 @@ To be more consistent with other implementations, we now look for
>  specific keytab entries.  The search order for keytabs to be used
>  for "machine credentials" is now:
>  .br
> +  <HOSTNAME>$@<REALM>
> +.br
>    root/<hostname>@<REALM>
>  .br
>    nfs/<hostname>@<REALM>
> @@ -64,6 +66,9 @@ for "machine credentials" is now:
>    nfs/<anyname>@<REALM>
>  .br
>    host/<anyname>@<REALM>
> +.IP
> +If this search order does not use the correct key then provide a
> +keytab file that contains only correct keys.
>  .TP
>  .B -p path
>  Tells
> 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.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-02-09 16:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-22 19:22 [PATCH] Support AD style kerberos automatically in rpc.gss Jason Gunthorpe
2010-12-23 10:55 ` Timo Aaltonen
2011-01-04 21:32   ` Jason Gunthorpe
2011-01-06 13:12     ` Steve Dickson
2011-02-09 16:34 ` Steve Dickson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.