]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4413. [bug] GSSAPI negotiation could fail if GSS_S_CONTINUE_NEEDED
authorMark Andrews <marka@isc.org>
Thu, 14 Jul 2016 05:06:28 +0000 (15:06 +1000)
committerMark Andrews <marka@isc.org>
Thu, 14 Jul 2016 05:06:28 +0000 (15:06 +1000)
                        was returned. [RT #42733]

CHANGES
bin/nsupdate/nsupdate.c
lib/dns/gssapictx.c
lib/dns/include/dst/gssapi.h
lib/dns/spnego.c
lib/dns/tkey.c

diff --git a/CHANGES b/CHANGES
index dfda273cef015b7d67c3c0651aa62f49077c6a5a..cf4356d188b264382e10cba811a12540665d262c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4413.  [bug]           GSSAPI negotiation could fail if GSS_S_CONTINUE_NEEDED
+                       was returned. [RT #42733]
+
 4412.  [cleanup]       Make fixes for GCC 6. ISC_OFFSET_MAXIMUM macro was
                        removed. [RT #42721]
 
index 96fb76b1197449341820f4cbbf44c491398c86f9..894bddbee8c920e59718f942546f4e4e525fbfd9 100644 (file)
@@ -2976,13 +2976,15 @@ recvgss(isc_task_t *task, isc_event_t *event) {
        tsigkey = NULL;
        result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
                                       &context, &tsigkey, gssring,
-                                      use_win2k_gsstsig,
-                                      &err_message);
+                                      use_win2k_gsstsig, &err_message);
        switch (result) {
 
        case DNS_R_CONTINUE:
+               dns_message_destroy(&rcvmsg);
+               dns_request_destroy(&request);
                send_gssrequest(kserver, tsigquery, &request, context);
-               break;
+               ddebug("Out of recvgss");
+               return;
 
        case ISC_R_SUCCESS:
                /*
@@ -3019,7 +3021,7 @@ recvgss(isc_task_t *task, isc_event_t *event) {
                break;
 
        default:
-               fatal("dns_tkey_negotiategss: %s %s",
+               fatal("dns_tkey_gssnegotiate: %s %s",
                      isc_result_totext(result),
                      err_message != NULL ? err_message : "");
        }
index bbcaf7c073cbe9571ccc7acf0529e61fb492ee3f..3b92805cb1186ca3e636b81d3f45e16e545786bd 100644 (file)
@@ -712,10 +712,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
 
        switch (gret) {
        case GSS_S_COMPLETE:
-               result = ISC_R_SUCCESS;
-               break;
        case GSS_S_CONTINUE_NEEDED:
-               result = DNS_R_CONTINUE;
                break;
        case GSS_S_DEFECTIVE_TOKEN:
        case GSS_S_DEFECTIVE_CREDENTIAL:
@@ -780,7 +777,8 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
                                        gss_error_tostring(gret, minor, buf,
                                                           sizeof(buf)));
                }
-       }
+       } else
+               result = DNS_R_CONTINUE;
 
        *ctxout = context;
 
index aa2a183c339a8354a361ee31b24cd49c9523924a..c22e8290d3f3dfba031073398852dc53c3c80933 100644 (file)
@@ -136,6 +136,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
  *     Returns:
  *             ISC_R_SUCCESS   msg was successfully updated to include the
  *                             query to be sent
+ *             DNS_R_CONTINUE  transaction still in progress
  *             other           an error occurred while building the message
  */
 
index aa4714e94b74d0f893cbdca25a9b1e9f384213a8..9e367f95933a2cd91a6184e55ff17b789e6ccf24 100644 (file)
@@ -561,7 +561,7 @@ gss_accept_sec_context_spnego(OM_uint32 *minor_status,
                              gss_cred_id_t *delegated_cred_handle)
 {
        NegTokenInit init_token;
-       OM_uint32 major_status;
+       OM_uint32 major_status = GSS_S_COMPLETE;
        OM_uint32 minor_status2;
        gss_buffer_desc ibuf, obuf;
        gss_buffer_t ot = NULL;
@@ -677,7 +677,7 @@ gss_accept_sec_context_spnego(OM_uint32 *minor_status,
        if (ot != NULL && ot->length != 0U)
                gss_release_buffer(&minor_status2, ot);
 
-       return (ret);
+       return (ret != GSS_S_COMPLETE ? ret : major_status);
 }
 
 /* decapsulate.c */
index d5b866e5d49acc8c099627fcafe468248d25c47b..9e1c6a191eaef289ad72c8172328a0b7e89e5184 100644 (file)
@@ -444,7 +444,8 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
        isc_result_t result = ISC_R_SUCCESS;
        dst_key_t *dstkey = NULL;
        dns_tsigkey_t *tsigkey = NULL;
-       dns_fixedname_t principal;
+       dns_fixedname_t fixed;
+       dns_name_t *principal;
        isc_stdtime_t now;
        isc_region_t intoken;
        isc_buffer_t *outtoken = NULL;
@@ -481,16 +482,15 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
        if (result == ISC_R_SUCCESS)
                gss_ctx = dst_key_getgssctx(tsigkey->key);
 
-       dns_fixedname_init(&principal);
+       dns_fixedname_init(&fixed);
+       principal = dns_fixedname_name(&fixed);
 
        /*
         * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
         */
        result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
-                                     &intoken,
-                                     &outtoken, &gss_ctx,
-                                     dns_fixedname_name(&principal),
-                                     tctx->mctx);
+                                     &intoken, &outtoken, &gss_ctx,
+                                     principal, tctx->mctx);
        if (result == DNS_R_INVALIDTKEY) {
                if (tsigkey != NULL)
                        dns_tsigkey_detach(&tsigkey);
@@ -506,7 +506,10 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
 
        isc_stdtime_get(&now);
 
-       if (tsigkey == NULL) {
+       if (dns_name_countlabels(principal) == 0U) {
+               if (tsigkey != NULL)
+                       dns_tsigkey_detach(&tsigkey);
+       } else if (tsigkey == NULL) {
 #ifdef GSSAPI
                OM_uint32 gret, minor, lifetime;
 #endif
@@ -525,8 +528,7 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
                        expire = now + lifetime;
 #endif
                RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
-                                                dstkey, ISC_TRUE,
-                                                dns_fixedname_name(&principal),
+                                                dstkey, ISC_TRUE, principal,
                                                 now, expire, ring->mctx, ring,
                                                 NULL));
                dst_key_free(&dstkey);
@@ -1262,7 +1264,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
        dst_key_t *dstkey = NULL;
        isc_buffer_t intoken;
        isc_result_t result;
-       unsigned char array[1024];
+       unsigned char array[TEMP_BUFFER_SZ];
 
        REQUIRE(outtoken != NULL);
        REQUIRE(qmsg != NULL);
@@ -1391,11 +1393,11 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
 {
        dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
        dns_name_t *tkeyname;
-       dns_rdata_tkey_t rtkey, qtkey;
+       dns_rdata_tkey_t rtkey, qtkey, tkey;
        isc_buffer_t intoken, outtoken;
        dst_key_t *dstkey = NULL;
        isc_result_t result;
-       unsigned char array[1024];
+       unsigned char array[TEMP_BUFFER_SZ];
        isc_boolean_t freertkey = ISC_FALSE;
 
        REQUIRE(qmsg != NULL);
@@ -1438,6 +1440,38 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
        if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
                return (result);
 
+       if (result == DNS_R_CONTINUE) {
+               dns_fixedname_t fixed;
+
+               dns_fixedname_init(&fixed);
+               dns_name_copy(tkeyname, dns_fixedname_name(&fixed), NULL);
+               tkeyname = dns_fixedname_name(&fixed);
+
+               tkey.common.rdclass = dns_rdataclass_any;
+               tkey.common.rdtype = dns_rdatatype_tkey;
+               ISC_LINK_INIT(&tkey.common, link);
+               tkey.mctx = NULL;
+               dns_name_init(&tkey.algorithm, NULL);
+
+               if (win2k)
+                       dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
+               else
+                       dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
+               tkey.inception = qtkey.inception;
+               tkey.expire = qtkey.expire;
+               tkey.mode = DNS_TKEYMODE_GSSAPI;
+               tkey.error = 0;
+               tkey.key = isc_buffer_base(&outtoken);
+               tkey.keylen = isc_buffer_usedlength(&outtoken);
+               tkey.other = NULL;
+               tkey.otherlen = 0;
+
+               dns_message_reset(qmsg, DNS_MESSAGE_INTENTRENDER);
+               RETERR(buildquery(qmsg, tkeyname, &tkey, win2k));
+               return (DNS_R_CONTINUE);
+       }
+
        RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
                                  &dstkey, NULL));