diff --git a/lib/gssapi/spnego/accept_sec_context.c b/lib/gssapi/spnego/accept_sec_context.c index cf7e452b0..00d395d42 100644 --- a/lib/gssapi/spnego/accept_sec_context.c +++ b/lib/gssapi/spnego/accept_sec_context.c @@ -91,17 +91,23 @@ static OM_uint32 send_supported_mechs (OM_uint32 *minor_status, gss_buffer_t output_token) { - NegotiationToken nt; + NegotiationTokenWin nt; + char hostname[MAXHOSTNAMELEN], *p; + gss_buffer_desc name_buf; + gss_OID name_type; + gss_name_t target_princ; + gss_name_t canon_princ; + OM_uint32 minor; size_t buf_len; gss_buffer_desc data; OM_uint32 ret; memset(&nt, 0, sizeof(nt)); - nt.element = choice_NegotiationToken_negTokenInit; + nt.element = choice_NegotiationTokenWin_negTokenInit; nt.u.negTokenInit.reqFlags = NULL; nt.u.negTokenInit.mechToken = NULL; - nt.u.negTokenInit.mechListMIC = NULL; + nt.u.negTokenInit.negHints = NULL; ret = _gss_spnego_indicate_mechtypelist(minor_status, GSS_C_NO_NAME, acceptor_approved, 1, NULL, @@ -110,10 +116,81 @@ send_supported_mechs (OM_uint32 *minor_status, return ret; } - ASN1_MALLOC_ENCODE(NegotiationToken, data.value, data.length, - &nt, &buf_len, ret); + memset(&target_princ, 0, sizeof(target_princ)); + if (gethostname(hostname, sizeof(hostname) - 1) != 0) { + *minor_status = errno; + free_NegotiationTokenWin(&nt); + return GSS_S_FAILURE; + } + + /* Send the constructed SAM name for this host */ + for (p = hostname; *p != '\0' && *p != '.'; p++) { + *p = toupper((unsigned char)*p); + } + *p++ = '$'; + *p = '\0'; + + name_buf.length = strlen(hostname); + name_buf.value = hostname; + + ret = gss_import_name(minor_status, &name_buf, + GSS_C_NO_OID, + &target_princ); + if (ret != GSS_S_COMPLETE) { + free_NegotiationTokenWin(&nt); + return ret; + } + + name_buf.length = 0; + name_buf.value = NULL; + + /* Canonicalize the name using the preferred mechanism */ + ret = gss_canonicalize_name(minor_status, + target_princ, + GSS_C_NO_OID, + &canon_princ); + if (ret != GSS_S_COMPLETE) { + free_NegotiationTokenWin(&nt); + gss_release_name(&minor, &target_princ); + return ret; + } + + ret = gss_display_name(minor_status, canon_princ, + &name_buf, &name_type); + if (ret != GSS_S_COMPLETE) { + free_NegotiationTokenWin(&nt); + gss_release_name(&minor, &canon_princ); + gss_release_name(&minor, &target_princ); + return ret; + } + + gss_release_name(&minor, &canon_princ); + gss_release_name(&minor, &target_princ); + + ALLOC(nt.u.negTokenInit.negHints, 1); + if (nt.u.negTokenInit.negHints == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegotiationTokenWin(&nt); + return GSS_S_FAILURE; + } + + ALLOC(nt.u.negTokenInit.negHints->hintName, 1); + if (nt.u.negTokenInit.negHints->hintName == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegotiationTokenWin(&nt); + return GSS_S_FAILURE; + } + + *(nt.u.negTokenInit.negHints->hintName) = name_buf.value; + name_buf.value = NULL; + nt.u.negTokenInit.negHints->hintAddress = NULL; + + ASN1_MALLOC_ENCODE(NegotiationTokenWin, + data.value, data.length, &nt, &buf_len, ret); + free_NegotiationTokenWin(&nt); if (ret) { - free_NegotiationToken(&nt); return ret; } if (data.length != buf_len) @@ -122,7 +199,6 @@ send_supported_mechs (OM_uint32 *minor_status, ret = gss_encapsulate_token(&data, GSS_SPNEGO_MECHANISM, output_token); free (data.value); - free_NegotiationToken(&nt); if (ret != GSS_S_COMPLETE) return ret;