summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/gssapi/spnego
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-01-10 01:57:32 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:37:20 -0500
commitf7242f643763ccb6e10801af4ce53d0873e2d3e1 (patch)
treecd06665f49d12795e23699e6666d85da1f64d7bd /source4/heimdal/lib/gssapi/spnego
parent08976cb3d2adfe5ea90ed53e6aa6fa8161649f7a (diff)
downloadsamba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.tar.gz
samba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.tar.bz2
samba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.zip
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)
Diffstat (limited to 'source4/heimdal/lib/gssapi/spnego')
-rw-r--r--source4/heimdal/lib/gssapi/spnego/accept_sec_context.c978
-rw-r--r--source4/heimdal/lib/gssapi/spnego/compat.c154
-rw-r--r--source4/heimdal/lib/gssapi/spnego/context_stubs.c88
-rw-r--r--source4/heimdal/lib/gssapi/spnego/init_sec_context.c219
-rw-r--r--source4/heimdal/lib/gssapi/spnego/spnego-private.h25
-rw-r--r--source4/heimdal/lib/gssapi/spnego/spnego.asn117
-rw-r--r--source4/heimdal/lib/gssapi/spnego/spnego_locl.h27
7 files changed, 940 insertions, 568 deletions
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*/,
@@ -112,13 +106,6 @@ _gss_spnego_duplicate_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*/,
@@ -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*/,
@@ -271,12 +260,6 @@ _gss_spnego_seal (
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*/,
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 <gssapi_mech.h>
#include "spnego_asn1.h"
+#include "mech/utils.h"
#include <der.h>
#include <roken.h>
@@ -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 <spnego/spnego-private.h>
#endif /* SPNEGO_LOCL_H */