Blame SOURCES/bind99-rh1214827.patch

900526
From c8cd2cd7f21ce56f93532a6d5f26239e60657acb Mon Sep 17 00:00:00 2001
900526
From: Tomas Hozza <thozza@redhat.com>
900526
Date: Thu, 25 Jun 2015 14:53:31 +0200
900526
Subject: [PATCH] nsupdate: Don't extract REAML from ticket, but leave it up to
900526
 GSSAPI
900526
900526
The current implementation of nsupdate does not work correctly with
900526
GSSAPI in cross realm trust scenarios. The realm is currently
900526
extracted from local kerberos ticket instead of letting GSSAPI to
900526
figure out the realm based on the remote nameserver hostname.
900526
900526
RFC 4752 section 3.1 states that the client should use
900526
GSS_C_NT_HOSTBASED_SERVICE when calling gss_import_name().
900526
900526
nsupdate now leaves the realm detection up to GSSAPI, if the realm is
900526
not specified explicitly using the 'realm' option. If the option is
900526
used, the old behavior is preserved.
900526
900526
Signed-off-by: Tomas Hozza <thozza@redhat.com>
900526
---
900526
 bin/nsupdate/nsupdate.1       |  3 +-
900526
 bin/nsupdate/nsupdate.c       | 72 ++++++++-----------------------------------
900526
 bin/nsupdate/nsupdate.docbook |  2 +-
900526
 bin/nsupdate/nsupdate.html    |  2 +-
900526
 bin/tests/dst/gsstest.c       |  4 +--
900526
 lib/dns/gssapictx.c           | 16 +++++++---
900526
 lib/dns/include/dns/tkey.h    | 24 +++++++++------
900526
 lib/dns/include/dst/gssapi.h  |  8 +++--
900526
 lib/dns/tkey.c                | 28 +++++++++--------
900526
 9 files changed, 65 insertions(+), 94 deletions(-)
900526
900526
diff --git a/bin/nsupdate/nsupdate.1 b/bin/nsupdate/nsupdate.1
900526
index 1e2dcaf..c847fb8 100644
900526
--- a/bin/nsupdate/nsupdate.1
900526
+++ b/bin/nsupdate/nsupdate.1
900526
@@ -259,8 +259,7 @@ on the commandline.
900526
 .RS 4
900526
 When using GSS\-TSIG use
900526
 \fIrealm_name\fR
900526
-rather than the default realm in
900526
-\fIkrb5.conf\fR. If no realm is specified the saved realm is cleared.
900526
+rather than leaving the realm detection up to GSSAPI. If no realm is specified the saved realm is cleared.
900526
 .RE
900526
 .PP
900526
 \fB[prereq]\fR\fB nxdomain\fR {domain\-name}
900526
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
900526
index b901e03..644e3d9 100644
900526
--- a/bin/nsupdate/nsupdate.c
900526
+++ b/bin/nsupdate/nsupdate.c
900526
@@ -2489,57 +2489,6 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
900526
 
900526
 #ifdef GSSAPI
900526
 
900526
-/*
900526
- * Get the realm from the users kerberos ticket if possible
900526
- */
900526
-static void
900526
-get_ticket_realm(isc_mem_t *mctx)
900526
-{
900526
-	krb5_context ctx;
900526
-	krb5_error_code rc;
900526
-	krb5_ccache ccache;
900526
-	krb5_principal princ;
900526
-	char *name, *ticket_realm;
900526
-
900526
-	rc = krb5_init_context(&ctx;;
900526
-	if (rc != 0)
900526
-		return;
900526
-
900526
-	rc = krb5_cc_default(ctx, &ccache);
900526
-	if (rc != 0) {
900526
-		krb5_free_context(ctx);
900526
-		return;
900526
-	}
900526
-
900526
-	rc = krb5_cc_get_principal(ctx, ccache, &princ);
900526
-	if (rc != 0) {
900526
-		krb5_cc_close(ctx, ccache);
900526
-		krb5_free_context(ctx);
900526
-		return;
900526
-	}
900526
-
900526
-	rc = krb5_unparse_name(ctx, princ, &name);
900526
-	if (rc != 0) {
900526
-		krb5_free_principal(ctx, princ);
900526
-		krb5_cc_close(ctx, ccache);
900526
-		krb5_free_context(ctx);
900526
-		return;
900526
-	}
900526
-
900526
-	ticket_realm = strrchr(name, '@');
900526
-	if (ticket_realm != NULL) {
900526
-		realm = isc_mem_strdup(mctx, ticket_realm);
900526
-	}
900526
-
900526
-	free(name);
900526
-	krb5_free_principal(ctx, princ);
900526
-	krb5_cc_close(ctx, ccache);
900526
-	krb5_free_context(ctx);
900526
-	if (realm != NULL && debugging)
900526
-		fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
900526
-}
900526
-
900526
-
900526
 static void
900526
 start_gssrequest(dns_name_t *master) {
900526
 	gss_ctx_id_t context;
900526
@@ -2580,11 +2529,15 @@ start_gssrequest(dns_name_t *master) {
900526
 	dns_fixedname_init(&fname);
900526
 	servname = dns_fixedname_name(&fname);
900526
 
900526
-	if (realm == NULL)
900526
-		get_ticket_realm(mctx);
900526
-
900526
-	result = isc_string_printf(servicename, sizeof(servicename),
900526
-				   "DNS/%s%s", namestr, realm ? realm : "");
900526
+	if (realm != NULL) {
900526
+		/* Use explicit REALM passed as argument */
900526
+		result = isc_string_printf(servicename, sizeof(servicename),
900526
+				   "DNS/%s%s", namestr, realm);
900526
+	} else {
900526
+		/* Use service@host as advised in RFC4752 section 3.1 */
900526
+		result = isc_string_printf(servicename, sizeof(servicename),
900526
+				   "DNS@%s", namestr);
900526
+	}
900526
 	if (result != ISC_R_SUCCESS)
900526
 		fatal("isc_string_printf(servicename) failed: %s",
900526
 		      isc_result_totext(result));
900526
@@ -2623,9 +2576,9 @@ start_gssrequest(dns_name_t *master) {
900526
 
900526
 	/* Build first request. */
900526
 	context = GSS_C_NO_CONTEXT;
900526
-	result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
900526
-					&context, use_win2k_gsstsig,
900526
-					mctx, &err_message);
900526
+	result = dns_tkey_buildgssquery(rmsg, keyname, servname,
900526
+					realm != NULL ? ISC_TRUE : ISC_FALSE, NULL, 0,
900526
+					&context, use_win2k_gsstsig, mctx, &err_message);
900526
 	if (result == ISC_R_FAILURE)
900526
 		fatal("tkey query failed: %s",
900526
 		      err_message != NULL ? err_message : "unknown error");
900526
@@ -2765,6 +2718,7 @@ recvgss(isc_task_t *task, isc_event_t *event) {
900526
 
900526
 	tsigkey = NULL;
900526
 	result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
900526
+				       realm != NULL ? ISC_TRUE : ISC_FALSE,
900526
 				       &context, &tsigkey, gssring,
900526
 				       use_win2k_gsstsig,
900526
 				       &err_message);
900526
diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook
900526
index c54211c..bbcc681 100644
900526
--- a/bin/nsupdate/nsupdate.docbook
900526
+++ b/bin/nsupdate/nsupdate.docbook
900526
@@ -418,7 +418,7 @@
900526
           <listitem>
900526
             <para>
900526
 	      When using GSS-TSIG use <parameter>realm_name</parameter> rather
900526
-	      than the default realm in <filename>krb5.conf</filename>.  If no
900526
+	      than leaving the realm detection up to GSSAPI.  If no
900526
 	      realm is specified the saved realm is cleared.
900526
             </para>
900526
           </listitem>
900526
diff --git a/bin/nsupdate/nsupdate.html b/bin/nsupdate/nsupdate.html
900526
index 276d4af..9c0eba0 100644
900526
--- a/bin/nsupdate/nsupdate.html
900526
+++ b/bin/nsupdate/nsupdate.html
900526
@@ -327,7 +327,7 @@
900526
           
900526
 

900526
 	      When using GSS-TSIG use realm_name rather
900526
-	      than the default realm in krb5.conf.  If no
900526
+	      than leaving the realm detection up to GSSAPI.  If no
900526
 	      realm is specified the saved realm is cleared.
900526
             

900526
 
900526
diff --git a/bin/tests/dst/gsstest.c b/bin/tests/dst/gsstest.c
900526
index c1296f7..7c85d0b 100755
900526
--- a/bin/tests/dst/gsstest.c
900526
+++ b/bin/tests/dst/gsstest.c
900526
@@ -309,7 +309,7 @@ initctx2(isc_task_t *task, isc_event_t *event) {
900526
 	printf("Received token from server, calling gss_init_sec_context()\n");
900526
 	isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
900526
 	result = dns_tkey_processgssresponse(query, response,
900526
-					     dns_fixedname_name(&gssname),
900526
+					     dns_fixedname_name(&gssname), ISC_FALSE,
900526
 					     &gssctx, &outtoken,
900526
 					     &tsigkey, ring, NULL);
900526
 	gssctx = *gssctxp;
900526
@@ -396,7 +396,7 @@ initctx1(isc_task_t *task, isc_event_t *event) {
900526
 	printf("Calling gss_init_sec_context()\n");
900526
 	gssctx = GSS_C_NO_CONTEXT;
900526
 	result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
900526
-					dns_fixedname_name(&gssname),
900526
+					dns_fixedname_name(&gssname), ISC_FALSE,
900526
 					NULL, 36000, &gssctx, ISC_TRUE,
900526
 					mctx, NULL);
900526
 	CHECK("dns_tkey_buildgssquery", result);
900526
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
900526
index aeaeb85..21222e0 100644
900526
--- a/lib/dns/gssapictx.c
900526
+++ b/lib/dns/gssapictx.c
900526
@@ -558,14 +558,15 @@ gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor,
900526
 #endif
900526
 
900526
 isc_result_t
900526
-dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
900526
-		   isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
900526
-		   isc_mem_t *mctx, char **err_message)
900526
+dst_gssapi_initctx(dns_name_t *name, isc_boolean_t explicit_realm,
900526
+		   isc_buffer_t *intoken, isc_buffer_t *outtoken,
900526
+		   gss_ctx_id_t *gssctx, isc_mem_t *mctx, char **err_message)
900526
 {
900526
 #ifdef GSSAPI
900526
 	isc_region_t r;
900526
 	isc_buffer_t namebuf;
900526
 	gss_name_t gname;
900526
+	gss_OID gname_type;
900526
 	OM_uint32 gret, minor, ret_flags, flags;
900526
 	gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
900526
 	isc_result_t result;
900526
@@ -580,7 +581,13 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
900526
 	name_to_gbuffer(name, &namebuf, &gnamebuf);
900526
 
900526
 	/* Get the name as a GSS name */
900526
-	gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
900526
+	if (explicit_realm == ISC_TRUE) {
900526
+		gname_type = GSS_C_NO_OID;
900526
+	} else {
900526
+		gname_type = GSS_C_NT_HOSTBASED_SERVICE;
900526
+	}
900526
+
900526
+	gret = gss_import_name(&minor, &gnamebuf, gname_type, &gname);
900526
 	if (gret != GSS_S_COMPLETE) {
900526
 		gss_err_message(mctx, gret, minor, err_message);
900526
 		result = ISC_R_FAILURE;
900526
@@ -642,6 +649,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
900526
 	return (result);
900526
 #else
900526
 	UNUSED(name);
900526
+	UNUSED(explicit_realm);
900526
 	UNUSED(intoken);
900526
 	UNUSED(outtoken);
900526
 	UNUSED(gssctx);
900526
diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h
900526
index 0dcec1e..a0e6c2a 100644
900526
--- a/lib/dns/include/dns/tkey.h
900526
+++ b/lib/dns/include/dns/tkey.h
900526
@@ -123,9 +123,9 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
900526
 
900526
 isc_result_t
900526
 dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
900526
-		       isc_buffer_t *intoken, isc_uint32_t lifetime,
900526
-		       gss_ctx_id_t *context, isc_boolean_t win2k,
900526
-		       isc_mem_t *mctx, char **err_message);
900526
+		       isc_boolean_t explicit_realm, isc_buffer_t *intoken,
900526
+		       isc_uint32_t lifetime, gss_ctx_id_t *context,
900526
+		       isc_boolean_t win2k, isc_mem_t *mctx, char **err_message);
900526
 /*%<
900526
  *	Builds a query containing a TKEY that will generate a GSSAPI context.
900526
  *	The key is requested to have the specified lifetime (in seconds).
900526
@@ -134,6 +134,8 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
900526
  *\li		'msg'	  is a valid message
900526
  *\li		'name'	  is a valid name
900526
  *\li		'gname'	  is a valid name
900526
+ *\li		'explicit_realm' ISC_TRUE if an explicit realm is used,
900526
+ *			  ISC_FALSE if the realm detection is left up to GSSAPI.
900526
  *\li		'context' is a pointer to a valid gss_ctx_id_t
900526
  *			  (which may have the value GSS_C_NO_CONTEXT)
900526
  *\li		'win2k'   when true says to turn on some hacks to work
900526
@@ -188,9 +190,10 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 
900526
 isc_result_t
900526
 dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
-			    dns_name_t *gname, gss_ctx_id_t *context,
900526
-			    isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
900526
-			    dns_tsig_keyring_t *ring, char **err_message);
900526
+			    dns_name_t *gname, isc_boolean_t explicit_realm,
900526
+			    gss_ctx_id_t *context, isc_buffer_t *outtoken,
900526
+			    dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
900526
+			    char **err_message);
900526
 /*%<
900526
  * XXX
900526
  */
900526
@@ -216,9 +219,10 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 
900526
 isc_result_t
900526
 dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
900526
-		      dns_name_t *server, gss_ctx_id_t *context,
900526
-		      dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
900526
-		      isc_boolean_t win2k, char **err_message);
900526
+		      dns_name_t *server, isc_boolean_t explicit_realm,
900526
+		      gss_ctx_id_t *context, dns_tsigkey_t **outkey,
900526
+		      dns_tsig_keyring_t *ring, isc_boolean_t win2k,
900526
+		      char **err_message);
900526
 
900526
 /*
900526
  *	Client side negotiation of GSS-TSIG.  Process the response
900526
@@ -231,6 +235,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
900526
  *			     it will be filled with the new message to send
900526
  *		'rmsg'    is a valid message, the incoming TKEY message
900526
  *		'server'  is the server name
900526
+ *		'explicit_realm' ISC_TRUE if an explicit realm is used,
900526
+ *			      ISC_FALSE if the realm detection is left up to GSSAPI.
900526
  *		'context' is the input context handle
900526
  *		'outkey'  receives the established key, if non-NULL;
900526
  *			      if non-NULL must point to NULL
900526
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
900526
index 1e81a55..d093fa3 100644
900526
--- a/lib/dns/include/dst/gssapi.h
900526
+++ b/lib/dns/include/dst/gssapi.h
900526
@@ -93,15 +93,17 @@ dst_gssapi_releasecred(gss_cred_id_t *cred);
900526
  */
900526
 
900526
 isc_result_t
900526
-dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
900526
-		   isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
900526
-		   isc_mem_t *mctx, char **err_message);
900526
+dst_gssapi_initctx(dns_name_t *name, isc_boolean_t explicit_realm,
900526
+		   isc_buffer_t *intoken, isc_buffer_t *outtoken,
900526
+		   gss_ctx_id_t *gssctx, isc_mem_t *mctx, char **err_message);
900526
 /*
900526
  *	Initiates a GSS context.
900526
  *
900526
  *	Requires:
900526
  * 	'name'     is a valid name, preferably one known by the GSS
900526
  * 	provider
900526
+ * 	'explicit_realm' True if the REALM is explicitly included in the 'name',
900526
+ *  	   otherwise leave the REALM detection up to GSSAPI
900526
  * 	'intoken'  is a token received from the acceptor, or NULL if
900526
  *		   there isn't one
900526
  * 	'outtoken' is a buffer to receive the token generated by
900526
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
900526
index 20c98e5..3463d3a 100644
900526
--- a/lib/dns/tkey.c
900526
+++ b/lib/dns/tkey.c
900526
@@ -1016,9 +1016,9 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
900526
 
900526
 isc_result_t
900526
 dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
900526
-		       isc_buffer_t *intoken, isc_uint32_t lifetime,
900526
-		       gss_ctx_id_t *context, isc_boolean_t win2k,
900526
-		       isc_mem_t *mctx, char **err_message)
900526
+		       isc_boolean_t explicit_realm, isc_buffer_t *intoken,
900526
+		       isc_uint32_t lifetime, gss_ctx_id_t *context,
900526
+		       isc_boolean_t win2k, isc_mem_t *mctx, char **err_message)
900526
 {
900526
 	dns_rdata_tkey_t tkey;
900526
 	isc_result_t result;
900526
@@ -1035,7 +1035,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
900526
 	REQUIRE(mctx != NULL);
900526
 
900526
 	isc_buffer_init(&token, array, sizeof(array));
900526
-	result = dst_gssapi_initctx(gname, NULL, &token, context,
900526
+	result = dst_gssapi_initctx(gname, explicit_realm, NULL, &token, context,
900526
 				    mctx, err_message);
900526
 	if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
900526
 		return (result);
900526
@@ -1251,9 +1251,10 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 
900526
 isc_result_t
900526
 dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
-			    dns_name_t *gname, gss_ctx_id_t *context,
900526
-			    isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
900526
-			    dns_tsig_keyring_t *ring, char **err_message)
900526
+			    dns_name_t *gname, isc_boolean_t explicit_realm,
900526
+			    gss_ctx_id_t *context, isc_buffer_t *outtoken,
900526
+			    dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
900526
+			    char **err_message)
900526
 {
900526
 	dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
900526
 	dns_name_t *tkeyname;
900526
@@ -1304,7 +1305,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 
900526
 	isc_buffer_init(outtoken, array, sizeof(array));
900526
 	isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
900526
-	RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context,
900526
+	RETERR(dst_gssapi_initctx(gname, explicit_realm, &intoken, outtoken, context,
900526
 				  ring->mctx, err_message));
900526
 
900526
 	RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
900526
@@ -1384,9 +1385,10 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 
900526
 isc_result_t
900526
 dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
900526
-		      dns_name_t *server, gss_ctx_id_t *context,
900526
-		      dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
900526
-		      isc_boolean_t win2k, char **err_message)
900526
+		      dns_name_t *server, isc_boolean_t explicit_realm,
900526
+		      gss_ctx_id_t *context, dns_tsigkey_t **outkey,
900526
+		      dns_tsig_keyring_t *ring, isc_boolean_t win2k,
900526
+		      char **err_message)
900526
 {
900526
 	dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
900526
 	dns_name_t *tkeyname;
900526
@@ -1430,8 +1432,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
900526
 	isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
900526
 	isc_buffer_init(&outtoken, array, sizeof(array));
900526
 
900526
-	result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
900526
-				    ring->mctx, err_message);
900526
+	result = dst_gssapi_initctx(server, explicit_realm, &intoken, &outtoken,
900526
+					context, ring->mctx, err_message);
900526
 	if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
900526
 		return (result);
900526
 
900526
-- 
900526
2.4.3
900526