From 3c1e780ec7e16dc6667402bbc65708bf9a5c062f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Nov 2006 06:59:56 +0000 Subject: r19604: This is a massive commit, and I appologise in advance for it's size. This merges Samba4 with lorikeet-heimdal, which itself has been tracking Heimdal CVS for the past couple of weeks. This is such a big change because Heimdal reorganised it's internal structures, with the mechglue merge, and because many of our 'wishes' have been granted: we now have DCE_STYLE GSSAPI, send_to_kdc hooks and many other features merged into the mainline code. We have adapted to upstream's choice of API in these cases. In gensec_gssapi and gensec_krb5, we either expect a valid PAC, or NO PAC. This matches windows behavour. We also have an option to require the PAC to be present (which allows us to automate the testing of this code). This also includes a restructure of how the kerberos dependencies are handled, due to the fallout of the merge. Andrew Bartlett (This used to be commit 4826f1735197c2a471d771495e6d4c1051b4c471) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 873 +++++++++++++++++++++ source4/heimdal/lib/gssapi/spnego/compat.c | 285 +++++++ source4/heimdal/lib/gssapi/spnego/context_stubs.c | 835 ++++++++++++++++++++ source4/heimdal/lib/gssapi/spnego/cred_stubs.c | 291 +++++++ source4/heimdal/lib/gssapi/spnego/external.c | 89 +++ .../heimdal/lib/gssapi/spnego/init_sec_context.c | 578 ++++++++++++++ source4/heimdal/lib/gssapi/spnego/spnego-private.h | 347 ++++++++ source4/heimdal/lib/gssapi/spnego/spnego.asn1 | 51 ++ source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 96 +++ 9 files changed, 3445 insertions(+) create mode 100644 source4/heimdal/lib/gssapi/spnego/accept_sec_context.c create mode 100644 source4/heimdal/lib/gssapi/spnego/compat.c create mode 100644 source4/heimdal/lib/gssapi/spnego/context_stubs.c create mode 100644 source4/heimdal/lib/gssapi/spnego/cred_stubs.c create mode 100644 source4/heimdal/lib/gssapi/spnego/external.c create mode 100644 source4/heimdal/lib/gssapi/spnego/init_sec_context.c create mode 100644 source4/heimdal/lib/gssapi/spnego/spnego-private.h create mode 100644 source4/heimdal/lib/gssapi/spnego/spnego.asn1 create mode 100644 source4/heimdal/lib/gssapi/spnego/spnego_locl.h (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c new file mode 100644 index 0000000000..8a885a3e2f --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -0,0 +1,873 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: accept_sec_context.c,v 1.6 2006/10/07 22:26:57 lha Exp $"); + +OM_uint32 +_gss_spnego_encode_response(OM_uint32 *minor_status, + const NegTokenResp *resp, + gss_buffer_t data, + u_char **ret_buf) +{ + OM_uint32 ret; + u_char *buf; + size_t buf_size, buf_len; + + buf_size = 1024; + buf = malloc(buf_size); + if (buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + do { + ret = encode_NegTokenResp(buf + buf_size - 1, + buf_size, + resp, &buf_len); + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 1, + &tmp); + if (ret == 0) + buf_len += tmp; + } + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + *minor_status = ENOMEM; + free(buf); + return GSS_S_FAILURE; + } + buf = tmp; + } else { + *minor_status = ret; + free(buf); + return GSS_S_FAILURE; + } + } + } while (ret == ASN1_OVERFLOW); + + data->value = buf + buf_size - buf_len; + data->length = buf_len; + *ret_buf = buf; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +send_reject (OM_uint32 *minor_status, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc data; + u_char *buf; + OM_uint32 ret; + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + *(resp.negResult) = reject; + resp.supportedMech = NULL; + resp.responseToken = NULL; + resp.mechListMIC = NULL; + + ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); + free_NegTokenResp(&resp); + if (ret != GSS_S_COMPLETE) + return ret; + + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + if (ret != GSS_S_COMPLETE) + return ret; + return GSS_S_BAD_MECH; +} + +OM_uint32 +_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, + int includeMSCompatOID, + const gssspnego_cred cred_handle, + MechTypeList *mechtypelist, + gss_OID *preferred_mech) +{ + OM_uint32 ret; + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; + int i, count; + + if (cred_handle != NULL) { + ret = gss_inquire_cred(minor_status, + cred_handle->negotiated_cred_id, + NULL, + NULL, + NULL, + &supported_mechs); + } else { + ret = gss_indicate_mechs(minor_status, &supported_mechs); + } + + if (ret != GSS_S_COMPLETE) { + return ret; + } + + if (supported_mechs->count == 0) { + *minor_status = ENOENT; + gss_release_oid_set(minor_status, &supported_mechs); + return GSS_S_FAILURE; + } + + count = supported_mechs->count; + if (includeMSCompatOID) + count++; + + mechtypelist->len = 0; + mechtypelist->val = calloc(count, sizeof(MechType)); + if (mechtypelist->val == NULL) { + *minor_status = ENOMEM; + gss_release_oid_set(minor_status, &supported_mechs); + return GSS_S_FAILURE; + } + + for (i = 0; i < supported_mechs->count; i++) { + ret = _gss_spnego_add_mech_type(&supported_mechs->elements[i], + includeMSCompatOID, + mechtypelist); + if (ret != 0) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + break; + } + } + + if (ret == GSS_S_COMPLETE && preferred_mech != NULL) { + ret = gss_duplicate_oid(minor_status, + &supported_mechs->elements[0], + preferred_mech); + } + + if (ret != GSS_S_COMPLETE) { + free_MechTypeList(mechtypelist); + mechtypelist->len = 0; + mechtypelist->val = NULL; + } + gss_release_oid_set(minor_status, &supported_mechs); + + return ret; +} + +static OM_uint32 +send_supported_mechs (OM_uint32 *minor_status, + gss_buffer_t output_token) +{ + NegTokenInit ni; + 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 ret, minor; + u_char *buf; + size_t buf_size, buf_len; + gss_buffer_desc data; + + memset(&ni, 0, sizeof(ni)); + + ni.reqFlags = NULL; + ni.mechToken = NULL; + ni.negHints = NULL; + ni.mechListMIC = NULL; + + ret = _gss_spnego_indicate_mechtypelist(minor_status, 1, + NULL, + &ni.mechTypes, NULL); + if (ret != GSS_S_COMPLETE) { + return ret; + } + + memset(&target_princ, 0, sizeof(target_princ)); + if (gethostname(hostname, sizeof(hostname) - 1) != 0) { + *minor_status = errno; + free_NegTokenInit(&ni); + 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) { + 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) { + 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) { + 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(ni.negHints, 1); + if (ni.negHints == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + + ALLOC(ni.negHints->hintName, 1); + if (ni.negHints->hintName == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + + *(ni.negHints->hintName) = name_buf.value; + name_buf.value = NULL; + ni.negHints->hintAddress = NULL; + + buf_size = 1024; + buf = malloc(buf_size); + if (buf == NULL) { + free_NegTokenInit(&ni); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + do { + ret = encode_NegTokenInit(buf + buf_size - 1, + buf_size, + &ni, &buf_len); + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 0, + &tmp); + if (ret == 0) + buf_len += tmp; + } + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + *minor_status = ENOMEM; + free(buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + buf = tmp; + } else { + *minor_status = ret; + free(buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + } + } while (ret == ASN1_OVERFLOW); + + data.value = buf + buf_size - buf_len; + data.length = buf_len; + + ret = gss_encapsulate_token(&data, + GSS_SPNEGO_MECHANISM, + output_token); + free (buf); + free_NegTokenInit (&ni); + + if (ret != GSS_S_COMPLETE) + return ret; + + *minor_status = 0; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +send_accept (OM_uint32 *minor_status, + gssspnego_ctx context_handle, + gss_buffer_t mech_token, + int initial_response, + gss_buffer_t mech_buf, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc data; + u_char *buf; + OM_uint32 ret; + gss_buffer_desc mech_mic_buf; + + memset(&resp, 0, sizeof(resp)); + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (context_handle->open) { + if (mech_token != GSS_C_NO_BUFFER + && mech_token->length != 0 + && mech_buf != GSS_C_NO_BUFFER) + *(resp.negResult) = accept_incomplete; + else + *(resp.negResult) = accept_completed; + } else { + if (initial_response && context_handle->require_mic) + *(resp.negResult) = request_mic; + else + *(resp.negResult) = accept_incomplete; + } + + if (initial_response) { + ALLOC(resp.supportedMech, 1); + if (resp.supportedMech == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = der_get_oid(context_handle->preferred_mech_type->elements, + context_handle->preferred_mech_type->length, + resp.supportedMech, + NULL); + if (ret) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } else { + resp.supportedMech = NULL; + } + + if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { + ALLOC(resp.responseToken, 1); + if (resp.responseToken == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + resp.responseToken->length = mech_token->length; + resp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + } else { + resp.responseToken = NULL; + } + + if (mech_buf != GSS_C_NO_BUFFER) { + ALLOC(resp.mechListMIC, 1); + if (resp.mechListMIC == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = gss_get_mic(minor_status, + context_handle->negotiated_ctx_id, + 0, + mech_buf, + &mech_mic_buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + resp.mechListMIC->length = mech_mic_buf.length; + resp.mechListMIC->data = mech_mic_buf.value; + } else + resp.mechListMIC = NULL; + + ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + /* + * The response should not be encapsulated, because + * it is a SubsequentContextToken (note though RFC 1964 + * specifies encapsulation for all _Kerberos_ tokens). + */ + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + ret = (*(resp.negResult) == accept_completed) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + free_NegTokenResp(&resp); + return ret; +} + + +static OM_uint32 +verify_mechlist_mic + (OM_uint32 *minor_status, + gssspnego_ctx context_handle, + gss_buffer_t mech_buf, + heim_octet_string *mechListMIC + ) +{ + OM_uint32 ret; + gss_buffer_desc mic_buf; + + if (context_handle->verified_mic) { + /* This doesn't make sense, we've already verified it? */ + *minor_status = 0; + return GSS_S_DUPLICATE_TOKEN; + } + + if (mechListMIC == NULL) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + mic_buf.length = mechListMIC->length; + mic_buf.value = mechListMIC->data; + + ret = gss_verify_mic(minor_status, + context_handle->negotiated_ctx_id, + mech_buf, + &mic_buf, + NULL); + + if (ret != GSS_S_COMPLETE) + ret = GSS_S_DEFECTIVE_TOKEN; + + return ret; +} + +OM_uint32 +_gss_spnego_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + OM_uint32 ret, ret2, minor; + NegTokenInit ni; + NegTokenResp na; + size_t ni_len, na_len; + int i; + gss_buffer_desc data; + size_t len, taglen; + int initialToken; + unsigned int negResult = accept_incomplete; + gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; + gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; + gss_buffer_desc mech_buf; + gss_OID preferred_mech_type = GSS_C_NO_OID; + gssspnego_ctx ctx; + gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; + + *minor_status = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + + if (ret_flags != NULL) + *ret_flags = 0; + + if (time_rec != NULL) + *time_rec = 0; + + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + mech_buf.value = NULL; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gss_spnego_alloc_sec_context(minor_status, + context_handle); + if (ret != GSS_S_COMPLETE) + return ret; + + if (input_token_buffer->length == 0) { + return send_supported_mechs (minor_status, + output_token); + } + } + + ctx = (gssspnego_ctx)*context_handle; + + /* + * The GSS-API encapsulation is only present on the initial + * context token (negTokenInit). + */ + ret = gss_decapsulate_token (input_token_buffer, + GSS_SPNEGO_MECHANISM, + &data); + initialToken = (ret == GSS_S_COMPLETE); + + if (!initialToken) { + data.value = input_token_buffer->value; + data.length = input_token_buffer->length; + } + + ret = der_match_tag_and_length(data.value, data.length, + ASN1_C_CONTEXT, CONS, + initialToken ? 0 : 1, + &len, &taglen); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (len > data.length - taglen) { + *minor_status = ASN1_OVERRUN; + return GSS_S_FAILURE; + } + + if (initialToken) { + ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, + len, &ni, &ni_len); + } else { + ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, + len, &na, &na_len); + } + if (ret) { + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (!initialToken && na.negResult != NULL) { + negResult = *(na.negResult); + } + + if (negResult == reject || negResult == request_mic) { + /* request_mic should only be sent by acceptor */ + free_NegTokenResp(&na); + return GSS_S_DEFECTIVE_TOKEN; + } + + if (initialToken) { + for (i = 0; i < ni.mechTypes.len; ++i) { + /* Call glue layer to find first mech we support */ + ret = _gss_spnego_select_mech(minor_status, &ni.mechTypes.val[i], + &preferred_mech_type); + if (ret == 0) + break; + } + if (preferred_mech_type == GSS_C_NO_OID) { + free_NegTokenInit(&ni); + return GSS_S_BAD_MECH; + } + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (initialToken) { + ctx->preferred_mech_type = preferred_mech_type; + ctx->initiator_mech_types.len = ni.mechTypes.len; + ctx->initiator_mech_types.val = ni.mechTypes.val; + ni.mechTypes.len = 0; + ni.mechTypes.val = NULL; + } + + { + gss_buffer_desc ibuf, obuf; + int require_mic, verify_mic, get_mic; + int require_response; + heim_octet_string *mic; + + if (initialToken) { + if (ni.mechToken != NULL) { + ibuf.length = ni.mechToken->length; + ibuf.value = ni.mechToken->data; + mech_input_token = &ibuf; + } + } else { + if (na.responseToken != NULL) { + ibuf.length = na.responseToken->length; + ibuf.value = na.responseToken->data; + mech_input_token = &ibuf; + } + } + + if (mech_input_token != GSS_C_NO_BUFFER) { + gss_cred_id_t mech_cred; + gss_cred_id_t mech_delegated_cred; + gss_cred_id_t *mech_delegated_cred_p; + + if (acceptor_cred != NULL) + mech_cred = acceptor_cred->negotiated_cred_id; + else + mech_cred = GSS_C_NO_CREDENTIAL; + + if (delegated_cred_handle != NULL) { + mech_delegated_cred = GSS_C_NO_CREDENTIAL; + mech_delegated_cred_p = &mech_delegated_cred; + } else { + mech_delegated_cred_p = NULL; + } + + if (ctx->mech_src_name != GSS_C_NO_NAME) + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) + _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + + ret = gss_accept_sec_context(&minor, + &ctx->negotiated_ctx_id, + mech_cred, + mech_input_token, + input_chan_bindings, + &ctx->mech_src_name, + &ctx->negotiated_mech_type, + &obuf, + &ctx->mech_flags, + &ctx->mech_time_rec, + mech_delegated_cred_p); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + if (mech_delegated_cred_p != NULL && + mech_delegated_cred != GSS_C_NO_CREDENTIAL) { + ret2 = _gss_spnego_alloc_cred(minor_status, + mech_delegated_cred, + &ctx->delegated_cred_id); + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + } + mech_output_token = &obuf; + } + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + if (initialToken) + free_NegTokenInit(&ni); + else + free_NegTokenResp(&na); + send_reject (minor_status, output_token); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + if (ret == GSS_S_COMPLETE) + ctx->open = 1; + } else + ret = GSS_S_COMPLETE; + + ret2 = _gss_spnego_require_mechlist_mic(minor_status, + ctx, + &require_mic); + if (ret2) + goto out; + + ctx->require_mic = require_mic; + + mic = initialToken ? ni.mechListMIC : na.mechListMIC; + if (mic != NULL) + require_mic = 1; + + if (ctx->open && require_mic) { + if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ + verify_mic = 1; + get_mic = 0; + } else if (mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length == 0) { /* Odd */ + get_mic = verify_mic = 1; + } else { /* Even/One */ + verify_mic = 0; + get_mic = 1; + } + + if (verify_mic || get_mic) { + int eret; + size_t buf_len; + + ASN1_MALLOC_ENCODE(MechTypeList, + mech_buf.value, mech_buf.length, + &ctx->initiator_mech_types, &buf_len, eret); + if (eret) { + ret2 = GSS_S_FAILURE; + *minor_status = eret; + goto out; + } + if (mech_buf.length != buf_len) + abort(); + } + + if (verify_mic) { + ret2 = verify_mechlist_mic(minor_status, ctx, &mech_buf, mic); + if (ret2) { + if (get_mic) + send_reject (minor_status, output_token); + goto out; + } + + ctx->verified_mic = 1; + } + } else + verify_mic = get_mic = 0; + + if (ctx->mech_flags & GSS_C_DCE_STYLE) + require_response = (negResult != accept_completed); + else + require_response = 0; + + /* + * Check whether we need to send a result: there should be only + * one accept_completed response sent in the entire negotiation + */ + if ((mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length != 0) + || require_response + || get_mic) { + ret2 = send_accept (minor_status, + ctx, + mech_output_token, + initialToken, + get_mic ? &mech_buf : NULL, + output_token); + if (ret2) + goto out; + } + + out: + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + if (mech_output_token != NULL) + gss_release_buffer(&minor, mech_output_token); + if (mech_buf.value != NULL) + free(mech_buf.value); + if (initialToken) + free_NegTokenInit(&ni); + else + free_NegTokenResp(&na); + } + + if (ret == GSS_S_COMPLETE) { + if (src_name != NULL) { + ret2 = gss_duplicate_name(minor_status, + ctx->mech_src_name, + src_name); + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + } + if (delegated_cred_handle != NULL) { + *delegated_cred_handle = ctx->delegated_cred_id; + ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; + } + } + + if (mech_type != NULL) + *mech_type = ctx->negotiated_mech_type; + if (ret_flags != NULL) + *ret_flags = ctx->mech_flags; + if (time_rec != NULL) + *time_rec = ctx->mech_time_rec; + + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + _gss_spnego_internal_delete_sec_context(&minor, context_handle, + GSS_C_NO_BUFFER); + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c new file mode 100644 index 0000000000..aeae088258 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: compat.c,v 1.6 2006/10/07 22:26:59 lha Exp $"); + +/* + * Apparently Microsoft got the OID wrong, and used + * 1.2.840.48018.1.2.2 instead. We need both this and + * the correct Kerberos OID here in order to deal with + * this. Because this is manifest in SPNEGO only I'd + * prefer to deal with this here rather than inside the + * Kerberos mechanism. + */ +static gss_OID_desc gss_mskrb_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"}; + +static gss_OID_desc gss_krb5_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +/* + * Allocate a SPNEGO context handle + */ +OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status, + gss_ctx_id_t *context_handle) +{ + gssspnego_ctx ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx->initiator_mech_types.len = 0; + ctx->initiator_mech_types.val = NULL; + ctx->preferred_mech_type = GSS_C_NO_OID; + ctx->negotiated_mech_type = GSS_C_NO_OID; + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + /* + * Cache these so we can return them before returning + * GSS_S_COMPLETE, even if the mechanism has itself + * completed earlier + */ + ctx->mech_flags = 0; + ctx->mech_time_rec = 0; + ctx->mech_src_name = GSS_C_NO_NAME; + ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; + + ctx->open = 0; + ctx->local = 0; + ctx->require_mic = 0; + ctx->verified_mic = 0; + + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + +/* + * Free a SPNEGO context handle. The caller must have acquired + * the lock before this is called. + */ +OM_uint32 _gss_spnego_internal_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 ret, minor; + + *minor_status = 0; + + if (context_handle == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + ctx = (gssspnego_ctx)*context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + if (ctx == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (ctx->initiator_mech_types.val != NULL) + free_MechTypeList(&ctx->initiator_mech_types); + + _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + + gss_release_oid(&minor, &ctx->preferred_mech_type); + ctx->negotiated_mech_type = GSS_C_NO_OID; + + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { + ret = gss_delete_sec_context(minor_status, + &ctx->negotiated_ctx_id, + output_token); + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + } else { + ret = GSS_S_COMPLETE; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + free(ctx); + *context_handle = NULL; + + return ret; +} + +/* + * For compatability with the Windows SPNEGO implementation, the + * default is to ignore the mechListMIC unless CFX is used and + * a non-preferred mechanism was negotiated + */ + +OM_uint32 +_gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, + gssspnego_ctx ctx, + int *require_mic) +{ + gss_buffer_set_t buffer_set = GSS_C_NO_BUFFER_SET; + OM_uint32 minor; + + *minor_status = 0; + *require_mic = 0; + + if (ctx == NULL) { + return GSS_S_COMPLETE; + } + + if (ctx->require_mic) { + /* Acceptor requested it: mandatory to honour */ + *require_mic = 1; + return GSS_S_COMPLETE; + } + + /* + * Check whether peer indicated implicit support for updated SPNEGO + * (eg. in the Kerberos case by using CFX) + */ + if (gss_inquire_sec_context_by_oid(&minor, ctx->negotiated_ctx_id, + GSS_C_PEER_HAS_UPDATED_SPNEGO, + &buffer_set) == GSS_S_COMPLETE) { + *require_mic = 1; + gss_release_buffer_set(&minor, &buffer_set); + } + + /* Safe-to-omit MIC rules follow */ + if (*require_mic) { + if (gss_oid_equal(ctx->negotiated_mech_type, ctx->preferred_mech_type)) { + *require_mic = 0; + } else if (gss_oid_equal(ctx->negotiated_mech_type, &gss_krb5_mechanism_oid_desc) && + gss_oid_equal(ctx->preferred_mech_type, &gss_mskrb_mechanism_oid_desc)) { + *require_mic = 0; + } + } + + return GSS_S_COMPLETE; +} + +int _gss_spnego_add_mech_type(gss_OID mech_type, + int includeMSCompatOID, + MechTypeList *mechtypelist) +{ + int ret; + + if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) + return 0; + + if (includeMSCompatOID && + gss_oid_equal(mech_type, &gss_krb5_mechanism_oid_desc)) { + ret = der_get_oid(gss_mskrb_mechanism_oid_desc.elements, + gss_mskrb_mechanism_oid_desc.length, + &mechtypelist->val[mechtypelist->len], + NULL); + if (ret) + return ret; + mechtypelist->len++; + } + ret = der_get_oid(mech_type->elements, + mech_type->length, + &mechtypelist->val[mechtypelist->len], + NULL); + if (ret) + return ret; + mechtypelist->len++; + + return 0; +} + +OM_uint32 +_gss_spnego_select_mech(OM_uint32 *minor_status, + MechType *mechType, + gss_OID *mech_p) +{ + char mechbuf[64]; + size_t mech_len; + gss_OID_desc oid; + OM_uint32 ret; + + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + mechType, + &mech_len); + if (ret) { + return GSS_S_DEFECTIVE_TOKEN; + } + + oid.length = mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { + return GSS_S_BAD_MECH; + } + + *minor_status = 0; + + /* Translate broken MS Kebreros OID */ + if (gss_oid_equal(&oid, &gss_mskrb_mechanism_oid_desc)) { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&gss_krb5_mechanism_oid_desc); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &gss_mskrb_mechanism_oid_desc, + mech_p); + } else { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&oid); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &mech->gm_mech_oid, + mech_p); + } + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c new file mode 100644 index 0000000000..902ddbbdf9 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: context_stubs.c,v 1.8 2006/10/07 22:27:01 lha Exp $"); + +static OM_uint32 +spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) +{ + OM_uint32 ret, junk; + gss_OID_set m; + int i; + + ret = gss_indicate_mechs(minor_status, &m); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_create_empty_oid_set(minor_status, mechs); + if (ret != GSS_S_COMPLETE) { + gss_release_oid_set(&junk, &m); + return ret; + } + + for (i = 0; i < m->count; i++) { + if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM)) + continue; + + ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs); + if (ret) { + gss_release_oid_set(&junk, &m); + gss_release_oid_set(&junk, mechs); + return ret; + } + } + return ret; +} + + + +OM_uint32 _gss_spnego_process_context_token + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + gss_ctx_id_t context ; + gssspnego_ctx ctx; + OM_uint32 ret; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + context = context_handle; + ctx = (gssspnego_ctx)context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = gss_process_context_token(minor_status, + ctx->negotiated_ctx_id, + token_buffer); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + return _gss_spnego_internal_delete_sec_context(minor_status, + &context, + GSS_C_NO_BUFFER); +} + +OM_uint32 _gss_spnego_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)*context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + return _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + output_token); +} + +OM_uint32 _gss_spnego_context_time + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec + ) +{ + gssspnego_ctx ctx; + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_context_time(minor_status, + ctx->negotiated_ctx_id, + time_rec); +} + +OM_uint32 _gss_spnego_get_mic + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_get_mic(minor_status, ctx->negotiated_ctx_id, + qop_req, message_buffer, message_token); +} + +OM_uint32 _gss_spnego_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + message_buffer, + token_buffer, + qop_state); +} + +OM_uint32 _gss_spnego_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); +} + +OM_uint32 _gss_spnego_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +OM_uint32 _gss_spnego_display_status + (OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 * message_context, + gss_buffer_t status_string + ) +{ + return GSS_S_FAILURE; +} + +OM_uint32 _gss_spnego_compare_name + (OM_uint32 *minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ) +{ + return gss_compare_name(minor_status, name1, name2, name_equal); +} + +OM_uint32 _gss_spnego_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + return gss_display_name(minor_status, input_name, + output_name_buffer, output_name_type); +} + +OM_uint32 _gss_spnego_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + return gss_import_name(minor_status, input_name_buffer, + input_name_type, output_name); +} + +OM_uint32 _gss_spnego_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ) +{ + return gss_export_name(minor_status, input_name, + exported_name); +} + +OM_uint32 _gss_spnego_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + return gss_release_name(minor_status, input_name); +} + +OM_uint32 _gss_spnego_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_inquire_context(minor_status, + ctx->negotiated_ctx_id, + src_name, + targ_name, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open_context); +} + +OM_uint32 _gss_spnego_wrap_size_limit ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_size_limit(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + req_output_size, + max_input_size); +} + +OM_uint32 _gss_spnego_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 ret; + + *minor_status = 0; + + if (context_handle == NULL) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)*context_handle; + + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_NO_CONTEXT; + } + + ret = gss_export_sec_context(minor_status, + &ctx->negotiated_ctx_id, + interprocess_token); + if (ret == GSS_S_COMPLETE) { + ret = _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + GSS_C_NO_BUFFER); + if (ret == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return ret; +} + +OM_uint32 _gss_spnego_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle + ) +{ + OM_uint32 ret, minor; + gss_ctx_id_t context; + gssspnego_ctx ctx; + + ret = _gss_spnego_alloc_sec_context(minor_status, &context); + if (ret != GSS_S_COMPLETE) { + return ret; + } + ctx = (gssspnego_ctx)context; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = gss_import_sec_context(minor_status, + interprocess_token, + &ctx->negotiated_ctx_id); + if (ret != GSS_S_COMPLETE) { + _gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER); + return ret; + } + + ctx->open = 1; + /* don't bother filling in the rest of the fields */ + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + gss_OID_set mechs, names, n; + OM_uint32 ret, junk; + int i, j; + + *name_types = NULL; + + ret = spnego_supported_mechs(minor_status, &mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_create_empty_oid_set(minor_status, &names); + if (ret != GSS_S_COMPLETE) + goto out; + + for (i = 0; i < mechs->count; i++) { + ret = gss_inquire_names_for_mech(minor_status, + &mechs->elements[i], + &n); + if (ret) + continue; + + for (j = 0; j < n->count; j++) + gss_add_oid_set_member(minor_status, + &n->elements[j], + &names); + gss_release_oid_set(&junk, &n); + } + + ret = GSS_S_COMPLETE; + *name_types = names; +out: + + gss_release_oid_set(&junk, &mechs); + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ) +{ + OM_uint32 ret, junk; + + ret = gss_create_empty_oid_set(minor_status, mech_types); + if (ret) + return ret; + + ret = gss_add_oid_set_member(minor_status, + GSS_SPNEGO_MECHANISM, + mech_types); + if (ret) + gss_release_oid_set(&junk, mech_types); + + return ret; +} + +OM_uint32 _gss_spnego_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + /* XXX */ + return gss_duplicate_name(minor_status, input_name, output_name); +} + +OM_uint32 _gss_spnego_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ) +{ + return gss_duplicate_name(minor_status, src_name, dest_name); +} + +OM_uint32 _gss_spnego_sign + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_sign(minor_status, + ctx->negotiated_ctx_id, + qop_req, + message_buffer, + message_token); +} + +OM_uint32 _gss_spnego_verify + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_verify(minor_status, + ctx->negotiated_ctx_id, + message_buffer, + token_buffer, + qop_state); +} + +OM_uint32 _gss_spnego_seal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_seal(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); +} + +OM_uint32 _gss_spnego_unseal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + int * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unseal(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +#if 0 +OM_uint32 _gss_spnego_unwrap_ex + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_header_buffer, + const gss_buffer_t associated_data_buffer, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap_ex(minor_status, + ctx->negotiated_ctx_id, + token_header_buffer, + associated_data_buffer, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +OM_uint32 _gss_spnego_wrap_ex + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t associated_data_buffer, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_token_buffer, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 && + associated_data_buffer->length != input_message_buffer->length) { + *minor_status = EINVAL; + return GSS_S_BAD_QOP; + } + + return gss_wrap_ex(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + associated_data_buffer, + input_message_buffer, + conf_state, + output_token_buffer, + output_message_buffer); +} + +OM_uint32 _gss_spnego_complete_auth_token + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_complete_auth_token(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer); +} +#endif + +OM_uint32 _gss_spnego_inquire_sec_context_by_oid + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_inquire_sec_context_by_oid(minor_status, + ctx->negotiated_ctx_id, + desired_object, + data_set); +} + +OM_uint32 _gss_spnego_set_sec_context_option + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_set_sec_context_option(minor_status, + &ctx->negotiated_ctx_id, + desired_object, + value); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c new file mode 100644 index 0000000000..8f8edab15e --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: cred_stubs.c,v 1.5 2006/10/07 22:27:04 lha Exp $"); + +OM_uint32 +_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ + gssspnego_cred cred; + OM_uint32 ret; + + *minor_status = 0; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + return GSS_S_COMPLETE; + } + cred = (gssspnego_cred)*cred_handle; + + ret = gss_release_cred(minor_status, &cred->negotiated_cred_id); + + free(cred); + *cred_handle = GSS_C_NO_CREDENTIAL; + + return ret; +} + +OM_uint32 +_gss_spnego_alloc_cred(OM_uint32 *minor_status, + gss_cred_id_t mech_cred_handle, + gss_cred_id_t *cred_handle) +{ + gssspnego_cred cred; + + if (*cred_handle != GSS_C_NO_CREDENTIAL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) { + *cred_handle = GSS_C_NO_CREDENTIAL; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + cred->negotiated_cred_id = mech_cred_handle; + + *cred_handle = (gss_cred_id_t)cred; + + return GSS_S_COMPLETE; +} + +/* + * For now, just a simple wrapper that avoids recursion. When + * we support gss_{get,set}_neg_mechs() we will need to expose + * more functionality. + */ +OM_uint32 _gss_spnego_acquire_cred +(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret, tmp; + gss_OID_set_desc actual_desired_mechs; + gss_OID_set mechs; + int i, j; + gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; + gssspnego_cred cred; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + ret = gss_indicate_mechs(minor_status, &mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + /* Remove ourselves from this list */ + actual_desired_mechs.count = mechs->count; + actual_desired_mechs.elements = malloc(actual_desired_mechs.count * + sizeof(gss_OID_desc)); + if (actual_desired_mechs.elements == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + + for (i = 0, j = 0; i < mechs->count; i++) { + if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) + continue; + + actual_desired_mechs.elements[j] = mechs->elements[i]; + j++; + } + actual_desired_mechs.count = j; + + ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, + &cred_handle); + if (ret != GSS_S_COMPLETE) + goto out; + + cred = (gssspnego_cred)cred_handle; + ret = gss_acquire_cred(minor_status, desired_name, + time_req, &actual_desired_mechs, + cred_usage, + &cred->negotiated_cred_id, + actual_mechs, time_rec); + if (ret != GSS_S_COMPLETE) + goto out; + + *output_cred_handle = cred_handle; + +out: + gss_release_oid_set(&tmp, &mechs); + if (actual_desired_mechs.elements != NULL) { + free(actual_desired_mechs.elements); + } + if (ret != GSS_S_COMPLETE) { + _gss_spnego_release_cred(&tmp, &cred_handle); + } + + return ret; +} + +OM_uint32 _gss_spnego_inquire_cred + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred(minor_status, + cred->negotiated_cred_id, + name, + lifetime, + cred_usage, + mechanisms); + + return ret; +} + +OM_uint32 _gss_spnego_add_cred ( + OM_uint32 * minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * initiator_time_rec, + OM_uint32 * acceptor_time_rec + ) +{ + gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL; + OM_uint32 ret, tmp; + gssspnego_cred input_cred, output_cred; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, + &spnego_output_cred_handle); + if (ret) + return ret; + + input_cred = (gssspnego_cred)input_cred_handle; + output_cred = (gssspnego_cred)spnego_output_cred_handle; + + ret = gss_add_cred(minor_status, + input_cred->negotiated_cred_id, + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + &output_cred->negotiated_cred_id, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (ret) { + _gss_spnego_release_cred(&tmp, &spnego_output_cred_handle); + return ret; + } + + *output_cred_handle = spnego_output_cred_handle; + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred_by_mech(minor_status, + cred->negotiated_cred_id, + mech_type, + name, + initiator_lifetime, + acceptor_lifetime, + cred_usage); + + return ret; +} + +OM_uint32 _gss_spnego_inquire_cred_by_oid + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred_by_oid(minor_status, + cred->negotiated_cred_id, + desired_object, + data_set); + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c new file mode 100644 index 0000000000..b7e02a55e1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" +#include + +RCSID("$Id: external.c,v 1.7 2006/10/07 22:27:06 lha Exp $"); + +/* + * RFC2478, SPNEGO: + * The security mechanism of the initial + * negotiation token is identified by the Object Identifier + * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ + +static gssapi_mech_interface_desc spnego_mech = { + GMI_VERSION, + "spnego", + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}, + _gss_spnego_acquire_cred, + _gss_spnego_release_cred, + _gss_spnego_init_sec_context, + _gss_spnego_accept_sec_context, + _gss_spnego_process_context_token, + _gss_spnego_internal_delete_sec_context, + _gss_spnego_context_time, + _gss_spnego_get_mic, + _gss_spnego_verify_mic, + _gss_spnego_wrap, + _gss_spnego_unwrap, + _gss_spnego_display_status, + NULL, + _gss_spnego_compare_name, + _gss_spnego_display_name, + _gss_spnego_import_name, + _gss_spnego_export_name, + _gss_spnego_release_name, + _gss_spnego_inquire_cred, + _gss_spnego_inquire_context, + _gss_spnego_wrap_size_limit, + _gss_spnego_add_cred, + _gss_spnego_inquire_cred_by_mech, + _gss_spnego_export_sec_context, + _gss_spnego_import_sec_context, + _gss_spnego_inquire_names_for_mech, + _gss_spnego_inquire_mechs_for_name, + _gss_spnego_canonicalize_name, + _gss_spnego_duplicate_name +}; + +gssapi_mech_interface +__gss_spnego_initialize(void) +{ + return &spnego_mech; +} + +static gss_OID_desc _gss_spnego_mechanism_desc = + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; + +gss_OID GSS_SPNEGO_MECHANISM = &_gss_spnego_mechanism_desc; diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c new file mode 100644 index 0000000000..5a652fdb2e --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: init_sec_context.c,v 1.6 2006/10/14 10:09:15 lha Exp $"); + +/* + * Send a reply. Note that we only need to send a reply if we + * need to send a MIC or a mechanism token. Otherwise, we can + * return an empty buffer. + * + * The return value of this will be returned to the API, so it + * must return GSS_S_CONTINUE_NEEDED if a token was generated. + */ +static OM_uint32 +spnego_reply_internal(OM_uint32 *minor_status, + gssspnego_ctx context_handle, + const gss_buffer_t mech_buf, + gss_buffer_t mech_token, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc mic_buf; + OM_uint32 ret; + gss_buffer_desc data; + u_char *buf; + + if (mech_buf == GSS_C_NO_BUFFER && mech_token->length == 0) { + output_token->length = 0; + output_token->value = NULL; + + return context_handle->open ? GSS_S_COMPLETE : GSS_S_FAILURE; + } + + memset(&resp, 0, sizeof(resp)); + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + resp.supportedMech = NULL; + + output_token->length = 0; + output_token->value = NULL; + + if (mech_token->length == 0) { + resp.responseToken = NULL; + *(resp.negResult) = accept_completed; + } else { + ALLOC(resp.responseToken, 1); + if (resp.responseToken == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + resp.responseToken->length = mech_token->length; + resp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + + *(resp.negResult) = accept_incomplete; + } + + if (mech_buf != GSS_C_NO_BUFFER) { + ALLOC(resp.mechListMIC, 1); + if (resp.mechListMIC == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = gss_get_mic(minor_status, + context_handle->negotiated_ctx_id, + 0, + mech_buf, + &mic_buf); + if (ret) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + resp.mechListMIC->length = mic_buf.length; + resp.mechListMIC->data = mic_buf.value; + } else { + resp.mechListMIC = NULL; + } + + ret = _gss_spnego_encode_response (minor_status, &resp, + &data, &buf); + if (ret) { + free_NegTokenResp(&resp); + return ret; + } + + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + + if (*(resp.negResult) == accept_completed) + ret = GSS_S_COMPLETE; + else + ret = GSS_S_CONTINUE_NEEDED; + + free_NegTokenResp(&resp); + return ret; +} + +static OM_uint32 +spnego_initial + (OM_uint32 * minor_status, + gssspnego_cred cred, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + NegTokenInit ni; + int ret; + OM_uint32 sub, minor; + gss_buffer_desc mech_token; + u_char *buf; + size_t buf_size, buf_len; + gss_buffer_desc data; + size_t ni_len; + gss_ctx_id_t context; + gssspnego_ctx ctx; + + memset (&ni, 0, sizeof(ni)); + + *context_handle = GSS_C_NO_CONTEXT; + + *minor_status = 0; + + sub = _gss_spnego_alloc_sec_context(&minor, &context); + if (GSS_ERROR(sub)) { + *minor_status = minor; + return sub; + } + ctx = (gssspnego_ctx)context; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ctx->local = 1; + + sub = _gss_spnego_indicate_mechtypelist(&minor, 0, + cred, + &ni.mechTypes, + &ctx->preferred_mech_type); + if (GSS_ERROR(sub)) { + *minor_status = minor; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + ni.reqFlags = NULL; + + /* + * If we have a credential handle, use it to select the mechanism + * that we will use + */ + + /* generate optimistic token */ + sub = gss_init_sec_context(&minor, + (cred != NULL) ? cred->negotiated_cred_id : + GSS_C_NO_CREDENTIAL, + &ctx->negotiated_ctx_id, + target_name, + GSS_C_NO_OID, + req_flags, + time_req, + input_chan_bindings, + input_token, + &ctx->negotiated_mech_type, + &mech_token, + &ctx->mech_flags, + &ctx->mech_time_rec); + if (GSS_ERROR(sub)) { + free_NegTokenInit(&ni); + *minor_status = minor; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + if (mech_token.length != 0) { + ALLOC(ni.mechToken, 1); + if (ni.mechToken == NULL) { + free_NegTokenInit(&ni); + gss_release_buffer(&minor, &mech_token); + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ni.mechToken->length = mech_token.length; + ni.mechToken->data = malloc(mech_token.length); + if (ni.mechToken->data == NULL && mech_token.length != 0) { + free_NegTokenInit(&ni); + gss_release_buffer(&minor, &mech_token); + *minor_status = ENOMEM; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + memcpy(ni.mechToken->data, mech_token.value, mech_token.length); + gss_release_buffer(&minor, &mech_token); + } else + ni.mechToken = NULL; + + ni.mechListMIC = NULL; + + ni_len = length_NegTokenInit(&ni); + buf_size = 1 + der_length_len(ni_len) + ni_len; + + buf = malloc(buf_size); + if (buf == NULL) { + free_NegTokenInit(&ni); + *minor_status = ENOMEM; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + ret = encode_NegTokenInit(buf + buf_size - 1, + ni_len, + &ni, &buf_len); + if (ret == 0 && ni_len != buf_len) + abort(); + + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 0, + &tmp); + if (ret == 0 && tmp + buf_len != buf_size) + abort(); + } + if (ret) { + *minor_status = ret; + free(buf); + free_NegTokenInit(&ni); + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + data.value = buf; + data.length = buf_size; + + ctx->initiator_mech_types.len = ni.mechTypes.len; + ctx->initiator_mech_types.val = ni.mechTypes.val; + ni.mechTypes.len = 0; + ni.mechTypes.val = NULL; + + free_NegTokenInit(&ni); + + sub = gss_encapsulate_token(&data, + GSS_SPNEGO_MECHANISM, + output_token); + free (buf); + + if (sub) { + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + if (actual_mech_type) + *actual_mech_type = ctx->negotiated_mech_type; + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + *context_handle = context; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +spnego_reply + (OM_uint32 * minor_status, + const gssspnego_cred cred, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret, minor; + NegTokenResp resp; + u_char oidbuf[17]; + size_t oidlen; + size_t len, taglen; + gss_OID_desc mech; + int require_mic; + size_t buf_len; + gss_buffer_desc mic_buf, mech_buf; + gss_buffer_desc mech_output_token; + gssspnego_ctx ctx; + + *minor_status = 0; + + ctx = (gssspnego_ctx)*context_handle; + + output_token->length = 0; + output_token->value = NULL; + + mech_output_token.length = 0; + mech_output_token.value = NULL; + + mech_buf.value = NULL; + mech_buf.length = 0; + + ret = der_match_tag_and_length(input_token->value, input_token->length, + ASN1_C_CONTEXT, CONS, 1, &len, &taglen); + if (ret) + return ret; + + if (len > input_token->length - taglen) + return ASN1_OVERRUN; + + ret = decode_NegTokenResp((const unsigned char *)input_token->value+taglen, + len, &resp, NULL); + if (ret) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (resp.negResult == NULL + || *(resp.negResult) == reject + || resp.supportedMech == NULL) { + free_NegTokenResp(&resp); + return GSS_S_BAD_MECH; + } + + ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1, + sizeof(oidbuf), + resp.supportedMech, + &oidlen); + if (ret || (oidlen == GSS_SPNEGO_MECHANISM->length && + memcmp(oidbuf + sizeof(oidbuf) - oidlen, + GSS_SPNEGO_MECHANISM->elements, + oidlen) == 0)) { + /* Avoid recursively embedded SPNEGO */ + free_NegTokenResp(&resp); + return GSS_S_BAD_MECH; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (resp.responseToken != NULL) { + gss_buffer_desc mech_input_token; + + mech_input_token.length = resp.responseToken->length; + mech_input_token.value = resp.responseToken->data; + + mech.length = oidlen; + mech.elements = oidbuf + sizeof(oidbuf) - oidlen; + + /* Fall through as if the negotiated mechanism + was requested explicitly */ + ret = gss_init_sec_context(&minor, + (cred != NULL) ? cred->negotiated_cred_id : + GSS_C_NO_CREDENTIAL, + &ctx->negotiated_ctx_id, + target_name, + &mech, + req_flags, + time_req, + input_chan_bindings, + &mech_input_token, + &ctx->negotiated_mech_type, + &mech_output_token, + &ctx->mech_flags, + &ctx->mech_time_rec); + if (GSS_ERROR(ret)) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + *minor_status = minor; + return ret; + } + if (ret == GSS_S_COMPLETE) { + ctx->open = 1; + } + } + + if (*(resp.negResult) == request_mic) { + ctx->require_mic = 1; + } + + if (ctx->open) { + /* + * Verify the mechListMIC if one was provided or CFX was + * used and a non-preferred mechanism was selected + */ + if (resp.mechListMIC != NULL) { + require_mic = 1; + } else { + ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, + &require_mic); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + return ret; + } + } + } else { + require_mic = 0; + } + + if (require_mic) { + ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length, + &ctx->initiator_mech_types, &buf_len, ret); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + *minor_status = ret; + return GSS_S_FAILURE; + } + if (mech_buf.length != buf_len) + abort(); + + if (resp.mechListMIC == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free(mech_buf.value); + free_NegTokenResp(&resp); + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + mic_buf.length = resp.mechListMIC->length; + mic_buf.value = resp.mechListMIC->data; + + if (mech_output_token.length == 0) { + ret = gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + &mech_buf, + &mic_buf, + NULL); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free(mech_buf.value); + gss_release_buffer(&minor, &mech_output_token); + free_NegTokenResp(&resp); + return GSS_S_DEFECTIVE_TOKEN; + } + ctx->verified_mic = 1; + } + } + + ret = spnego_reply_internal(minor_status, ctx, + require_mic ? &mech_buf : NULL, + &mech_output_token, + output_token); + + if (mech_buf.value != NULL) + free(mech_buf.value); + + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + + if (actual_mech_type) + *actual_mech_type = ctx->negotiated_mech_type; + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; +} + +OM_uint32 _gss_spnego_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gssspnego_cred cred = (gssspnego_cred)initiator_cred_handle; + + if (*context_handle == GSS_C_NO_CONTEXT) + return spnego_initial (minor_status, + cred, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + else + return spnego_reply (minor_status, + cred, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h new file mode 100644 index 0000000000..df50f65580 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -0,0 +1,347 @@ +/* This is a generated file */ +#ifndef __spnego_private_h__ +#define __spnego_private_h__ + +#include + +gssapi_mech_interface +__gss_spnego_initialize (void); + +OM_uint32 +_gss_spnego_accept_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + gss_name_t * /*src_name*/, + gss_OID * /*mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/, + gss_cred_id_t *delegated_cred_handle ); + +OM_uint32 +_gss_spnego_acquire_cred ( + OM_uint32 */*minor_status*/, + const gss_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gss_spnego_add_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*initiator_time_rec*/, + OM_uint32 * acceptor_time_rec ); + +int +_gss_spnego_add_mech_type ( + gss_OID /*mech_type*/, + int /*includeMSCompatOID*/, + MechTypeList */*mechtypelist*/); + +OM_uint32 +_gss_spnego_alloc_cred ( + OM_uint32 */*minor_status*/, + gss_cred_id_t /*mech_cred_handle*/, + gss_cred_id_t */*cred_handle*/); + +OM_uint32 +_gss_spnego_alloc_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t */*context_handle*/); + +OM_uint32 +_gss_spnego_canonicalize_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gss_spnego_compare_name ( + OM_uint32 */*minor_status*/, + const gss_name_t /*name1*/, + const gss_name_t /*name2*/, + int * name_equal ); + +OM_uint32 +_gss_spnego_context_time ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + OM_uint32 *time_rec ); + +OM_uint32 +_gss_spnego_delete_sec_context ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + gss_buffer_t output_token ); + +OM_uint32 +_gss_spnego_display_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * output_name_type ); + +OM_uint32 +_gss_spnego_display_status ( + OM_uint32 * /*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 * /*message_context*/, + gss_buffer_t status_string ); + +OM_uint32 +_gss_spnego_duplicate_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*src_name*/, + gss_name_t * dest_name ); + +OM_uint32 +_gss_spnego_encode_response ( + OM_uint32 */*minor_status*/, + const NegTokenResp */*resp*/, + gss_buffer_t /*data*/, + u_char **/*ret_buf*/); + +OM_uint32 +_gss_spnego_export_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t exported_name ); + +OM_uint32 +_gss_spnego_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t interprocess_token ); + +OM_uint32 +_gss_spnego_get_mic ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gss_spnego_import_name ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gss_spnego_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t *context_handle ); + +OM_uint32 +_gss_spnego_indicate_mechtypelist ( + OM_uint32 */*minor_status*/, + int /*includeMSCompatOID*/, + const gssspnego_cred /*cred_handle*/, + MechTypeList */*mechtypelist*/, + gss_OID */*preferred_mech*/); + +OM_uint32 +_gss_spnego_init_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + const gss_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gss_spnego_inquire_context ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * open_context ); + +OM_uint32 +_gss_spnego_inquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + gss_name_t * /*name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * mechanisms ); + +OM_uint32 +_gss_spnego_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * cred_usage ); + +OM_uint32 +_gss_spnego_inquire_cred_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gss_spnego_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_OID_set * mech_types ); + +OM_uint32 +_gss_spnego_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * name_types ); + +OM_uint32 +_gss_spnego_inquire_sec_context_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gss_spnego_internal_delete_sec_context ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + gss_buffer_t output_token ); + +OM_uint32 +_gss_spnego_process_context_token ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t token_buffer ); + +OM_uint32 +_gss_spnego_release_cred ( + OM_uint32 */*minor_status*/, + gss_cred_id_t */*cred_handle*/); + +OM_uint32 +_gss_spnego_release_name ( + OM_uint32 * /*minor_status*/, + gss_name_t * input_name ); + +OM_uint32 +_gss_spnego_require_mechlist_mic ( + OM_uint32 */*minor_status*/, + gssspnego_ctx /*ctx*/, + int */*require_mic*/); + +OM_uint32 +_gss_spnego_seal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gss_spnego_select_mech ( + OM_uint32 */*minor_status*/, + MechType */*mechType*/, + gss_OID */*mech_p*/); + +OM_uint32 +_gss_spnego_set_sec_context_option ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +OM_uint32 +_gss_spnego_sign ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gss_spnego_unseal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * qop_state ); + +OM_uint32 +_gss_spnego_unwrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gss_spnego_verify ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * qop_state ); + +OM_uint32 +_gss_spnego_verify_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gss_spnego_wrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gss_spnego_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * max_input_size ); + +#endif /* __spnego_private_h__ */ diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 new file mode 100644 index 0000000000..187ce0a0a6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -0,0 +1,51 @@ +-- $Id: spnego.asn1,v 1.1.1.1 2006/06/28 08:34:45 lha Exp $ + +SPNEGO DEFINITIONS ::= +BEGIN + +MechType::= OBJECT IDENTIFIER + +MechTypeList ::= SEQUENCE OF MechType + +ContextFlags ::= BIT STRING { + delegFlag (0), + mutualFlag (1), + replayFlag (2), + sequenceFlag (3), + anonFlag (4), + confFlag (5), + integFlag (6) +} + +NegHints ::= SEQUENCE { + hintName [0] GeneralString OPTIONAL, + hintAddress [1] OCTET STRING OPTIONAL +} + +NegTokenInit ::= SEQUENCE { + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + negHints [3] NegHints OPTIONAL, + mechListMIC [4] OCTET STRING OPTIONAL + } + +-- NB: negResult is not OPTIONAL in the new SPNEGO spec but +-- Windows clients do not always send it +NegTokenResp ::= SEQUENCE { + negResult [0] ENUMERATED { + accept_completed (0), + accept_incomplete (1), + reject (2), + request-mic (3) } OPTIONAL, + supportedMech [1] MechType OPTIONAL, + responseToken [2] OCTET STRING OPTIONAL, + mechListMIC [3] OCTET STRING OPTIONAL +} + +NegotiationToken ::= CHOICE { + negTokenInit[0] NegTokenInit, + negTokenResp[1] NegTokenResp +} + +END diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h new file mode 100644 index 0000000000..571bce5569 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: spnego_locl.h,v 1.11 2006/10/12 06:28:06 lha Exp $ */ + +#ifndef SPNEGO_LOCL_H +#define SPNEGO_LOCL_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_PTHREAD_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#endif + +#include +#include + +#include + +#include "spnego_asn1.h" +#include + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) + +typedef struct { + gss_cred_id_t negotiated_cred_id; +} *gssspnego_cred; + +typedef struct { + MechTypeList initiator_mech_types; + gss_OID preferred_mech_type; + gss_OID negotiated_mech_type; + gss_ctx_id_t negotiated_ctx_id; + OM_uint32 mech_flags; + OM_uint32 mech_time_rec; + gss_name_t mech_src_name; + gss_cred_id_t delegated_cred_id; + int open : 1; + int local : 1; + int require_mic : 1; + int verified_mic : 1; + HEIMDAL_MUTEX ctx_id_mutex; +} *gssspnego_ctx; + +#include + +#endif /* SPNEGO_LOCL_H */ -- cgit From f722b0743811a4a5caf5288fa901cc8f683b9ffd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 8 Nov 2006 01:48:35 +0000 Subject: r19633: Merge to lorikeet-heimdal, removing krb5_rd_req_return_keyblock in favour of a more tasteful replacement. Remove kerberos_verify.c, as we don't need that code any more. Replace with code for using the new krb5_rd_req_ctx() borrowed from Heimdal's accecpt_sec_context.c Andrew Bartlett (This used to be commit 13c9df1d4f0517468c80040d3756310d4dcbdd50) --- source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h index 571bce5569..255e07d056 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: spnego_locl.h,v 1.11 2006/10/12 06:28:06 lha Exp $ */ +/* $Id: spnego_locl.h,v 1.12 2006/11/07 19:53:40 lha Exp $ */ #ifndef SPNEGO_LOCL_H #define SPNEGO_LOCL_H @@ -69,6 +69,8 @@ #include "spnego_asn1.h" #include +#include + #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) typedef struct { -- cgit From f7242f643763ccb6e10801af4ce53d0873e2d3e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 10 Jan 2007 01:57:32 +0000 Subject: r20640: Commit part 2/2 Update Heimdal to match current lorikeet-heimdal. This includes integrated PAC hooks, so Samba doesn't have to handle this any more. This also brings in the PKINIT code, hence so many new files. Andrew Bartlett (This used to be commit 351f7040f7bb73b9a60b22b564686f7c2f98a729) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 978 ++++++++++++--------- source4/heimdal/lib/gssapi/spnego/compat.c | 154 ++-- source4/heimdal/lib/gssapi/spnego/context_stubs.c | 88 +- .../heimdal/lib/gssapi/spnego/init_sec_context.c | 219 +++-- source4/heimdal/lib/gssapi/spnego/spnego-private.h | 25 +- source4/heimdal/lib/gssapi/spnego/spnego.asn1 | 17 +- source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 27 +- 7 files changed, 940 insertions(+), 568 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 8a885a3e2f..2c86b3f794 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * Portions Copyright (c) 2004 PADL Software Pty Ltd. * @@ -33,203 +33,85 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c,v 1.6 2006/10/07 22:26:57 lha Exp $"); - -OM_uint32 -_gss_spnego_encode_response(OM_uint32 *minor_status, - const NegTokenResp *resp, - gss_buffer_t data, - u_char **ret_buf) -{ - OM_uint32 ret; - u_char *buf; - size_t buf_size, buf_len; - - buf_size = 1024; - buf = malloc(buf_size); - if (buf == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - do { - ret = encode_NegTokenResp(buf + buf_size - 1, - buf_size, - resp, &buf_len); - if (ret == 0) { - size_t tmp; - - ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, - buf_size - buf_len, - buf_len, - ASN1_C_CONTEXT, - CONS, - 1, - &tmp); - if (ret == 0) - buf_len += tmp; - } - if (ret) { - if (ret == ASN1_OVERFLOW) { - u_char *tmp; - - buf_size *= 2; - tmp = realloc (buf, buf_size); - if (tmp == NULL) { - *minor_status = ENOMEM; - free(buf); - return GSS_S_FAILURE; - } - buf = tmp; - } else { - *minor_status = ret; - free(buf); - return GSS_S_FAILURE; - } - } - } while (ret == ASN1_OVERFLOW); - - data->value = buf + buf_size - buf_len; - data->length = buf_len; - *ret_buf = buf; - - return GSS_S_COMPLETE; -} +RCSID("$Id: accept_sec_context.c,v 1.16 2006/12/19 12:10:35 lha Exp $"); static OM_uint32 send_reject (OM_uint32 *minor_status, gss_buffer_t output_token) { - NegTokenResp resp; - gss_buffer_desc data; - u_char *buf; - OM_uint32 ret; + NegotiationToken nt; + size_t size; + + nt.element = choice_NegotiationToken_negTokenResp; - ALLOC(resp.negResult, 1); - if (resp.negResult == NULL) { + ALLOC(nt.u.negTokenResp.negResult, 1); + if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } - *(resp.negResult) = reject; - resp.supportedMech = NULL; - resp.responseToken = NULL; - resp.mechListMIC = NULL; + *(nt.u.negTokenResp.negResult) = reject; + nt.u.negTokenResp.supportedMech = NULL; + nt.u.negTokenResp.responseToken = NULL; + nt.u.negTokenResp.mechListMIC = NULL; - ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); - free_NegTokenResp(&resp); - if (ret != GSS_S_COMPLETE) - return ret; + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, &nt, + &size, *minor_status); + free_NegotiationToken(&nt); + if (*minor_status != 0) + return GSS_S_FAILURE; - output_token->value = malloc(data.length); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - } else { - output_token->length = data.length; - memcpy(output_token->value, data.value, output_token->length); - } - free(buf); - if (ret != GSS_S_COMPLETE) - return ret; return GSS_S_BAD_MECH; } -OM_uint32 -_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, - int includeMSCompatOID, - const gssspnego_cred cred_handle, - MechTypeList *mechtypelist, - gss_OID *preferred_mech) +static OM_uint32 +acceptor_approved(gss_name_t target_name, gss_OID mech) { - OM_uint32 ret; - gss_OID_set supported_mechs = GSS_C_NO_OID_SET; - int i, count; - - if (cred_handle != NULL) { - ret = gss_inquire_cred(minor_status, - cred_handle->negotiated_cred_id, - NULL, - NULL, - NULL, - &supported_mechs); - } else { - ret = gss_indicate_mechs(minor_status, &supported_mechs); - } + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_OID_set oidset; + OM_uint32 junk, ret; - if (ret != GSS_S_COMPLETE) { - return ret; - } + if (target_name == GSS_C_NO_NAME) + return GSS_S_COMPLETE; - if (supported_mechs->count == 0) { - *minor_status = ENOENT; - gss_release_oid_set(minor_status, &supported_mechs); - return GSS_S_FAILURE; - } - - count = supported_mechs->count; - if (includeMSCompatOID) - count++; - - mechtypelist->len = 0; - mechtypelist->val = calloc(count, sizeof(MechType)); - if (mechtypelist->val == NULL) { - *minor_status = ENOMEM; - gss_release_oid_set(minor_status, &supported_mechs); - return GSS_S_FAILURE; - } - - for (i = 0; i < supported_mechs->count; i++) { - ret = _gss_spnego_add_mech_type(&supported_mechs->elements[i], - includeMSCompatOID, - mechtypelist); - if (ret != 0) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - break; - } - } - - if (ret == GSS_S_COMPLETE && preferred_mech != NULL) { - ret = gss_duplicate_oid(minor_status, - &supported_mechs->elements[0], - preferred_mech); - } - - if (ret != GSS_S_COMPLETE) { - free_MechTypeList(mechtypelist); - mechtypelist->len = 0; - mechtypelist->val = NULL; - } - gss_release_oid_set(minor_status, &supported_mechs); - - return ret; + gss_create_empty_oid_set(&junk, &oidset); + gss_add_oid_set_member(&junk, mech, &oidset); + + ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, + GSS_C_ACCEPT, &cred, NULL, NULL); + gss_release_oid_set(&junk, &oidset); + if (ret != GSS_S_COMPLETE) + return ret; + gss_release_cred(&junk, &cred); + + return GSS_S_COMPLETE; } static OM_uint32 send_supported_mechs (OM_uint32 *minor_status, gss_buffer_t output_token) { - NegTokenInit ni; + 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 ret, minor; - u_char *buf; - size_t buf_size, buf_len; + OM_uint32 minor; + size_t buf_len; gss_buffer_desc data; + OM_uint32 ret; - memset(&ni, 0, sizeof(ni)); + memset(&nt, 0, sizeof(nt)); - ni.reqFlags = NULL; - ni.mechToken = NULL; - ni.negHints = NULL; - ni.mechListMIC = NULL; + nt.element = choice_NegotiationTokenWin_negTokenInit; + nt.u.negTokenInit.reqFlags = NULL; + nt.u.negTokenInit.mechToken = NULL; + nt.u.negTokenInit.negHints = NULL; - ret = _gss_spnego_indicate_mechtypelist(minor_status, 1, - NULL, - &ni.mechTypes, NULL); + ret = _gss_spnego_indicate_mechtypelist(minor_status, GSS_C_NO_NAME, + acceptor_approved, 1, NULL, + &nt.u.negTokenInit.mechTypes, NULL); if (ret != GSS_S_COMPLETE) { return ret; } @@ -237,7 +119,7 @@ send_supported_mechs (OM_uint32 *minor_status, memset(&target_princ, 0, sizeof(target_princ)); if (gethostname(hostname, sizeof(hostname) - 1) != 0) { *minor_status = errno; - free_NegTokenInit(&ni); + free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } @@ -255,6 +137,7 @@ send_supported_mechs (OM_uint32 *minor_status, GSS_C_NO_OID, &target_princ); if (ret != GSS_S_COMPLETE) { + free_NegotiationTokenWin(&nt); return ret; } @@ -267,6 +150,7 @@ send_supported_mechs (OM_uint32 *minor_status, GSS_C_NO_OID, &canon_princ); if (ret != GSS_S_COMPLETE) { + free_NegotiationTokenWin(&nt); gss_release_name(&minor, &target_princ); return ret; } @@ -274,6 +158,7 @@ send_supported_mechs (OM_uint32 *minor_status, 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; @@ -282,81 +167,38 @@ send_supported_mechs (OM_uint32 *minor_status, gss_release_name(&minor, &canon_princ); gss_release_name(&minor, &target_princ); - ALLOC(ni.negHints, 1); - if (ni.negHints == NULL) { + ALLOC(nt.u.negTokenInit.negHints, 1); + if (nt.u.negTokenInit.negHints == NULL) { *minor_status = ENOMEM; gss_release_buffer(&minor, &name_buf); - free_NegTokenInit(&ni); + free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } - ALLOC(ni.negHints->hintName, 1); - if (ni.negHints->hintName == NULL) { + ALLOC(nt.u.negTokenInit.negHints->hintName, 1); + if (nt.u.negTokenInit.negHints->hintName == NULL) { *minor_status = ENOMEM; gss_release_buffer(&minor, &name_buf); - free_NegTokenInit(&ni); + free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } - *(ni.negHints->hintName) = name_buf.value; + *(nt.u.negTokenInit.negHints->hintName) = name_buf.value; name_buf.value = NULL; - ni.negHints->hintAddress = NULL; + nt.u.negTokenInit.negHints->hintAddress = NULL; - buf_size = 1024; - buf = malloc(buf_size); - if (buf == NULL) { - free_NegTokenInit(&ni); - *minor_status = ENOMEM; - return GSS_S_FAILURE; + ASN1_MALLOC_ENCODE(NegotiationTokenWin, + data.value, data.length, &nt, &buf_len, ret); + free_NegotiationTokenWin(&nt); + if (ret) { + return ret; } + if (data.length != buf_len) + abort(); - do { - ret = encode_NegTokenInit(buf + buf_size - 1, - buf_size, - &ni, &buf_len); - if (ret == 0) { - size_t tmp; - - ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, - buf_size - buf_len, - buf_len, - ASN1_C_CONTEXT, - CONS, - 0, - &tmp); - if (ret == 0) - buf_len += tmp; - } - if (ret) { - if (ret == ASN1_OVERFLOW) { - u_char *tmp; - - buf_size *= 2; - tmp = realloc (buf, buf_size); - if (tmp == NULL) { - *minor_status = ENOMEM; - free(buf); - free_NegTokenInit(&ni); - return GSS_S_FAILURE; - } - buf = tmp; - } else { - *minor_status = ret; - free(buf); - free_NegTokenInit(&ni); - return GSS_S_FAILURE; - } - } - } while (ret == ASN1_OVERFLOW); + ret = gss_encapsulate_token(&data, GSS_SPNEGO_MECHANISM, output_token); - data.value = buf + buf_size - buf_len; - data.length = buf_len; - - ret = gss_encapsulate_token(&data, - GSS_SPNEGO_MECHANISM, - output_token); - free (buf); - free_NegTokenInit (&ni); + free (data.value); if (ret != GSS_S_COMPLETE) return ret; @@ -374,16 +216,17 @@ send_accept (OM_uint32 *minor_status, gss_buffer_t mech_buf, gss_buffer_t output_token) { - NegTokenResp resp; - gss_buffer_desc data; - u_char *buf; + NegotiationToken nt; OM_uint32 ret; gss_buffer_desc mech_mic_buf; + size_t size; - memset(&resp, 0, sizeof(resp)); + memset(&nt, 0, sizeof(nt)); - ALLOC(resp.negResult, 1); - if (resp.negResult == NULL) { + nt.element = choice_NegotiationToken_negTokenResp; + + ALLOC(nt.u.negTokenResp.negResult, 1); + if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } @@ -392,79 +235,85 @@ send_accept (OM_uint32 *minor_status, if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0 && mech_buf != GSS_C_NO_BUFFER) - *(resp.negResult) = accept_incomplete; + *(nt.u.negTokenResp.negResult) = accept_incomplete; else - *(resp.negResult) = accept_completed; + *(nt.u.negTokenResp.negResult) = accept_completed; } else { if (initial_response && context_handle->require_mic) - *(resp.negResult) = request_mic; + *(nt.u.negTokenResp.negResult) = request_mic; else - *(resp.negResult) = accept_incomplete; + *(nt.u.negTokenResp.negResult) = accept_incomplete; } if (initial_response) { - ALLOC(resp.supportedMech, 1); - if (resp.supportedMech == NULL) { - free_NegTokenResp(&resp); + ALLOC(nt.u.negTokenResp.supportedMech, 1); + if (nt.u.negTokenResp.supportedMech == NULL) { + free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } ret = der_get_oid(context_handle->preferred_mech_type->elements, context_handle->preferred_mech_type->length, - resp.supportedMech, + nt.u.negTokenResp.supportedMech, NULL); if (ret) { - free_NegTokenResp(&resp); + free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } } else { - resp.supportedMech = NULL; + nt.u.negTokenResp.supportedMech = NULL; } if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { - ALLOC(resp.responseToken, 1); - if (resp.responseToken == NULL) { - free_NegTokenResp(&resp); + ALLOC(nt.u.negTokenResp.responseToken, 1); + if (nt.u.negTokenResp.responseToken == NULL) { + free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } - resp.responseToken->length = mech_token->length; - resp.responseToken->data = mech_token->value; + nt.u.negTokenResp.responseToken->length = mech_token->length; + nt.u.negTokenResp.responseToken->data = mech_token->value; mech_token->length = 0; mech_token->value = NULL; } else { - resp.responseToken = NULL; + nt.u.negTokenResp.responseToken = NULL; } if (mech_buf != GSS_C_NO_BUFFER) { - ALLOC(resp.mechListMIC, 1); - if (resp.mechListMIC == NULL) { - free_NegTokenResp(&resp); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - ret = gss_get_mic(minor_status, context_handle->negotiated_ctx_id, 0, mech_buf, &mech_mic_buf); - if (ret != GSS_S_COMPLETE) { - free_NegTokenResp(&resp); + if (ret == GSS_S_COMPLETE) { + ALLOC(nt.u.negTokenResp.mechListMIC, 1); + if (nt.u.negTokenResp.mechListMIC == NULL) { + gss_release_buffer(minor_status, &mech_mic_buf); + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + nt.u.negTokenResp.mechListMIC->length = mech_mic_buf.length; + nt.u.negTokenResp.mechListMIC->data = mech_mic_buf.value; + } else if (ret == GSS_S_UNAVAILABLE) { + nt.u.negTokenResp.mechListMIC = NULL; + } else { + free_NegotiationToken(&nt); return ret; } - resp.mechListMIC->length = mech_mic_buf.length; - resp.mechListMIC->data = mech_mic_buf.value; } else - resp.mechListMIC = NULL; + nt.u.negTokenResp.mechListMIC = NULL; - ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); - if (ret != GSS_S_COMPLETE) { - free_NegTokenResp(&resp); - return ret; + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, + &nt, &size, ret); + if (ret) { + free_NegotiationToken(&nt); + *minor_status = ret; + return GSS_S_FAILURE; } /* @@ -472,23 +321,12 @@ send_accept (OM_uint32 *minor_status, * it is a SubsequentContextToken (note though RFC 1964 * specifies encapsulation for all _Kerberos_ tokens). */ - output_token->value = malloc(data.length); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - } else { - output_token->length = data.length; - memcpy(output_token->value, data.value, output_token->length); - } - free(buf); - if (ret != GSS_S_COMPLETE) { - free_NegTokenResp(&resp); - return ret; - } - ret = (*(resp.negResult) == accept_completed) ? GSS_S_COMPLETE : - GSS_S_CONTINUE_NEEDED; - free_NegTokenResp(&resp); + if (*(nt.u.negTokenResp.negResult) == accept_completed) + ret = GSS_S_COMPLETE; + else + ret = GSS_S_CONTINUE_NEEDED; + free_NegotiationToken(&nt); return ret; } @@ -530,8 +368,164 @@ verify_mechlist_mic return ret; } -OM_uint32 -_gss_spnego_accept_sec_context +static OM_uint32 +select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, + gss_OID *mech_p) +{ + char mechbuf[64]; + size_t mech_len; + gss_OID_desc oid; + OM_uint32 ret, junk; + + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + mechType, + &mech_len); + if (ret) { + return GSS_S_DEFECTIVE_TOKEN; + } + + oid.length = mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { + return GSS_S_BAD_MECH; + } + + *minor_status = 0; + + /* Translate broken MS Kebreros OID */ + if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&_gss_spnego_krb5_mechanism_oid_desc); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &_gss_spnego_mskrb_mechanism_oid_desc, + mech_p); + } else { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&oid); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &mech->gm_mech_oid, + mech_p); + } + + if (verify_p) { + gss_name_t name = GSS_C_NO_NAME; + gss_buffer_desc namebuf; + char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; + + host = getenv("GSSAPI_SPNEGO_NAME"); + if (host == NULL || issuid()) { + if (gethostname(hostname, sizeof(hostname)) != 0) { + *minor_status = errno; + return GSS_S_FAILURE; + } + asprintf(&str, "host@%s", hostname); + host = str; + } + + namebuf.length = strlen(host); + namebuf.value = host; + + ret = gss_import_name(minor_status, &namebuf, + GSS_C_NT_HOSTBASED_SERVICE, &name); + if (str) + free(str); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = acceptor_approved(name, *mech_p); + gss_release_name(&junk, &name); + } + + return ret; +} + + +static OM_uint32 +acceptor_complete(OM_uint32 * minor_status, + gssspnego_ctx ctx, + int *get_mic, + gss_buffer_t mech_buf, + gss_buffer_t mech_input_token, + gss_buffer_t mech_output_token, + heim_octet_string *mic, + gss_buffer_t output_token) +{ + OM_uint32 ret; + int require_mic, verify_mic; + gss_buffer_desc buf; + + buf.length = 0; + buf.value = NULL; + + ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, &require_mic); + if (ret) + return ret; + + ctx->require_mic = require_mic; + + if (mic != NULL) + require_mic = 1; + + if (ctx->open && require_mic) { + if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ + verify_mic = 1; + *get_mic = 0; + } else if (mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length == 0) { /* Odd */ + *get_mic = verify_mic = 1; + } else { /* Even/One */ + verify_mic = 0; + *get_mic = 1; + } + + if (verify_mic || get_mic) { + int eret; + size_t buf_len; + + ASN1_MALLOC_ENCODE(MechTypeList, + mech_buf->value, mech_buf->length, + &ctx->initiator_mech_types, &buf_len, eret); + if (eret) { + *minor_status = eret; + return GSS_S_FAILURE; + } + if (buf.length != buf_len) + abort(); + } + + if (verify_mic) { + ret = verify_mechlist_mic(minor_status, ctx, mech_buf, mic); + if (ret) { + if (get_mic) + send_reject (minor_status, output_token); + if (buf.value) + free(buf.value); + return ret; + } + ctx->verified_mic = 1; + } + if (buf.value) + free(buf.value); + + } else + *get_mic = verify_mic = 0; + + return GSS_S_COMPLETE; +} + + +static OM_uint32 +acceptor_start (OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_cred_id_t acceptor_cred_handle, @@ -547,40 +541,21 @@ _gss_spnego_accept_sec_context { OM_uint32 ret, ret2, minor; NegTokenInit ni; - NegTokenResp na; - size_t ni_len, na_len; + size_t ni_len; int i; gss_buffer_desc data; size_t len, taglen; - int initialToken; - unsigned int negResult = accept_incomplete; gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; - gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; + gss_buffer_desc mech_output_token; gss_buffer_desc mech_buf; gss_OID preferred_mech_type = GSS_C_NO_OID; gssspnego_ctx ctx; gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; + int get_mic = 0; + int first_ok = 0; - *minor_status = 0; - - output_token->length = 0; - output_token->value = NULL; - - if (src_name != NULL) - *src_name = GSS_C_NO_NAME; - - if (mech_type != NULL) - *mech_type = GSS_C_NO_OID; - - if (ret_flags != NULL) - *ret_flags = 0; - - if (time_rec != NULL) - *time_rec = 0; - - if (delegated_cred_handle != NULL) - *delegated_cred_handle = GSS_C_NO_CREDENTIAL; - + mech_output_token.value = NULL; + mech_output_token.length = 0; mech_buf.value = NULL; if (*context_handle == GSS_C_NO_CONTEXT) { @@ -590,8 +565,7 @@ _gss_spnego_accept_sec_context return ret; if (input_token_buffer->length == 0) { - return send_supported_mechs (minor_status, - output_token); + return send_supported_mechs (minor_status, output_token); } } @@ -604,16 +578,12 @@ _gss_spnego_accept_sec_context ret = gss_decapsulate_token (input_token_buffer, GSS_SPNEGO_MECHANISM, &data); - initialToken = (ret == GSS_S_COMPLETE); - - if (!initialToken) { - data.value = input_token_buffer->value; - data.length = input_token_buffer->length; - } + if (ret) + return ret; ret = der_match_tag_and_length(data.value, data.length, ASN1_C_CONTEXT, CONS, - initialToken ? 0 : 1, + 0, &len, &taglen); if (ret) { *minor_status = ret; @@ -625,70 +595,263 @@ _gss_spnego_accept_sec_context return GSS_S_FAILURE; } - if (initialToken) { - ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, + ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, len, &ni, &ni_len); - } else { - ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, - len, &na, &na_len); - } if (ret) { *minor_status = ret; return GSS_S_DEFECTIVE_TOKEN; } - if (!initialToken && na.negResult != NULL) { - negResult = *(na.negResult); + if (ni.mechTypes.len < 1) { + free_NegTokenInit(&ni); + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; } - if (negResult == reject || negResult == request_mic) { - /* request_mic should only be sent by acceptor */ - free_NegTokenResp(&na); - return GSS_S_DEFECTIVE_TOKEN; + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenInit(&ni); + *minor_status = ret; + return GSS_S_FAILURE; } - if (initialToken) { - for (i = 0; i < ni.mechTypes.len; ++i) { - /* Call glue layer to find first mech we support */ - ret = _gss_spnego_select_mech(minor_status, &ni.mechTypes.val[i], - &preferred_mech_type); + /* + * First we try the opportunistic token if we have support for it, + * don't try to verify we have credential for the token, + * gss_accept_sec_context will (hopefully) tell us that. + * If that failes, + */ + + ret = select_mech(minor_status, + &ni.mechTypes.val[0], + 0, + &preferred_mech_type); + + if (ret == 0 && ni.mechToken != NULL) { + gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL; + gss_cred_id_t mech_cred; + gss_buffer_desc ibuf; + + ibuf.length = ni.mechToken->length; + ibuf.value = ni.mechToken->data; + mech_input_token = &ibuf; + + if (acceptor_cred != NULL) + mech_cred = acceptor_cred->negotiated_cred_id; + else + mech_cred = GSS_C_NO_CREDENTIAL; + + if (ctx->mech_src_name != GSS_C_NO_NAME) + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) + _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + + ret = gss_accept_sec_context(&minor, + &ctx->negotiated_ctx_id, + mech_cred, + mech_input_token, + input_chan_bindings, + &ctx->mech_src_name, + &ctx->negotiated_mech_type, + &mech_output_token, + &ctx->mech_flags, + &ctx->mech_time_rec, + &mech_delegated_cred); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + if (delegated_cred_handle) + ret = _gss_spnego_alloc_cred(minor_status, + mech_delegated_cred, + delegated_cred_handle); + else + gss_release_cred(&ret2, &mech_delegated_cred); + + ctx->preferred_mech_type = preferred_mech_type; + ctx->negotiated_mech_type = preferred_mech_type; + if (ret == GSS_S_COMPLETE) + ctx->open = 1; + + ret = acceptor_complete(minor_status, + ctx, + &get_mic, + &mech_buf, + mech_input_token, + &mech_output_token, + ni.mechListMIC, + output_token); + if (ret != GSS_S_COMPLETE) + goto out; + + first_ok = 1; + } + } + + /* + * If opportunistic token failed, lets try the other mechs. + */ + + if (!first_ok) { + + /* Call glue layer to find first mech we support */ + for (i = 1; i < ni.mechTypes.len; ++i) { + ret = select_mech(minor_status, + &ni.mechTypes.val[i], + 1, + &preferred_mech_type); if (ret == 0) break; } if (preferred_mech_type == GSS_C_NO_OID) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_NegTokenInit(&ni); return GSS_S_BAD_MECH; } + + ctx->preferred_mech_type = preferred_mech_type; + ctx->negotiated_mech_type = preferred_mech_type; } - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* + * The initial token always have a response + */ - if (initialToken) { - ctx->preferred_mech_type = preferred_mech_type; - ctx->initiator_mech_types.len = ni.mechTypes.len; - ctx->initiator_mech_types.val = ni.mechTypes.val; - ni.mechTypes.len = 0; - ni.mechTypes.val = NULL; + ret = send_accept (minor_status, + ctx, + &mech_output_token, + 1, + get_mic ? &mech_buf : NULL, + output_token); + if (ret) + goto out; + +out: + if (mech_output_token.value != NULL) + gss_release_buffer(&minor, &mech_output_token); + if (mech_buf.value != NULL) { + free(mech_buf.value); + mech_buf.value = NULL; + } + free_NegTokenInit(&ni); + + if (ret == GSS_S_COMPLETE) { + if (src_name != NULL && ctx->mech_src_name != NULL) { + spnego_name name; + + name = calloc(1, sizeof(*name)); + if (name) { + name->mech = ctx->mech_src_name; + ctx->mech_src_name = NULL; + *src_name = (gss_name_t)name; + } else + *src_name = GSS_C_NO_NAME; + } + if (delegated_cred_handle != NULL) { + *delegated_cred_handle = ctx->delegated_cred_id; + ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; + } + } + + if (mech_type != NULL) + *mech_type = ctx->negotiated_mech_type; + if (ret_flags != NULL) + *ret_flags = ctx->mech_flags; + if (time_rec != NULL) + *time_rec = ctx->mech_time_rec; + + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; } + _gss_spnego_internal_delete_sec_context(&minor, context_handle, + GSS_C_NO_BUFFER); + + return ret; +} + + +static OM_uint32 +acceptor_continue + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + OM_uint32 ret, ret2, minor; + NegTokenResp na; + size_t na_len; + gss_buffer_desc data; + size_t len, taglen; + unsigned int negResult = accept_incomplete; + gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; + gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; + gss_buffer_desc mech_buf; + gssspnego_ctx ctx; + gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; + + mech_buf.value = NULL; + + ctx = (gssspnego_ctx)*context_handle; + + /* + * The GSS-API encapsulation is only present on the initial + * context token (negTokenInit). + */ + + data.value = input_token_buffer->value; + data.length = input_token_buffer->length; + + ret = der_match_tag_and_length(data.value, data.length, + ASN1_C_CONTEXT, CONS, + 1, + &len, &taglen); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (len > data.length - taglen) { + *minor_status = ASN1_OVERRUN; + return GSS_S_FAILURE; + } + + ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, + len, &na, &na_len); + if (ret) { + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (na.negResult != NULL) { + negResult = *(na.negResult); + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + { gss_buffer_desc ibuf, obuf; - int require_mic, verify_mic, get_mic; + int require_mic, get_mic; int require_response; heim_octet_string *mic; - if (initialToken) { - if (ni.mechToken != NULL) { - ibuf.length = ni.mechToken->length; - ibuf.value = ni.mechToken->data; - mech_input_token = &ibuf; - } + if (na.responseToken != NULL) { + ibuf.length = na.responseToken->length; + ibuf.value = na.responseToken->data; + mech_input_token = &ibuf; } else { - if (na.responseToken != NULL) { - ibuf.length = na.responseToken->length; - ibuf.value = na.responseToken->data; - mech_input_token = &ibuf; - } + ibuf.value = NULL; + ibuf.length = 0; } if (mech_input_token != GSS_C_NO_BUFFER) { @@ -737,10 +900,7 @@ _gss_spnego_accept_sec_context mech_output_token = &obuf; } if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - if (initialToken) - free_NegTokenInit(&ni); - else - free_NegTokenResp(&na); + free_NegTokenResp(&na); send_reject (minor_status, output_token); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); return ret; @@ -758,50 +918,19 @@ _gss_spnego_accept_sec_context ctx->require_mic = require_mic; - mic = initialToken ? ni.mechListMIC : na.mechListMIC; + mic = na.mechListMIC; if (mic != NULL) require_mic = 1; - if (ctx->open && require_mic) { - if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ - verify_mic = 1; - get_mic = 0; - } else if (mech_output_token != GSS_C_NO_BUFFER && - mech_output_token->length == 0) { /* Odd */ - get_mic = verify_mic = 1; - } else { /* Even/One */ - verify_mic = 0; - get_mic = 1; - } - - if (verify_mic || get_mic) { - int eret; - size_t buf_len; - - ASN1_MALLOC_ENCODE(MechTypeList, - mech_buf.value, mech_buf.length, - &ctx->initiator_mech_types, &buf_len, eret); - if (eret) { - ret2 = GSS_S_FAILURE; - *minor_status = eret; - goto out; - } - if (mech_buf.length != buf_len) - abort(); - } - - if (verify_mic) { - ret2 = verify_mechlist_mic(minor_status, ctx, &mech_buf, mic); - if (ret2) { - if (get_mic) - send_reject (minor_status, output_token); - goto out; - } - - ctx->verified_mic = 1; - } - } else - verify_mic = get_mic = 0; + if (ret == GSS_S_COMPLETE) + ret = acceptor_complete(minor_status, + ctx, + &get_mic, + &mech_buf, + mech_input_token, + mech_output_token, + na.mechListMIC, + output_token); if (ctx->mech_flags & GSS_C_DCE_STYLE) require_response = (negResult != accept_completed); @@ -814,12 +943,13 @@ _gss_spnego_accept_sec_context */ if ((mech_output_token != GSS_C_NO_BUFFER && mech_output_token->length != 0) + || (ctx->open && negResult == accept_incomplete) || require_response || get_mic) { ret2 = send_accept (minor_status, ctx, mech_output_token, - initialToken, + 0, get_mic ? &mech_buf : NULL, output_token); if (ret2) @@ -833,10 +963,7 @@ _gss_spnego_accept_sec_context gss_release_buffer(&minor, mech_output_token); if (mech_buf.value != NULL) free(mech_buf.value); - if (initialToken) - free_NegTokenInit(&ni); - else - free_NegTokenResp(&na); + free_NegTokenResp(&na); } if (ret == GSS_S_COMPLETE) { @@ -871,3 +998,48 @@ _gss_spnego_accept_sec_context return ret; } +OM_uint32 +_gss_spnego_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + _gss_accept_sec_context_t *func; + + *minor_status = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + if (ret_flags != NULL) + *ret_flags = 0; + if (time_rec != NULL) + *time_rec = 0; + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + + if (*context_handle == GSS_C_NO_CONTEXT) + func = acceptor_start; + else + func = acceptor_continue; + + + return (*func)(minor_status, context_handle, acceptor_cred_handle, + input_token_buffer, input_chan_bindings, + src_name, mech_type, output_token, ret_flags, + time_rec, delegated_cred_handle); +} diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index aeae088258..786eac1340 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c,v 1.6 2006/10/07 22:26:59 lha Exp $"); +RCSID("$Id: compat.c,v 1.9 2006/12/18 17:52:26 lha Exp $"); /* * Apparently Microsoft got the OID wrong, and used @@ -42,10 +42,10 @@ RCSID("$Id: compat.c,v 1.6 2006/10/07 22:26:59 lha Exp $"); * prefer to deal with this here rather than inside the * Kerberos mechanism. */ -static gss_OID_desc gss_mskrb_mechanism_oid_desc = +gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc = {9, (void *)"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"}; -static gss_OID_desc gss_krb5_mechanism_oid_desc = +gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; /* @@ -191,8 +191,8 @@ _gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, if (*require_mic) { if (gss_oid_equal(ctx->negotiated_mech_type, ctx->preferred_mech_type)) { *require_mic = 0; - } else if (gss_oid_equal(ctx->negotiated_mech_type, &gss_krb5_mechanism_oid_desc) && - gss_oid_equal(ctx->preferred_mech_type, &gss_mskrb_mechanism_oid_desc)) { + } else if (gss_oid_equal(ctx->negotiated_mech_type, &_gss_spnego_krb5_mechanism_oid_desc) && + gss_oid_equal(ctx->preferred_mech_type, &_gss_spnego_mskrb_mechanism_oid_desc)) { *require_mic = 0; } } @@ -200,86 +200,122 @@ _gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, return GSS_S_COMPLETE; } -int _gss_spnego_add_mech_type(gss_OID mech_type, - int includeMSCompatOID, - MechTypeList *mechtypelist) +static int +add_mech_type(gss_OID mech_type, + int includeMSCompatOID, + MechTypeList *mechtypelist) { + MechType mech; int ret; if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) return 0; if (includeMSCompatOID && - gss_oid_equal(mech_type, &gss_krb5_mechanism_oid_desc)) { - ret = der_get_oid(gss_mskrb_mechanism_oid_desc.elements, - gss_mskrb_mechanism_oid_desc.length, - &mechtypelist->val[mechtypelist->len], + gss_oid_equal(mech_type, &_gss_spnego_krb5_mechanism_oid_desc)) { + ret = der_get_oid(_gss_spnego_mskrb_mechanism_oid_desc.elements, + _gss_spnego_mskrb_mechanism_oid_desc.length, + &mech, NULL); if (ret) return ret; - mechtypelist->len++; + ret = add_MechTypeList(mechtypelist, &mech); + free_MechType(&mech); + if (ret) + return ret; } - ret = der_get_oid(mech_type->elements, - mech_type->length, - &mechtypelist->val[mechtypelist->len], - NULL); + ret = der_get_oid(mech_type->elements, mech_type->length, &mech, NULL); if (ret) return ret; - mechtypelist->len++; - - return 0; + ret = add_MechTypeList(mechtypelist, &mech); + free_MechType(&mech); + return ret; } + OM_uint32 -_gss_spnego_select_mech(OM_uint32 *minor_status, - MechType *mechType, - gss_OID *mech_p) +_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, + gss_name_t target_name, + OM_uint32 (*func)(gss_name_t, gss_OID), + int includeMSCompatOID, + const gssspnego_cred cred_handle, + MechTypeList *mechtypelist, + gss_OID *preferred_mech) { - char mechbuf[64]; - size_t mech_len; - gss_OID_desc oid; + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; + gss_OID first_mech = GSS_C_NO_OID; OM_uint32 ret; - - ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, - sizeof(mechbuf), - mechType, - &mech_len); - if (ret) { - return GSS_S_DEFECTIVE_TOKEN; + int i; + + mechtypelist->len = 0; + mechtypelist->val = NULL; + + if (cred_handle != NULL) { + ret = gss_inquire_cred(minor_status, + cred_handle->negotiated_cred_id, + NULL, + NULL, + NULL, + &supported_mechs); + } else { + ret = gss_indicate_mechs(minor_status, &supported_mechs); } - oid.length = mech_len; - oid.elements = mechbuf + sizeof(mechbuf) - mech_len; - - if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { - return GSS_S_BAD_MECH; + if (ret != GSS_S_COMPLETE) { + return ret; } - *minor_status = 0; - - /* Translate broken MS Kebreros OID */ - if (gss_oid_equal(&oid, &gss_mskrb_mechanism_oid_desc)) { - gssapi_mech_interface mech; - - mech = __gss_get_mechanism(&gss_krb5_mechanism_oid_desc); - if (mech == NULL) - return GSS_S_BAD_MECH; + if (supported_mechs->count == 0) { + *minor_status = ENOENT; + gss_release_oid_set(minor_status, &supported_mechs); + return GSS_S_FAILURE; + } - ret = gss_duplicate_oid(minor_status, - &gss_mskrb_mechanism_oid_desc, - mech_p); - } else { - gssapi_mech_interface mech; + ret = (*func)(target_name, GSS_KRB5_MECHANISM); + if (ret == GSS_S_COMPLETE) { + ret = add_mech_type(GSS_KRB5_MECHANISM, + includeMSCompatOID, + mechtypelist); + if (!GSS_ERROR(ret)) + first_mech = GSS_KRB5_MECHANISM; + } + ret = GSS_S_COMPLETE; + + for (i = 0; i < supported_mechs->count; i++) { + OM_uint32 subret; + if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM)) + continue; + if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM)) + continue; + + subret = (*func)(target_name, &supported_mechs->elements[i]); + if (subret != GSS_S_COMPLETE) + continue; + + ret = add_mech_type(&supported_mechs->elements[i], + includeMSCompatOID, + mechtypelist); + if (ret != 0) { + *minor_status = ret; + ret = GSS_S_FAILURE; + break; + } + if (first_mech == GSS_C_NO_OID) + first_mech = &supported_mechs->elements[i]; + } - mech = __gss_get_mechanism(&oid); - if (mech == NULL) - return GSS_S_BAD_MECH; + if (mechtypelist->len == 0) { + gss_release_oid_set(minor_status, &supported_mechs); + *minor_status = 0; + return GSS_S_BAD_MECH; + } - ret = gss_duplicate_oid(minor_status, - &mech->gm_mech_oid, - mech_p); + if (preferred_mech != NULL) { + ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech); + if (ret != GSS_S_COMPLETE) + free_MechTypeList(mechtypelist); } + gss_release_oid_set(minor_status, &supported_mechs); return ret; } - diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 902ddbbdf9..57bc45a492 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c,v 1.8 2006/10/07 22:27:01 lha Exp $"); +RCSID("$Id: context_stubs.c,v 1.9 2006/12/18 12:59:44 lha Exp $"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) @@ -282,7 +282,21 @@ OM_uint32 _gss_spnego_compare_name int * name_equal ) { - return gss_compare_name(minor_status, name1, name2, name_equal); + spnego_name n1 = (spnego_name)name1; + spnego_name n2 = (spnego_name)name2; + + *name_equal = 0; + + if (!gss_oid_equal(&n1->type, &n2->type)) + return GSS_S_COMPLETE; + if (n1->value.length != n2->value.length) + return GSS_S_COMPLETE; + if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0) + return GSS_S_COMPLETE; + + *name_equal = 1; + + return GSS_S_COMPLETE; } OM_uint32 _gss_spnego_display_name @@ -292,19 +306,51 @@ OM_uint32 _gss_spnego_display_name gss_OID * output_name_type ) { - return gss_display_name(minor_status, input_name, + spnego_name name = (spnego_name)input_name; + + *minor_status = 0; + + if (name->mech == GSS_C_NO_NAME) + return GSS_S_FAILURE; + + return gss_display_name(minor_status, name->mech, output_name_buffer, output_name_type); } OM_uint32 _gss_spnego_import_name (OM_uint32 * minor_status, - const gss_buffer_t input_name_buffer, - const gss_OID input_name_type, + const gss_buffer_t name_buffer, + const gss_OID name_type, gss_name_t * output_name ) { - return gss_import_name(minor_status, input_name_buffer, - input_name_type, output_name); + spnego_name name; + OM_uint32 maj_stat; + + *minor_status = 0; + + name = calloc(1, sizeof(*name)); + if (name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + maj_stat = _gss_copy_oid(minor_status, name_type, &name->type); + if (maj_stat) { + free(name); + return GSS_S_FAILURE; + } + + maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value); + if (maj_stat) { + gss_name_t rname = (gss_name_t)name; + _gss_spnego_release_name(minor_status, &rname); + return GSS_S_FAILURE; + } + name->mech = GSS_C_NO_NAME; + *output_name = (gss_name_t)name; + + return GSS_S_COMPLETE; } OM_uint32 _gss_spnego_export_name @@ -313,8 +359,17 @@ OM_uint32 _gss_spnego_export_name gss_buffer_t exported_name ) { - return gss_export_name(minor_status, input_name, - exported_name); + spnego_name name; + *minor_status = 0; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + name = (spnego_name)input_name; + if (name->mech == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; + + return gss_export_name(minor_status, name->mech, exported_name); } OM_uint32 _gss_spnego_release_name @@ -322,7 +377,20 @@ OM_uint32 _gss_spnego_release_name gss_name_t * input_name ) { - return gss_release_name(minor_status, input_name); + *minor_status = 0; + + if (*input_name != GSS_C_NO_NAME) { + OM_uint32 junk; + spnego_name name = (spnego_name)*input_name; + _gss_free_oid(&junk, &name->type); + gss_release_buffer(&junk, &name->value); + if (name->mech != GSS_C_NO_NAME) + gss_release_name(&junk, &name->mech); + free(name); + + *input_name = GSS_C_NO_NAME; + } + return GSS_S_COMPLETE; } OM_uint32 _gss_spnego_inquire_context ( diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c index 5a652fdb2e..a221281a70 100644 --- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -33,7 +33,39 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: init_sec_context.c,v 1.6 2006/10/14 10:09:15 lha Exp $"); +RCSID("$Id: init_sec_context.c,v 1.11 2006/12/18 15:42:03 lha Exp $"); + +/* + * Is target_name an sane target for `mech´. + */ + +static OM_uint32 +initiator_approved(gss_name_t target_name, gss_OID mech) +{ + OM_uint32 min_stat, maj_stat; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc out; + + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &ctx, + target_name, + mech, + 0, + GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, + NULL, + &out, + NULL, + NULL); + if (GSS_ERROR(maj_stat)) + return GSS_S_BAD_MECH; + gss_release_buffer(&min_stat, &out); + gss_delete_sec_context(&min_stat, &ctx, NULL); + + return GSS_S_COMPLETE; +} /* * Send a reply. Note that we only need to send a reply if we @@ -50,11 +82,10 @@ spnego_reply_internal(OM_uint32 *minor_status, gss_buffer_t mech_token, gss_buffer_t output_token) { - NegTokenResp resp; + NegotiationToken nt; gss_buffer_desc mic_buf; OM_uint32 ret; - gss_buffer_desc data; - u_char *buf; + size_t size; if (mech_buf == GSS_C_NO_BUFFER && mech_token->length == 0) { output_token->length = 0; @@ -63,85 +94,83 @@ spnego_reply_internal(OM_uint32 *minor_status, return context_handle->open ? GSS_S_COMPLETE : GSS_S_FAILURE; } - memset(&resp, 0, sizeof(resp)); + memset(&nt, 0, sizeof(nt)); - ALLOC(resp.negResult, 1); - if (resp.negResult == NULL) { + nt.element = choice_NegotiationToken_negTokenResp; + + ALLOC(nt.u.negTokenResp.negResult, 1); + if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } - resp.supportedMech = NULL; + nt.u.negTokenResp.supportedMech = NULL; output_token->length = 0; output_token->value = NULL; if (mech_token->length == 0) { - resp.responseToken = NULL; - *(resp.negResult) = accept_completed; + nt.u.negTokenResp.responseToken = NULL; + *(nt.u.negTokenResp.negResult) = accept_completed; } else { - ALLOC(resp.responseToken, 1); - if (resp.responseToken == NULL) { - free_NegTokenResp(&resp); + ALLOC(nt.u.negTokenResp.responseToken, 1); + if (nt.u.negTokenResp.responseToken == NULL) { + free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } - resp.responseToken->length = mech_token->length; - resp.responseToken->data = mech_token->value; + nt.u.negTokenResp.responseToken->length = mech_token->length; + nt.u.negTokenResp.responseToken->data = mech_token->value; mech_token->length = 0; mech_token->value = NULL; - *(resp.negResult) = accept_incomplete; + *(nt.u.negTokenResp.negResult) = accept_incomplete; } if (mech_buf != GSS_C_NO_BUFFER) { - ALLOC(resp.mechListMIC, 1); - if (resp.mechListMIC == NULL) { - free_NegTokenResp(&resp); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } ret = gss_get_mic(minor_status, context_handle->negotiated_ctx_id, 0, mech_buf, &mic_buf); - if (ret) { - free_NegTokenResp(&resp); + if (ret == GSS_S_COMPLETE) { + ALLOC(nt.u.negTokenResp.mechListMIC, 1); + if (nt.u.negTokenResp.mechListMIC == NULL) { + gss_release_buffer(minor_status, &mic_buf); + free_NegotiationToken(&nt); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + nt.u.negTokenResp.mechListMIC->length = mic_buf.length; + nt.u.negTokenResp.mechListMIC->data = mic_buf.value; + } else if (ret == GSS_S_UNAVAILABLE) { + nt.u.negTokenResp.mechListMIC = NULL; + } if (ret) { + free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } - - resp.mechListMIC->length = mic_buf.length; - resp.mechListMIC->data = mic_buf.value; } else { - resp.mechListMIC = NULL; + nt.u.negTokenResp.mechListMIC = NULL; } - ret = _gss_spnego_encode_response (minor_status, &resp, - &data, &buf); + ASN1_MALLOC_ENCODE(NegotiationToken, + output_token->value, output_token->length, + &nt, &size, ret); if (ret) { - free_NegTokenResp(&resp); - return ret; - } - - output_token->value = malloc(data.length); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - } else { - output_token->length = data.length; - memcpy(output_token->value, data.value, output_token->length); + free_NegotiationToken(&nt); + *minor_status = ret; + return GSS_S_FAILURE; } - free(buf); - if (*(resp.negResult) == accept_completed) + if (*(nt.u.negTokenResp.negResult) == accept_completed) ret = GSS_S_COMPLETE; else ret = GSS_S_CONTINUE_NEEDED; - free_NegTokenResp(&resp); + free_NegotiationToken(&nt); return ret; } @@ -172,12 +201,16 @@ spnego_initial size_t ni_len; gss_ctx_id_t context; gssspnego_ctx ctx; + spnego_name name = (spnego_name)target_name; + + *minor_status = 0; memset (&ni, 0, sizeof(ni)); *context_handle = GSS_C_NO_CONTEXT; - *minor_status = 0; + if (target_name == GSS_C_NO_NAME) + return GSS_S_BAD_NAME; sub = _gss_spnego_alloc_sec_context(&minor, &context); if (GSS_ERROR(sub)) { @@ -190,7 +223,17 @@ spnego_initial ctx->local = 1; - sub = _gss_spnego_indicate_mechtypelist(&minor, 0, + sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name); + if (GSS_ERROR(sub)) { + *minor_status = minor; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + sub = _gss_spnego_indicate_mechtypelist(&minor, + ctx->target_name, + initiator_approved, + 0, cred, &ni.mechTypes, &ctx->preferred_mech_type); @@ -212,8 +255,8 @@ spnego_initial (cred != NULL) ? cred->negotiated_cred_id : GSS_C_NO_CREDENTIAL, &ctx->negotiated_ctx_id, - target_name, - GSS_C_NO_OID, + ctx->target_name, + ctx->preferred_mech_type, req_flags, time_req, input_chan_bindings, @@ -228,6 +271,8 @@ spnego_initial _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } + if (sub == GSS_S_COMPLETE) + ctx->maybe_open = 1; if (mech_token.length != 0) { ALLOC(ni.mechToken, 1); @@ -345,8 +390,6 @@ spnego_reply { OM_uint32 ret, minor; NegTokenResp resp; - u_char oidbuf[17]; - size_t oidlen; size_t len, taglen; gss_OID_desc mech; int require_mic; @@ -385,34 +428,73 @@ spnego_reply if (resp.negResult == NULL || *(resp.negResult) == reject - || resp.supportedMech == NULL) { + /* || resp.supportedMech == NULL */ + ) + { free_NegTokenResp(&resp); return GSS_S_BAD_MECH; } - ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1, - sizeof(oidbuf), - resp.supportedMech, - &oidlen); - if (ret || (oidlen == GSS_SPNEGO_MECHANISM->length && - memcmp(oidbuf + sizeof(oidbuf) - oidlen, - GSS_SPNEGO_MECHANISM->elements, - oidlen) == 0)) { + /* + * Pick up the mechanism that the acceptor selected, only allow it + * to be sent in packet. + */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (resp.supportedMech) { + + if (ctx->oidlen) { + free_NegTokenResp(&resp); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_BAD_MECH; + } + ret = der_put_oid(ctx->oidbuf + sizeof(ctx->oidbuf) - 1, + sizeof(ctx->oidbuf), + resp.supportedMech, + &ctx->oidlen); /* Avoid recursively embedded SPNEGO */ + if (ret || (ctx->oidlen == GSS_SPNEGO_MECHANISM->length && + memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen, + GSS_SPNEGO_MECHANISM->elements, + ctx->oidlen) == 0)) + { + free_NegTokenResp(&resp); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_BAD_MECH; + } + + /* check if the acceptor took our optimistic token */ + if (ctx->oidlen != ctx->preferred_mech_type->length || + memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen, + ctx->preferred_mech_type->elements, + ctx->oidlen) != 0) + { + gss_delete_sec_context(&minor, &ctx->negotiated_ctx_id, + GSS_C_NO_BUFFER); + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + } + } else if (ctx->oidlen == 0) { free_NegTokenResp(&resp); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); return GSS_S_BAD_MECH; } - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - - if (resp.responseToken != NULL) { + if (resp.responseToken != NULL || + ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { gss_buffer_desc mech_input_token; - mech_input_token.length = resp.responseToken->length; - mech_input_token.value = resp.responseToken->data; + if (resp.responseToken) { + mech_input_token.length = resp.responseToken->length; + mech_input_token.value = resp.responseToken->data; + } else { + mech_input_token.length = 0; + mech_input_token.value = NULL; + } - mech.length = oidlen; - mech.elements = oidbuf + sizeof(oidbuf) - oidlen; + + mech.length = ctx->oidlen; + mech.elements = ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen; /* Fall through as if the negotiated mechanism was requested explicitly */ @@ -420,7 +502,7 @@ spnego_reply (cred != NULL) ? cred->negotiated_cred_id : GSS_C_NO_CREDENTIAL, &ctx->negotiated_ctx_id, - target_name, + ctx->target_name, &mech, req_flags, time_req, @@ -439,6 +521,9 @@ spnego_reply if (ret == GSS_S_COMPLETE) { ctx->open = 1; } + } else if (*(resp.negResult) == accept_completed) { + if (ctx->maybe_open) + ctx->open = 1; } if (*(resp.negResult) == request_mic) { diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h index df50f65580..d80db0018a 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego-private.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -46,12 +46,6 @@ _gss_spnego_add_cred ( OM_uint32 * /*initiator_time_rec*/, OM_uint32 * acceptor_time_rec ); -int -_gss_spnego_add_mech_type ( - gss_OID /*mech_type*/, - int /*includeMSCompatOID*/, - MechTypeList */*mechtypelist*/); - OM_uint32 _gss_spnego_alloc_cred ( OM_uint32 */*minor_status*/, @@ -111,13 +105,6 @@ _gss_spnego_duplicate_name ( const gss_name_t /*src_name*/, gss_name_t * dest_name ); -OM_uint32 -_gss_spnego_encode_response ( - OM_uint32 */*minor_status*/, - const NegTokenResp */*resp*/, - gss_buffer_t /*data*/, - u_char **/*ret_buf*/); - OM_uint32 _gss_spnego_export_name ( OM_uint32 * /*minor_status*/, @@ -141,8 +128,8 @@ _gss_spnego_get_mic ( OM_uint32 _gss_spnego_import_name ( OM_uint32 * /*minor_status*/, - const gss_buffer_t /*input_name_buffer*/, - const gss_OID /*input_name_type*/, + const gss_buffer_t /*name_buffer*/, + const gss_OID /*name_type*/, gss_name_t * output_name ); OM_uint32 @@ -154,6 +141,8 @@ _gss_spnego_import_sec_context ( OM_uint32 _gss_spnego_indicate_mechtypelist ( OM_uint32 */*minor_status*/, + gss_name_t /*target_name*/, + OM_uint32 (*/*func*/)(gss_name_t, gss_OID), int /*includeMSCompatOID*/, const gssspnego_cred /*cred_handle*/, MechTypeList */*mechtypelist*/, @@ -270,12 +259,6 @@ _gss_spnego_seal ( int * /*conf_state*/, gss_buffer_t output_message_buffer ); -OM_uint32 -_gss_spnego_select_mech ( - OM_uint32 */*minor_status*/, - MechType */*mechType*/, - gss_OID */*mech_p*/); - OM_uint32 _gss_spnego_set_sec_context_option ( OM_uint32 * /*minor_status*/, diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 index 187ce0a0a6..76fafa356c 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -1,4 +1,4 @@ --- $Id: spnego.asn1,v 1.1.1.1 2006/06/28 08:34:45 lha Exp $ +-- $Id: spnego.asn1,v 1.3 2006/12/18 18:28:49 lha Exp $ SPNEGO DEFINITIONS ::= BEGIN @@ -22,14 +22,21 @@ NegHints ::= SEQUENCE { hintAddress [1] OCTET STRING OPTIONAL } +NegTokenInitWin ::= SEQUENCE { + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + negHints [3] NegHints OPTIONAL + } + NegTokenInit ::= SEQUENCE { mechTypes [0] MechTypeList, reqFlags [1] ContextFlags OPTIONAL, mechToken [2] OCTET STRING OPTIONAL, - negHints [3] NegHints OPTIONAL, - mechListMIC [4] OCTET STRING OPTIONAL + mechListMIC [3] OCTET STRING OPTIONAL } + -- NB: negResult is not OPTIONAL in the new SPNEGO spec but -- Windows clients do not always send it NegTokenResp ::= SEQUENCE { @@ -48,4 +55,8 @@ NegotiationToken ::= CHOICE { negTokenResp[1] NegTokenResp } +NegotiationTokenWin ::= CHOICE { + negTokenInit[0] NegTokenInitWin +} + END diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h index 255e07d056..45dff04313 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: spnego_locl.h,v 1.12 2006/11/07 19:53:40 lha Exp $ */ +/* $Id: spnego_locl.h,v 1.15 2006/12/18 15:42:03 lha Exp $ */ #ifndef SPNEGO_LOCL_H #define SPNEGO_LOCL_H @@ -67,6 +67,7 @@ #include #include "spnego_asn1.h" +#include "mech/utils.h" #include #include @@ -86,13 +87,29 @@ typedef struct { OM_uint32 mech_time_rec; gss_name_t mech_src_name; gss_cred_id_t delegated_cred_id; - int open : 1; - int local : 1; - int require_mic : 1; - int verified_mic : 1; + unsigned int open : 1; + unsigned int local : 1; + unsigned int require_mic : 1; + unsigned int verified_mic : 1; + unsigned int maybe_open : 1; HEIMDAL_MUTEX ctx_id_mutex; + + gss_name_t target_name; + + u_char oidbuf[17]; + size_t oidlen; + } *gssspnego_ctx; +typedef struct { + gss_OID_desc type; + gss_buffer_desc value; + gss_name_t mech; +} *spnego_name; + +extern gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc; +extern gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc; + #include #endif /* SPNEGO_LOCL_H */ -- cgit From 91adebe749beb0dc23cacaea316cb2b724776aad Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 13 Jun 2007 05:44:24 +0000 Subject: r23456: Update Samba4 to current lorikeet-heimdal. Andrew Bartlett (This used to be commit ae0f81ab235c72cceb120bcdeb051a483cf3cc4f) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 17 ++++--- source4/heimdal/lib/gssapi/spnego/compat.c | 2 +- source4/heimdal/lib/gssapi/spnego/context_stubs.c | 4 +- source4/heimdal/lib/gssapi/spnego/cred_stubs.c | 57 +++++++++++++++++++--- source4/heimdal/lib/gssapi/spnego/external.c | 2 +- .../heimdal/lib/gssapi/spnego/init_sec_context.c | 2 +- source4/heimdal/lib/gssapi/spnego/spnego.asn1 | 2 +- source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 2 +- 8 files changed, 67 insertions(+), 21 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 2c86b3f794..106897b9b0 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c,v 1.16 2006/12/19 12:10:35 lha Exp $"); +RCSID("$Id: accept_sec_context.c 20929 2007-06-05 21:19:22Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -92,7 +92,7 @@ send_supported_mechs (OM_uint32 *minor_status, gss_buffer_t output_token) { NegotiationTokenWin nt; - char hostname[MAXHOSTNAMELEN], *p; + char hostname[MAXHOSTNAMELEN + 1], *p; gss_buffer_desc name_buf; gss_OID name_type; gss_name_t target_princ; @@ -117,11 +117,12 @@ send_supported_mechs (OM_uint32 *minor_status, } memset(&target_princ, 0, sizeof(target_princ)); - if (gethostname(hostname, sizeof(hostname) - 1) != 0) { + if (gethostname(hostname, sizeof(hostname) - 2) != 0) { *minor_status = errno; free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } + hostname[sizeof(hostname) - 1] = '\0'; /* Send the constructed SAM name for this host */ for (p = hostname; *p != '\0' && *p != '.'; p++) { @@ -662,6 +663,11 @@ acceptor_start &ctx->mech_time_rec, &mech_delegated_cred); if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + ctx->preferred_mech_type = preferred_mech_type; + ctx->negotiated_mech_type = preferred_mech_type; + if (ret == GSS_S_COMPLETE) + ctx->open = 1; + if (delegated_cred_handle) ret = _gss_spnego_alloc_cred(minor_status, mech_delegated_cred, @@ -669,11 +675,6 @@ acceptor_start else gss_release_cred(&ret2, &mech_delegated_cred); - ctx->preferred_mech_type = preferred_mech_type; - ctx->negotiated_mech_type = preferred_mech_type; - if (ret == GSS_S_COMPLETE) - ctx->open = 1; - ret = acceptor_complete(minor_status, ctx, &get_mic, diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index 786eac1340..bc7da9410e 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c,v 1.9 2006/12/18 17:52:26 lha Exp $"); +RCSID("$Id: compat.c 19415 2006-12-18 17:52:26Z lha $"); /* * Apparently Microsoft got the OID wrong, and used diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 57bc45a492..3535c7bb35 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c,v 1.9 2006/12/18 12:59:44 lha Exp $"); +RCSID("$Id: context_stubs.c 21035 2007-06-09 15:32:47Z lha $"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) @@ -310,7 +310,7 @@ OM_uint32 _gss_spnego_display_name *minor_status = 0; - if (name->mech == GSS_C_NO_NAME) + if (name == NULL || name->mech == GSS_C_NO_NAME) return GSS_S_FAILURE; return gss_display_name(minor_status, name->mech, diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c index 8f8edab15e..2362e99019 100644 --- a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: cred_stubs.c,v 1.5 2006/10/07 22:27:04 lha Exp $"); +RCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $"); OM_uint32 _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) @@ -97,6 +97,8 @@ OM_uint32 _gss_spnego_acquire_cred OM_uint32 * time_rec ) { + const spnego_name dname = (const spnego_name)desired_name; + gss_name_t name = GSS_C_NO_NAME; OM_uint32 ret, tmp; gss_OID_set_desc actual_desired_mechs; gss_OID_set mechs; @@ -106,9 +108,18 @@ OM_uint32 _gss_spnego_acquire_cred *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (dname) { + ret = gss_import_name(minor_status, &dname->value, &dname->type, &name); + if (ret) { + return ret; + } + } + ret = gss_indicate_mechs(minor_status, &mechs); - if (ret != GSS_S_COMPLETE) + if (ret != GSS_S_COMPLETE) { + gss_release_name(minor_status, &name); return ret; + } /* Remove ourselves from this list */ actual_desired_mechs.count = mechs->count; @@ -135,7 +146,7 @@ OM_uint32 _gss_spnego_acquire_cred goto out; cred = (gssspnego_cred)cred_handle; - ret = gss_acquire_cred(minor_status, desired_name, + ret = gss_acquire_cred(minor_status, name, time_req, &actual_desired_mechs, cred_usage, &cred->negotiated_cred_id, @@ -146,6 +157,7 @@ OM_uint32 _gss_spnego_acquire_cred *output_cred_handle = cred_handle; out: + gss_release_name(minor_status, &name); gss_release_oid_set(&tmp, &mechs); if (actual_desired_mechs.elements != NULL) { free(actual_desired_mechs.elements); @@ -167,6 +179,7 @@ OM_uint32 _gss_spnego_inquire_cred ) { gssspnego_cred cred; + spnego_name sname = NULL; OM_uint32 ret; if (cred_handle == GSS_C_NO_CREDENTIAL) { @@ -174,14 +187,29 @@ OM_uint32 _gss_spnego_inquire_cred return GSS_S_NO_CRED; } + if (name) { + sname = calloc(1, sizeof(*sname)); + if (sname == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } + cred = (gssspnego_cred)cred_handle; ret = gss_inquire_cred(minor_status, cred->negotiated_cred_id, - name, + sname ? &sname->mech : NULL, lifetime, cred_usage, mechanisms); + if (ret) { + if (sname) + free(sname); + return ret; + } + if (name) + *name = (gss_name_t)sname; return ret; } @@ -246,6 +274,7 @@ OM_uint32 _gss_spnego_inquire_cred_by_mech ( ) { gssspnego_cred cred; + spnego_name sname = NULL; OM_uint32 ret; if (cred_handle == GSS_C_NO_CREDENTIAL) { @@ -253,17 +282,33 @@ OM_uint32 _gss_spnego_inquire_cred_by_mech ( return GSS_S_NO_CRED; } + if (name) { + sname = calloc(1, sizeof(*sname)); + if (sname == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } + cred = (gssspnego_cred)cred_handle; ret = gss_inquire_cred_by_mech(minor_status, cred->negotiated_cred_id, mech_type, - name, + sname ? &sname->mech : NULL, initiator_lifetime, acceptor_lifetime, cred_usage); - return ret; + if (ret) { + if (sname) + free(sname); + return ret; + } + if (name) + *name = (gss_name_t)sname; + + return GSS_S_COMPLETE; } OM_uint32 _gss_spnego_inquire_cred_by_oid diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index b7e02a55e1..fbc231f3ae 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" #include -RCSID("$Id: external.c,v 1.7 2006/10/07 22:27:06 lha Exp $"); +RCSID("$Id: external.c 18336 2006-10-07 22:27:13Z lha $"); /* * RFC2478, SPNEGO: diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c index a221281a70..7c74981e66 100644 --- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: init_sec_context.c,v 1.11 2006/12/18 15:42:03 lha Exp $"); +RCSID("$Id: init_sec_context.c 19411 2006-12-18 15:42:03Z lha $"); /* * Is target_name an sane target for `mech´. diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 index 76fafa356c..aed67dc4ae 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -1,4 +1,4 @@ --- $Id: spnego.asn1,v 1.3 2006/12/18 18:28:49 lha Exp $ +-- $Id: spnego.asn1 19420 2006-12-18 18:28:49Z lha $ SPNEGO DEFINITIONS ::= BEGIN diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h index 45dff04313..44b24688e1 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: spnego_locl.h,v 1.15 2006/12/18 15:42:03 lha Exp $ */ +/* $Id: spnego_locl.h 19411 2006-12-18 15:42:03Z lha $ */ #ifndef SPNEGO_LOCL_H #define SPNEGO_LOCL_H -- cgit From ec0035c9b8e0690f3bc21f3de089c39eae660916 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 3 Jul 2007 08:00:08 +0000 Subject: r23678: Update to current lorikeet-heimdal (-r 767), which should fix the panics on hosts without /dev/random. Andrew Bartlett (This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 135 +++++++++------------ 1 file changed, 60 insertions(+), 75 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 106897b9b0..d20c913bf0 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 20929 2007-06-05 21:19:22Z lha $"); +RCSID("$Id: accept_sec_context.c 21243 2007-06-20 15:16:22Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -540,12 +540,12 @@ acceptor_start gss_cred_id_t *delegated_cred_handle ) { - OM_uint32 ret, ret2, minor; - NegTokenInit ni; - size_t ni_len; + OM_uint32 ret, junk, minor; + NegotiationToken nt; + size_t nt_len; + NegTokenInit *ni; int i; gss_buffer_desc data; - size_t len, taglen; gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; gss_buffer_desc mech_output_token; gss_buffer_desc mech_buf; @@ -555,6 +555,9 @@ acceptor_start int get_mic = 0; int first_ok = 0; + if (src_name) + *src_name = GSS_C_NO_NAME; + mech_output_token.value = NULL; mech_output_token.length = 0; mech_buf.value = NULL; @@ -582,39 +585,30 @@ acceptor_start if (ret) return ret; - ret = der_match_tag_and_length(data.value, data.length, - ASN1_C_CONTEXT, CONS, - 0, - &len, &taglen); + ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len); + gss_release_buffer(minor_status, &data); if (ret) { *minor_status = ret; - return GSS_S_FAILURE; - } - - if (len > data.length - taglen) { - *minor_status = ASN1_OVERRUN; - return GSS_S_FAILURE; + return GSS_S_DEFECTIVE_TOKEN; } - - ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, - len, &ni, &ni_len); - if (ret) { - *minor_status = ret; + if (nt.element != choice_NegotiationToken_negTokenInit) { + *minor_status = 0; return GSS_S_DEFECTIVE_TOKEN; } + ni = &nt.u.negTokenInit; - if (ni.mechTypes.len < 1) { - free_NegTokenInit(&ni); + if (ni->mechTypes.len < 1) { + free_NegotiationToken(&nt); *minor_status = 0; return GSS_S_DEFECTIVE_TOKEN; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types); + ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types); if (ret) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - free_NegTokenInit(&ni); + free_NegotiationToken(&nt); *minor_status = ret; return GSS_S_FAILURE; } @@ -627,17 +621,17 @@ acceptor_start */ ret = select_mech(minor_status, - &ni.mechTypes.val[0], + &ni->mechTypes.val[0], 0, &preferred_mech_type); - if (ret == 0 && ni.mechToken != NULL) { + if (ret == 0 && ni->mechToken != NULL) { gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL; gss_cred_id_t mech_cred; gss_buffer_desc ibuf; - ibuf.length = ni.mechToken->length; - ibuf.value = ni.mechToken->data; + ibuf.length = ni->mechToken->length; + ibuf.value = ni->mechToken->data; mech_input_token = &ibuf; if (acceptor_cred != NULL) @@ -668,12 +662,12 @@ acceptor_start if (ret == GSS_S_COMPLETE) ctx->open = 1; - if (delegated_cred_handle) + if (mech_delegated_cred && delegated_cred_handle) ret = _gss_spnego_alloc_cred(minor_status, mech_delegated_cred, delegated_cred_handle); else - gss_release_cred(&ret2, &mech_delegated_cred); + gss_release_cred(&junk, &mech_delegated_cred); ret = acceptor_complete(minor_status, ctx, @@ -681,7 +675,7 @@ acceptor_start &mech_buf, mech_input_token, &mech_output_token, - ni.mechListMIC, + ni->mechListMIC, output_token); if (ret != GSS_S_COMPLETE) goto out; @@ -697,9 +691,9 @@ acceptor_start if (!first_ok) { /* Call glue layer to find first mech we support */ - for (i = 1; i < ni.mechTypes.len; ++i) { + for (i = 1; i < ni->mechTypes.len; ++i) { ret = select_mech(minor_status, - &ni.mechTypes.val[i], + &ni->mechTypes.val[i], 1, &preferred_mech_type); if (ret == 0) @@ -707,7 +701,7 @@ acceptor_start } if (preferred_mech_type == GSS_C_NO_OID) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - free_NegTokenInit(&ni); + free_NegotiationToken(&nt); return GSS_S_BAD_MECH; } @@ -735,7 +729,8 @@ out: free(mech_buf.value); mech_buf.value = NULL; } - free_NegTokenInit(&ni); + free_NegotiationToken(&nt); + if (ret == GSS_S_COMPLETE) { if (src_name != NULL && ctx->mech_src_name != NULL) { @@ -746,8 +741,7 @@ out: name->mech = ctx->mech_src_name; ctx->mech_src_name = NULL; *src_name = (gss_name_t)name; - } else - *src_name = GSS_C_NO_NAME; + } } if (delegated_cred_handle != NULL) { *delegated_cred_handle = ctx->delegated_cred_id; @@ -790,10 +784,9 @@ acceptor_continue ) { OM_uint32 ret, ret2, minor; - NegTokenResp na; - size_t na_len; - gss_buffer_desc data; - size_t len, taglen; + NegotiationToken nt; + size_t nt_len; + NegTokenResp *na; unsigned int negResult = accept_incomplete; gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; @@ -810,45 +803,34 @@ acceptor_continue * context token (negTokenInit). */ - data.value = input_token_buffer->value; - data.length = input_token_buffer->length; - - ret = der_match_tag_and_length(data.value, data.length, - ASN1_C_CONTEXT, CONS, - 1, - &len, &taglen); + ret = decode_NegotiationToken(input_token_buffer->value, + input_token_buffer->length, + &nt, &nt_len); if (ret) { *minor_status = ret; - return GSS_S_FAILURE; - } - - if (len > data.length - taglen) { - *minor_status = ASN1_OVERRUN; - return GSS_S_FAILURE; + return GSS_S_DEFECTIVE_TOKEN; } - - ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, - len, &na, &na_len); - if (ret) { - *minor_status = ret; + if (nt.element != choice_NegotiationToken_negTokenResp) { + *minor_status = 0; return GSS_S_DEFECTIVE_TOKEN; } + na = &nt.u.negTokenResp; - if (na.negResult != NULL) { - negResult = *(na.negResult); + if (na->negResult != NULL) { + negResult = *(na->negResult); } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); { gss_buffer_desc ibuf, obuf; - int require_mic, get_mic; + int require_mic, get_mic = 0; int require_response; heim_octet_string *mic; - if (na.responseToken != NULL) { - ibuf.length = na.responseToken->length; - ibuf.value = na.responseToken->data; + if (na->responseToken != NULL) { + ibuf.length = na->responseToken->length; + ibuf.value = na->responseToken->data; mech_input_token = &ibuf; } else { ibuf.value = NULL; @@ -901,7 +883,7 @@ acceptor_continue mech_output_token = &obuf; } if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - free_NegTokenResp(&na); + free_NegotiationToken(&nt); send_reject (minor_status, output_token); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); return ret; @@ -919,7 +901,7 @@ acceptor_continue ctx->require_mic = require_mic; - mic = na.mechListMIC; + mic = na->mechListMIC; if (mic != NULL) require_mic = 1; @@ -930,7 +912,7 @@ acceptor_continue &mech_buf, mech_input_token, mech_output_token, - na.mechListMIC, + na->mechListMIC, output_token); if (ctx->mech_flags & GSS_C_DCE_STYLE) @@ -964,16 +946,19 @@ acceptor_continue gss_release_buffer(&minor, mech_output_token); if (mech_buf.value != NULL) free(mech_buf.value); - free_NegTokenResp(&na); + free_NegotiationToken(&nt); } if (ret == GSS_S_COMPLETE) { - if (src_name != NULL) { - ret2 = gss_duplicate_name(minor_status, - ctx->mech_src_name, - src_name); - if (ret2 != GSS_S_COMPLETE) - ret = ret2; + if (src_name != NULL && ctx->mech_src_name != NULL) { + spnego_name name; + + name = calloc(1, sizeof(*name)); + if (name) { + name->mech = ctx->mech_src_name; + ctx->mech_src_name = NULL; + *src_name = (gss_name_t)name; + } } if (delegated_cred_handle != NULL) { *delegated_cred_handle = ctx->delegated_cred_id; -- cgit From b39330c4873d4c3923a577e89690fc0e43b0c61a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Aug 2007 06:46:34 +0000 Subject: r24614: Merge with current lorikeet-heimdal. This brings us one step closer to an alpha release. Andrew Bartlett (This used to be commit 30e02747d511630659c59eafec8d28f58605943b) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 21 ++++------ source4/heimdal/lib/gssapi/spnego/spnego.asn1 | 45 +++++++++++----------- 2 files changed, 30 insertions(+), 36 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index d20c913bf0..1afe26f1e3 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 21243 2007-06-20 15:16:22Z lha $"); +RCSID("$Id: accept_sec_context.c 21461 2007-07-10 14:01:13Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -555,23 +555,16 @@ acceptor_start int get_mic = 0; int first_ok = 0; - if (src_name) - *src_name = GSS_C_NO_NAME; - mech_output_token.value = NULL; mech_output_token.length = 0; mech_buf.value = NULL; - if (*context_handle == GSS_C_NO_CONTEXT) { - ret = _gss_spnego_alloc_sec_context(minor_status, - context_handle); - if (ret != GSS_S_COMPLETE) - return ret; - - if (input_token_buffer->length == 0) { - return send_supported_mechs (minor_status, output_token); - } - } + if (input_token_buffer->length == 0) + return send_supported_mechs (minor_status, output_token); + + ret = _gss_spnego_alloc_sec_context(minor_status, context_handle); + if (ret != GSS_S_COMPLETE) + return ret; ctx = (gssspnego_ctx)*context_handle; diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 index aed67dc4ae..058f10ba3a 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -1,4 +1,4 @@ --- $Id: spnego.asn1 19420 2006-12-18 18:28:49Z lha $ +-- $Id: spnego.asn1 21403 2007-07-04 08:13:12Z lha $ SPNEGO DEFINITIONS ::= BEGIN @@ -8,34 +8,34 @@ MechType::= OBJECT IDENTIFIER MechTypeList ::= SEQUENCE OF MechType ContextFlags ::= BIT STRING { - delegFlag (0), - mutualFlag (1), - replayFlag (2), - sequenceFlag (3), - anonFlag (4), - confFlag (5), - integFlag (6) + delegFlag (0), + mutualFlag (1), + replayFlag (2), + sequenceFlag (3), + anonFlag (4), + confFlag (5), + integFlag (6) } NegHints ::= SEQUENCE { - hintName [0] GeneralString OPTIONAL, - hintAddress [1] OCTET STRING OPTIONAL + hintName [0] GeneralString OPTIONAL, + hintAddress [1] OCTET STRING OPTIONAL } NegTokenInitWin ::= SEQUENCE { - mechTypes [0] MechTypeList, - reqFlags [1] ContextFlags OPTIONAL, - mechToken [2] OCTET STRING OPTIONAL, - negHints [3] NegHints OPTIONAL - } + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + negHints [3] NegHints OPTIONAL +} NegTokenInit ::= SEQUENCE { - mechTypes [0] MechTypeList, - reqFlags [1] ContextFlags OPTIONAL, - mechToken [2] OCTET STRING OPTIONAL, - mechListMIC [3] OCTET STRING OPTIONAL - } - + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + mechListMIC [3] OCTET STRING OPTIONAL, + ... +} -- NB: negResult is not OPTIONAL in the new SPNEGO spec but -- Windows clients do not always send it @@ -47,7 +47,8 @@ NegTokenResp ::= SEQUENCE { request-mic (3) } OPTIONAL, supportedMech [1] MechType OPTIONAL, responseToken [2] OCTET STRING OPTIONAL, - mechListMIC [3] OCTET STRING OPTIONAL + mechListMIC [3] OCTET STRING OPTIONAL, + ... } NegotiationToken ::= CHOICE { -- cgit From 9e6b0c28712ee77ce878809c8576826a3ba08d95 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Mar 2008 10:17:42 +1100 Subject: Merge lorikeet-heimdal -r 787 into Samba4 tree. Andrew Bartlett (This used to be commit d88b530522d3cef67c24422bd5182fb875d87ee2) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 27 +++++---- source4/heimdal/lib/gssapi/spnego/compat.c | 3 +- source4/heimdal/lib/gssapi/spnego/context_stubs.c | 70 ++++++++++++++-------- source4/heimdal/lib/gssapi/spnego/external.c | 4 +- .../heimdal/lib/gssapi/spnego/init_sec_context.c | 11 +++- source4/heimdal/lib/gssapi/spnego/spnego-private.h | 9 --- 6 files changed, 72 insertions(+), 52 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 1afe26f1e3..df25b0f4bf 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 21461 2007-07-10 14:01:13Z lha $"); +RCSID("$Id: accept_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -540,7 +540,7 @@ acceptor_start gss_cred_id_t *delegated_cred_handle ) { - OM_uint32 ret, junk, minor; + OM_uint32 ret, junk; NegotiationToken nt; size_t nt_len; NegTokenInit *ni; @@ -609,7 +609,7 @@ acceptor_start /* * First we try the opportunistic token if we have support for it, * don't try to verify we have credential for the token, - * gss_accept_sec_context will (hopefully) tell us that. + * gss_accept_sec_context() will (hopefully) tell us that. * If that failes, */ @@ -633,12 +633,12 @@ acceptor_start mech_cred = GSS_C_NO_CREDENTIAL; if (ctx->mech_src_name != GSS_C_NO_NAME) - gss_release_name(&minor, &ctx->mech_src_name); + gss_release_name(&junk, &ctx->mech_src_name); if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) - _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + _gss_spnego_release_cred(&junk, &ctx->delegated_cred_id); - ret = gss_accept_sec_context(&minor, + ret = gss_accept_sec_context(minor_status, &ctx->negotiated_ctx_id, mech_cred, mech_input_token, @@ -656,7 +656,7 @@ acceptor_start ctx->open = 1; if (mech_delegated_cred && delegated_cred_handle) - ret = _gss_spnego_alloc_cred(minor_status, + ret = _gss_spnego_alloc_cred(&junk, mech_delegated_cred, delegated_cred_handle); else @@ -674,6 +674,8 @@ acceptor_start goto out; first_ok = 1; + } else { + gss_mg_collect_error(preferred_mech_type, ret, *minor_status); } } @@ -681,7 +683,9 @@ acceptor_start * If opportunistic token failed, lets try the other mechs. */ - if (!first_ok) { + if (!first_ok && ni->mechToken != NULL) { + + preferred_mech_type = GSS_C_NO_OID; /* Call glue layer to find first mech we support */ for (i = 1; i < ni->mechTypes.len; ++i) { @@ -695,7 +699,7 @@ acceptor_start if (preferred_mech_type == GSS_C_NO_OID) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_NegotiationToken(&nt); - return GSS_S_BAD_MECH; + return ret; } ctx->preferred_mech_type = preferred_mech_type; @@ -717,7 +721,7 @@ acceptor_start out: if (mech_output_token.value != NULL) - gss_release_buffer(&minor, &mech_output_token); + gss_release_buffer(&junk, &mech_output_token); if (mech_buf.value != NULL) { free(mech_buf.value); mech_buf.value = NULL; @@ -754,7 +758,7 @@ out: return ret; } - _gss_spnego_internal_delete_sec_context(&minor, context_handle, + _gss_spnego_internal_delete_sec_context(&junk, context_handle, GSS_C_NO_BUFFER); return ret; @@ -877,6 +881,7 @@ acceptor_continue } if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { free_NegotiationToken(&nt); + gss_mg_collect_error(ctx->negotiated_mech_type, ret, minor); send_reject (minor_status, output_token); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); return ret; diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index bc7da9410e..287f4f760e 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c 19415 2006-12-18 17:52:26Z lha $"); +RCSID("$Id: compat.c 21866 2007-08-08 11:31:29Z lha $"); /* * Apparently Microsoft got the OID wrong, and used @@ -129,6 +129,7 @@ OM_uint32 _gss_spnego_internal_delete_sec_context gss_release_oid(&minor, &ctx->preferred_mech_type); ctx->negotiated_mech_type = GSS_C_NO_OID; + gss_release_name(&minor, &ctx->target_name); gss_release_name(&minor, &ctx->mech_src_name); if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 3535c7bb35..0169017ee5 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c 21035 2007-06-09 15:32:47Z lha $"); +RCSID("$Id: context_stubs.c 22604 2008-02-21 21:12:48Z lha $"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) @@ -263,18 +263,6 @@ OM_uint32 _gss_spnego_unwrap qop_state); } -OM_uint32 _gss_spnego_display_status - (OM_uint32 * minor_status, - OM_uint32 status_value, - int status_type, - const gss_OID mech_type, - OM_uint32 * message_context, - gss_buffer_t status_string - ) -{ - return GSS_S_FAILURE; -} - OM_uint32 _gss_spnego_compare_name (OM_uint32 *minor_status, const gss_name_t name1, @@ -406,28 +394,58 @@ OM_uint32 _gss_spnego_inquire_context ( ) { gssspnego_ctx ctx; + OM_uint32 maj_stat, junk; + gss_name_t src_mn, targ_mn; *minor_status = 0; - if (context_handle == GSS_C_NO_CONTEXT) { + if (context_handle == GSS_C_NO_CONTEXT) return GSS_S_NO_CONTEXT; - } ctx = (gssspnego_ctx)context_handle; - if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) return GSS_S_NO_CONTEXT; - } - return gss_inquire_context(minor_status, - ctx->negotiated_ctx_id, - src_name, - targ_name, - lifetime_rec, - mech_type, - ctx_flags, - locally_initiated, - open_context); + maj_stat = gss_inquire_context(minor_status, + ctx->negotiated_ctx_id, + &src_mn, + &targ_mn, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open_context); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + if (src_name) { + spnego_name name = calloc(1, sizeof(*name)); + if (name == NULL) + goto enomem; + name->mech = src_mn; + *src_name = (gss_name_t)name; + } else + gss_release_name(&junk, &src_mn); + + if (targ_name) { + spnego_name name = calloc(1, sizeof(*name)); + if (name == NULL) { + gss_release_name(minor_status, src_name); + goto enomem; + } + name->mech = targ_mn; + *targ_name = (gss_name_t)name; + } else + gss_release_name(&junk, &targ_mn); + + return GSS_S_COMPLETE; + +enomem: + gss_release_name(&junk, &targ_mn); + gss_release_name(&junk, &src_mn); + *minor_status = ENOMEM; + return GSS_S_FAILURE; } OM_uint32 _gss_spnego_wrap_size_limit ( diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index fbc231f3ae..6c9a03a3b0 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" #include -RCSID("$Id: external.c 18336 2006-10-07 22:27:13Z lha $"); +RCSID("$Id: external.c 22600 2008-02-21 12:46:24Z lha $"); /* * RFC2478, SPNEGO: @@ -57,7 +57,7 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_verify_mic, _gss_spnego_wrap, _gss_spnego_unwrap, - _gss_spnego_display_status, + NULL, NULL, _gss_spnego_compare_name, _gss_spnego_display_name, diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c index 7c74981e66..bee4895898 100644 --- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: init_sec_context.c 19411 2006-12-18 15:42:03Z lha $"); +RCSID("$Id: init_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); /* * Is target_name an sane target for `mech´. @@ -59,8 +59,10 @@ initiator_approved(gss_name_t target_name, gss_OID mech) &out, NULL, NULL); - if (GSS_ERROR(maj_stat)) + if (GSS_ERROR(maj_stat)) { + gss_mg_collect_error(mech, maj_stat, min_stat); return GSS_S_BAD_MECH; + } gss_release_buffer(&min_stat, &out); gss_delete_sec_context(&min_stat, &ctx, NULL); @@ -268,6 +270,7 @@ spnego_initial if (GSS_ERROR(sub)) { free_NegTokenInit(&ni); *minor_status = minor; + gss_mg_collect_error(ctx->preferred_mech_type, sub, minor); _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } @@ -480,7 +483,8 @@ spnego_reply return GSS_S_BAD_MECH; } - if (resp.responseToken != NULL || + /* if a token (of non zero length), or no context, pass to underlaying mech */ + if ((resp.responseToken != NULL && resp.responseToken->length) || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { gss_buffer_desc mech_input_token; @@ -515,6 +519,7 @@ spnego_reply if (GSS_ERROR(ret)) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_NegTokenResp(&resp); + gss_mg_collect_error(&mech, ret, minor); *minor_status = minor; return ret; } diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h index d80db0018a..69f4d8423d 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego-private.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -90,15 +90,6 @@ _gss_spnego_display_name ( gss_buffer_t /*output_name_buffer*/, gss_OID * output_name_type ); -OM_uint32 -_gss_spnego_display_status ( - OM_uint32 * /*minor_status*/, - OM_uint32 /*status_value*/, - int /*status_type*/, - const gss_OID /*mech_type*/, - OM_uint32 * /*message_context*/, - gss_buffer_t status_string ); - OM_uint32 _gss_spnego_duplicate_name ( OM_uint32 * /*minor_status*/, -- cgit From a925f039ee382df0f3be434108416bab0d17e8c0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 Aug 2008 07:08:51 +0200 Subject: heimdal: update to lorikeet-heimdal rev 801 metze (This used to be commit d6c54a66fb23c784ef221a3c1cf766b72bdb5a0b) --- .../heimdal/lib/gssapi/spnego/accept_sec_context.c | 98 +++++++++------------- source4/heimdal/lib/gssapi/spnego/compat.c | 5 +- source4/heimdal/lib/gssapi/spnego/context_stubs.c | 32 ++++++- source4/heimdal/lib/gssapi/spnego/cred_stubs.c | 22 ++++- source4/heimdal/lib/gssapi/spnego/external.c | 13 ++- source4/heimdal/lib/gssapi/spnego/spnego-private.h | 16 ++++ source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 3 +- 7 files changed, 119 insertions(+), 70 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index df25b0f4bf..6b618092fe 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); +RCSID("$Id: accept_sec_context.c 23158 2008-05-02 09:45:28Z lha $"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -376,6 +376,9 @@ select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, char mechbuf[64]; size_t mech_len; gss_OID_desc oid; + gss_OID oidp; + gss_OID_set mechs; + int i; OM_uint32 ret, junk; ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, @@ -396,27 +399,29 @@ select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, *minor_status = 0; /* Translate broken MS Kebreros OID */ - if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) { - gssapi_mech_interface mech; + if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) + oidp = &_gss_spnego_krb5_mechanism_oid_desc; + else + oidp = &oid; - mech = __gss_get_mechanism(&_gss_spnego_krb5_mechanism_oid_desc); - if (mech == NULL) - return GSS_S_BAD_MECH; - ret = gss_duplicate_oid(minor_status, - &_gss_spnego_mskrb_mechanism_oid_desc, - mech_p); - } else { - gssapi_mech_interface mech; + ret = gss_indicate_mechs(&junk, &mechs); + if (ret) + return (ret); - mech = __gss_get_mechanism(&oid); - if (mech == NULL) - return GSS_S_BAD_MECH; + for (i = 0; i < mechs->count; i++) + if (gss_oid_equal(&mechs->elements[i], oidp)) + break; - ret = gss_duplicate_oid(minor_status, - &mech->gm_mech_oid, - mech_p); + if (i == mechs->count) { + gss_release_oid_set(&junk, &mechs); + return GSS_S_BAD_MECH; } + gss_release_oid_set(&junk, &mechs); + + ret = gss_duplicate_oid(minor_status, + &oid, /* possibly this should be oidp */ + mech_p); if (verify_p) { gss_name_t name = GSS_C_NO_NAME; @@ -635,9 +640,6 @@ acceptor_start if (ctx->mech_src_name != GSS_C_NO_NAME) gss_release_name(&junk, &ctx->mech_src_name); - if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) - _gss_spnego_release_cred(&junk, &ctx->delegated_cred_id); - ret = gss_accept_sec_context(minor_status, &ctx->negotiated_ctx_id, mech_cred, @@ -649,19 +651,20 @@ acceptor_start &ctx->mech_flags, &ctx->mech_time_rec, &mech_delegated_cred); + + if (mech_delegated_cred && delegated_cred_handle) { + _gss_spnego_alloc_cred(&junk, + mech_delegated_cred, + delegated_cred_handle); + } else if (mech_delegated_cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&junk, &mech_delegated_cred); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { ctx->preferred_mech_type = preferred_mech_type; ctx->negotiated_mech_type = preferred_mech_type; if (ret == GSS_S_COMPLETE) ctx->open = 1; - if (mech_delegated_cred && delegated_cred_handle) - ret = _gss_spnego_alloc_cred(&junk, - mech_delegated_cred, - delegated_cred_handle); - else - gss_release_cred(&junk, &mech_delegated_cred); - ret = acceptor_complete(minor_status, ctx, &get_mic, @@ -740,10 +743,6 @@ out: *src_name = (gss_name_t)name; } } - if (delegated_cred_handle != NULL) { - *delegated_cred_handle = ctx->delegated_cred_id; - ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; - } } if (mech_type != NULL) @@ -780,7 +779,7 @@ acceptor_continue gss_cred_id_t *delegated_cred_handle ) { - OM_uint32 ret, ret2, minor; + OM_uint32 ret, ret2, minor, junk; NegotiationToken nt; size_t nt_len; NegTokenResp *na; @@ -836,27 +835,16 @@ acceptor_continue if (mech_input_token != GSS_C_NO_BUFFER) { gss_cred_id_t mech_cred; - gss_cred_id_t mech_delegated_cred; - gss_cred_id_t *mech_delegated_cred_p; + gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL; if (acceptor_cred != NULL) mech_cred = acceptor_cred->negotiated_cred_id; else mech_cred = GSS_C_NO_CREDENTIAL; - if (delegated_cred_handle != NULL) { - mech_delegated_cred = GSS_C_NO_CREDENTIAL; - mech_delegated_cred_p = &mech_delegated_cred; - } else { - mech_delegated_cred_p = NULL; - } - if (ctx->mech_src_name != GSS_C_NO_NAME) gss_release_name(&minor, &ctx->mech_src_name); - if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) - _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); - ret = gss_accept_sec_context(&minor, &ctx->negotiated_ctx_id, mech_cred, @@ -867,16 +855,16 @@ acceptor_continue &obuf, &ctx->mech_flags, &ctx->mech_time_rec, - mech_delegated_cred_p); + &mech_delegated_cred); + + if (mech_delegated_cred && delegated_cred_handle) { + _gss_spnego_alloc_cred(&junk, + mech_delegated_cred, + delegated_cred_handle); + } else if (mech_delegated_cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&junk, &mech_delegated_cred); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { - if (mech_delegated_cred_p != NULL && - mech_delegated_cred != GSS_C_NO_CREDENTIAL) { - ret2 = _gss_spnego_alloc_cred(minor_status, - mech_delegated_cred, - &ctx->delegated_cred_id); - if (ret2 != GSS_S_COMPLETE) - ret = ret2; - } mech_output_token = &obuf; } if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { @@ -958,10 +946,6 @@ acceptor_continue *src_name = (gss_name_t)name; } } - if (delegated_cred_handle != NULL) { - *delegated_cred_handle = ctx->delegated_cred_id; - ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; - } } if (mech_type != NULL) diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index 287f4f760e..36de854784 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c 21866 2007-08-08 11:31:29Z lha $"); +RCSID("$Id: compat.c 22688 2008-03-16 11:33:58Z lha $"); /* * Apparently Microsoft got the OID wrong, and used @@ -76,7 +76,6 @@ OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status, ctx->mech_flags = 0; ctx->mech_time_rec = 0; ctx->mech_src_name = GSS_C_NO_NAME; - ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; ctx->open = 0; ctx->local = 0; @@ -124,8 +123,6 @@ OM_uint32 _gss_spnego_internal_delete_sec_context if (ctx->initiator_mech_types.val != NULL) free_MechTypeList(&ctx->initiator_mech_types); - _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); - gss_release_oid(&minor, &ctx->preferred_mech_type); ctx->negotiated_mech_type = GSS_C_NO_OID; diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 0169017ee5..6f1c3eb4b6 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c 22604 2008-02-21 21:12:48Z lha $"); +RCSID("$Id: context_stubs.c 22688 2008-03-16 11:33:58Z lha $"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) @@ -907,7 +907,7 @@ OM_uint32 _gss_spnego_set_sec_context_option return GSS_S_NO_CONTEXT; } - ctx = (gssspnego_ctx)context_handle; + ctx = (gssspnego_ctx)*context_handle; if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { return GSS_S_NO_CONTEXT; @@ -919,3 +919,31 @@ OM_uint32 _gss_spnego_set_sec_context_option value); } + +OM_uint32 +_gss_spnego_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return gss_pseudo_random(minor_status, + ctx->negotiated_ctx_id, + prf_key, + prf_in, + desired_output_len, + prf_out); +} diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c index 2362e99019..d87d7d618e 100644 --- a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $"); +RCSID("$Id: cred_stubs.c 22688 2008-03-16 11:33:58Z lha $"); OM_uint32 _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) @@ -334,3 +334,23 @@ OM_uint32 _gss_spnego_inquire_cred_by_oid return ret; } +OM_uint32 +_gss_spnego_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value) +{ + gssspnego_cred cred; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + cred = (gssspnego_cred)*cred_handle; + return gss_set_cred_option(minor_status, + &cred->negotiated_cred_id, + object, + value); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index 6c9a03a3b0..317d358707 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" #include -RCSID("$Id: external.c 22600 2008-02-21 12:46:24Z lha $"); +RCSID("$Id: external.c 22688 2008-03-16 11:33:58Z lha $"); /* * RFC2478, SPNEGO: @@ -57,8 +57,8 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_verify_mic, _gss_spnego_wrap, _gss_spnego_unwrap, - NULL, - NULL, + NULL, /* gm_display_status */ + NULL, /* gm_indicate_mechs */ _gss_spnego_compare_name, _gss_spnego_display_name, _gss_spnego_import_name, @@ -74,7 +74,12 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_inquire_names_for_mech, _gss_spnego_inquire_mechs_for_name, _gss_spnego_canonicalize_name, - _gss_spnego_duplicate_name + _gss_spnego_duplicate_name, + _gss_spnego_inquire_sec_context_by_oid, + _gss_spnego_inquire_cred_by_oid, + _gss_spnego_set_sec_context_option, + _gss_spnego_set_cred_option, + _gss_spnego_pseudo_random }; gssapi_mech_interface diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h index 69f4d8423d..3b20d737b7 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego-private.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -224,6 +224,15 @@ _gss_spnego_process_context_token ( const gss_ctx_id_t /*context_handle*/, const gss_buffer_t token_buffer ); +OM_uint32 +_gss_spnego_pseudo_random ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*prf_key*/, + const gss_buffer_t /*prf_in*/, + ssize_t /*desired_output_len*/, + gss_buffer_t /*prf_out*/); + OM_uint32 _gss_spnego_release_cred ( OM_uint32 */*minor_status*/, @@ -250,6 +259,13 @@ _gss_spnego_seal ( int * /*conf_state*/, gss_buffer_t output_message_buffer ); +OM_uint32 +_gss_spnego_set_cred_option ( + OM_uint32 */*minor_status*/, + gss_cred_id_t */*cred_handle*/, + const gss_OID /*object*/, + const gss_buffer_t /*value*/); + OM_uint32 _gss_spnego_set_sec_context_option ( OM_uint32 * /*minor_status*/, diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h index 44b24688e1..6eb808efbc 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: spnego_locl.h 19411 2006-12-18 15:42:03Z lha $ */ +/* $Id: spnego_locl.h 23161 2008-05-05 09:56:20Z lha $ */ #ifndef SPNEGO_LOCL_H #define SPNEGO_LOCL_H @@ -86,7 +86,6 @@ typedef struct { OM_uint32 mech_flags; OM_uint32 mech_time_rec; gss_name_t mech_src_name; - gss_cred_id_t delegated_cred_id; unsigned int open : 1; unsigned int local : 1; unsigned int require_mic : 1; -- cgit From 9080b5d979e2af4de1022513bdaa303306b1ca9b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 11:20:54 +0200 Subject: heimdal_build: autogenerate the heimdal private/proto headers Now it's possible to just use a plain heimdal tree in source/heimdal/ without any pregenerated files. metze (This used to be commit da333ca7113f78eeacab4f93b401f075114c7d88) --- source4/heimdal/lib/gssapi/spnego/spnego-private.h | 337 --------------------- 1 file changed, 337 deletions(-) delete mode 100644 source4/heimdal/lib/gssapi/spnego/spnego-private.h (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h deleted file mode 100644 index 3b20d737b7..0000000000 --- a/source4/heimdal/lib/gssapi/spnego/spnego-private.h +++ /dev/null @@ -1,337 +0,0 @@ -/* This is a generated file */ -#ifndef __spnego_private_h__ -#define __spnego_private_h__ - -#include - -gssapi_mech_interface -__gss_spnego_initialize (void); - -OM_uint32 -_gss_spnego_accept_sec_context ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - const gss_cred_id_t /*acceptor_cred_handle*/, - const gss_buffer_t /*input_token_buffer*/, - const gss_channel_bindings_t /*input_chan_bindings*/, - gss_name_t * /*src_name*/, - gss_OID * /*mech_type*/, - gss_buffer_t /*output_token*/, - OM_uint32 * /*ret_flags*/, - OM_uint32 * /*time_rec*/, - gss_cred_id_t *delegated_cred_handle ); - -OM_uint32 -_gss_spnego_acquire_cred ( - OM_uint32 */*minor_status*/, - const gss_name_t /*desired_name*/, - OM_uint32 /*time_req*/, - const gss_OID_set /*desired_mechs*/, - gss_cred_usage_t /*cred_usage*/, - gss_cred_id_t * /*output_cred_handle*/, - gss_OID_set * /*actual_mechs*/, - OM_uint32 * time_rec ); - -OM_uint32 -_gss_spnego_add_cred ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*input_cred_handle*/, - const gss_name_t /*desired_name*/, - const gss_OID /*desired_mech*/, - gss_cred_usage_t /*cred_usage*/, - OM_uint32 /*initiator_time_req*/, - OM_uint32 /*acceptor_time_req*/, - gss_cred_id_t * /*output_cred_handle*/, - gss_OID_set * /*actual_mechs*/, - OM_uint32 * /*initiator_time_rec*/, - OM_uint32 * acceptor_time_rec ); - -OM_uint32 -_gss_spnego_alloc_cred ( - OM_uint32 */*minor_status*/, - gss_cred_id_t /*mech_cred_handle*/, - gss_cred_id_t */*cred_handle*/); - -OM_uint32 -_gss_spnego_alloc_sec_context ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t */*context_handle*/); - -OM_uint32 -_gss_spnego_canonicalize_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - const gss_OID /*mech_type*/, - gss_name_t * output_name ); - -OM_uint32 -_gss_spnego_compare_name ( - OM_uint32 */*minor_status*/, - const gss_name_t /*name1*/, - const gss_name_t /*name2*/, - int * name_equal ); - -OM_uint32 -_gss_spnego_context_time ( - OM_uint32 */*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - OM_uint32 *time_rec ); - -OM_uint32 -_gss_spnego_delete_sec_context ( - OM_uint32 */*minor_status*/, - gss_ctx_id_t */*context_handle*/, - gss_buffer_t output_token ); - -OM_uint32 -_gss_spnego_display_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_buffer_t /*output_name_buffer*/, - gss_OID * output_name_type ); - -OM_uint32 -_gss_spnego_duplicate_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*src_name*/, - gss_name_t * dest_name ); - -OM_uint32 -_gss_spnego_export_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_buffer_t exported_name ); - -OM_uint32 -_gss_spnego_export_sec_context ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - gss_buffer_t interprocess_token ); - -OM_uint32 -_gss_spnego_get_mic ( - OM_uint32 */*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - gss_qop_t /*qop_req*/, - const gss_buffer_t /*message_buffer*/, - gss_buffer_t message_token ); - -OM_uint32 -_gss_spnego_import_name ( - OM_uint32 * /*minor_status*/, - const gss_buffer_t /*name_buffer*/, - const gss_OID /*name_type*/, - gss_name_t * output_name ); - -OM_uint32 -_gss_spnego_import_sec_context ( - OM_uint32 * /*minor_status*/, - const gss_buffer_t /*interprocess_token*/, - gss_ctx_id_t *context_handle ); - -OM_uint32 -_gss_spnego_indicate_mechtypelist ( - OM_uint32 */*minor_status*/, - gss_name_t /*target_name*/, - OM_uint32 (*/*func*/)(gss_name_t, gss_OID), - int /*includeMSCompatOID*/, - const gssspnego_cred /*cred_handle*/, - MechTypeList */*mechtypelist*/, - gss_OID */*preferred_mech*/); - -OM_uint32 -_gss_spnego_init_sec_context ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*initiator_cred_handle*/, - gss_ctx_id_t * /*context_handle*/, - const gss_name_t /*target_name*/, - const gss_OID /*mech_type*/, - OM_uint32 /*req_flags*/, - OM_uint32 /*time_req*/, - const gss_channel_bindings_t /*input_chan_bindings*/, - const gss_buffer_t /*input_token*/, - gss_OID * /*actual_mech_type*/, - gss_buffer_t /*output_token*/, - OM_uint32 * /*ret_flags*/, - OM_uint32 * time_rec ); - -OM_uint32 -_gss_spnego_inquire_context ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - gss_name_t * /*src_name*/, - gss_name_t * /*targ_name*/, - OM_uint32 * /*lifetime_rec*/, - gss_OID * /*mech_type*/, - OM_uint32 * /*ctx_flags*/, - int * /*locally_initiated*/, - int * open_context ); - -OM_uint32 -_gss_spnego_inquire_cred ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*cred_handle*/, - gss_name_t * /*name*/, - OM_uint32 * /*lifetime*/, - gss_cred_usage_t * /*cred_usage*/, - gss_OID_set * mechanisms ); - -OM_uint32 -_gss_spnego_inquire_cred_by_mech ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*cred_handle*/, - const gss_OID /*mech_type*/, - gss_name_t * /*name*/, - OM_uint32 * /*initiator_lifetime*/, - OM_uint32 * /*acceptor_lifetime*/, - gss_cred_usage_t * cred_usage ); - -OM_uint32 -_gss_spnego_inquire_cred_by_oid ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*cred_handle*/, - const gss_OID /*desired_object*/, - gss_buffer_set_t */*data_set*/); - -OM_uint32 -_gss_spnego_inquire_mechs_for_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_OID_set * mech_types ); - -OM_uint32 -_gss_spnego_inquire_names_for_mech ( - OM_uint32 * /*minor_status*/, - const gss_OID /*mechanism*/, - gss_OID_set * name_types ); - -OM_uint32 -_gss_spnego_inquire_sec_context_by_oid ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_OID /*desired_object*/, - gss_buffer_set_t */*data_set*/); - -OM_uint32 -_gss_spnego_internal_delete_sec_context ( - OM_uint32 */*minor_status*/, - gss_ctx_id_t */*context_handle*/, - gss_buffer_t output_token ); - -OM_uint32 -_gss_spnego_process_context_token ( - OM_uint32 */*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t token_buffer ); - -OM_uint32 -_gss_spnego_pseudo_random ( - OM_uint32 */*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*prf_key*/, - const gss_buffer_t /*prf_in*/, - ssize_t /*desired_output_len*/, - gss_buffer_t /*prf_out*/); - -OM_uint32 -_gss_spnego_release_cred ( - OM_uint32 */*minor_status*/, - gss_cred_id_t */*cred_handle*/); - -OM_uint32 -_gss_spnego_release_name ( - OM_uint32 * /*minor_status*/, - gss_name_t * input_name ); - -OM_uint32 -_gss_spnego_require_mechlist_mic ( - OM_uint32 */*minor_status*/, - gssspnego_ctx /*ctx*/, - int */*require_mic*/); - -OM_uint32 -_gss_spnego_seal ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - int /*qop_req*/, - gss_buffer_t /*input_message_buffer*/, - int * /*conf_state*/, - gss_buffer_t output_message_buffer ); - -OM_uint32 -_gss_spnego_set_cred_option ( - OM_uint32 */*minor_status*/, - gss_cred_id_t */*cred_handle*/, - const gss_OID /*object*/, - const gss_buffer_t /*value*/); - -OM_uint32 -_gss_spnego_set_sec_context_option ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - const gss_OID /*desired_object*/, - const gss_buffer_t /*value*/); - -OM_uint32 -_gss_spnego_sign ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*qop_req*/, - gss_buffer_t /*message_buffer*/, - gss_buffer_t message_token ); - -OM_uint32 -_gss_spnego_unseal ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - gss_buffer_t /*input_message_buffer*/, - gss_buffer_t /*output_message_buffer*/, - int * /*conf_state*/, - int * qop_state ); - -OM_uint32 -_gss_spnego_unwrap ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t /*input_message_buffer*/, - gss_buffer_t /*output_message_buffer*/, - int * /*conf_state*/, - gss_qop_t * qop_state ); - -OM_uint32 -_gss_spnego_verify ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - gss_buffer_t /*message_buffer*/, - gss_buffer_t /*token_buffer*/, - int * qop_state ); - -OM_uint32 -_gss_spnego_verify_mic ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t /*message_buffer*/, - const gss_buffer_t /*token_buffer*/, - gss_qop_t * qop_state ); - -OM_uint32 -_gss_spnego_wrap ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - gss_qop_t /*qop_req*/, - const gss_buffer_t /*input_message_buffer*/, - int * /*conf_state*/, - gss_buffer_t output_message_buffer ); - -OM_uint32 -_gss_spnego_wrap_size_limit ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - gss_qop_t /*qop_req*/, - OM_uint32 /*req_output_size*/, - OM_uint32 * max_input_size ); - -#endif /* __spnego_private_h__ */ -- cgit From 243321b4bbe273cf3a9105ca132caa2b53e2f263 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 19:35:52 +0200 Subject: heimdal: import heimdal's trunk svn rev 23697 + lorikeet-heimdal patches This is based on f56a3b1846c7d462542f2e9527f4d0ed8a34748d in my heimdal-wip repo. metze (This used to be commit 467a1f2163a63cdf1a4c83a69473db50e8794f53) --- source4/heimdal/lib/gssapi/spnego/accept_sec_context.c | 4 ++-- source4/heimdal/lib/gssapi/spnego/compat.c | 2 +- source4/heimdal/lib/gssapi/spnego/context_stubs.c | 2 +- source4/heimdal/lib/gssapi/spnego/cred_stubs.c | 2 +- source4/heimdal/lib/gssapi/spnego/external.c | 2 +- source4/heimdal/lib/gssapi/spnego/init_sec_context.c | 2 +- source4/heimdal/lib/gssapi/spnego/spnego.asn1 | 2 +- source4/heimdal/lib/gssapi/spnego/spnego_locl.h | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/heimdal/lib/gssapi/spnego') diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 6b618092fe..2afeaf080e 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: accept_sec_context.c 23158 2008-05-02 09:45:28Z lha $"); +RCSID("$Id$"); static OM_uint32 send_reject (OM_uint32 *minor_status, @@ -524,7 +524,7 @@ acceptor_complete(OM_uint32 * minor_status, free(buf.value); } else - *get_mic = verify_mic = 0; + *get_mic = 0; return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c index 36de854784..67d9b202a7 100644 --- a/source4/heimdal/lib/gssapi/spnego/compat.c +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: compat.c 22688 2008-03-16 11:33:58Z lha $"); +RCSID("$Id$"); /* * Apparently Microsoft got the OID wrong, and used diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c index 6f1c3eb4b6..60c53058b8 100644 --- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: context_stubs.c 22688 2008-03-16 11:33:58Z lha $"); +RCSID("$Id$"); static OM_uint32 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c index d87d7d618e..836b63f437 100644 --- a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -32,7 +32,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: cred_stubs.c 22688 2008-03-16 11:33:58Z lha $"); +RCSID("$Id$"); OM_uint32 _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index 317d358707..d5718c3fd3 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" #include -RCSID("$Id: external.c 22688 2008-03-16 11:33:58Z lha $"); +RCSID("$Id$"); /* * RFC2478, SPNEGO: diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c index bee4895898..f032757fdd 100644 --- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -33,7 +33,7 @@ #include "spnego/spnego_locl.h" -RCSID("$Id: init_sec_context.c 22600 2008-02-21 12:46:24Z lha $"); +RCSID("$Id$"); /* * Is target_name an sane target for `mech´. diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 index 058f10ba3a..048e86bb43 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -1,4 +1,4 @@ --- $Id: spnego.asn1 21403 2007-07-04 08:13:12Z lha $ +-- $Id$ SPNEGO DEFINITIONS ::= BEGIN diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h index 6eb808efbc..8344e750ae 100644 --- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: spnego_locl.h 23161 2008-05-05 09:56:20Z lha $ */ +/* $Id$ */ #ifndef SPNEGO_LOCL_H #define SPNEGO_LOCL_H -- cgit