* SPNEGO wrapper for Kerberos5 GSS-API
* kouril@ics.muni.cz, 2003
*/
-#include <stdlib.h>
-#include <errno.h>
-#include <gssapi.h>
-#include <spnego_asn1.h>
+#include "spnegokrb5_locl.h"
#define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
#define OID_cmp(o1, o2) \
- (((o1).length == (o2).length) && \
- (memcmp((o1).components, (o2).components,(int) (o1).length) == 0))
+ (((o1)->length == (o2)->length) && \
+ (memcmp((o1)->components, (o2)->components,(int) (o1)->length) == 0))
static int
-create_reply(OM_uint32 major_status, oid *mech, gss_buffer_t mech_token,
+create_reply(OM_uint32 major_status, gss_OID mech, gss_buffer_t mech_token,
gss_buffer_t output_token)
{
NegTokenTarg targ_token;
ret = ENOMEM;
goto end;
}
- copy_MechType(mech, targ_token.supportedMech);
+ copy_MechType((oid*)mech, targ_token.supportedMech);
if (mech_token->length > 0) {
ALLOC(targ_token.responseToken);
gss_buffer_desc krb5_input_token = GSS_C_EMPTY_BUFFER;
size_t len;
int ret;
- unsigned krb5_oid_array[] =
- {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02};
- oid krb5_oid;
-
- krb5_oid.length = sizeof(krb5_oid_array);
- krb5_oid.components = krb5_oid_array;
memset(&init_token, 0, sizeof(init_token));
}
if (init_token.mechTypes == NULL || init_token.mechTypes->len == 0 ||
- OID_cmp(init_token.mechTypes->val[0], krb5_oid)) {
+ OID_cmp(&init_token.mechTypes->val[0], (oid *)GSS_KRB5_MECH)) {
*minor_status = EINVAL;
ret = GSS_S_BAD_MECH;
goto end;
goto end;
}
- ret = create_reply(major_status, &krb5_oid, &krb5_output_token, output_token);
+ ret = create_reply(major_status, GSS_KRB5_MECH, &krb5_output_token, output_token);
if (ret) {
*minor_status = ret;
ret = GSS_S_FAILURE;
--- /dev/null
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 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 "gssapi_locl.h"
+
+RCSID("$Id$");
+
+OM_uint32
+gssapi_krb5_verify_header(u_char **str,
+ size_t total_len,
+ char *type)
+{
+ size_t len, len_len, mech_len, foo;
+ int e;
+ u_char *p = *str;
+
+ if (total_len < 1)
+ return GSS_S_DEFECTIVE_TOKEN;
+ if (*p++ != 0x60)
+ return GSS_S_DEFECTIVE_TOKEN;
+ e = der_get_length (p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return GSS_S_DEFECTIVE_TOKEN;
+ p += len_len;
+ if (*p++ != 0x06)
+ return GSS_S_DEFECTIVE_TOKEN;
+ e = der_get_length (p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return GSS_S_DEFECTIVE_TOKEN;
+ p += foo;
+ if (mech_len != GSS_KRB5_MECHANISM->length)
+ return GSS_S_BAD_MECH;
+ if (memcmp(p,
+ GSS_KRB5_MECHANISM->elements,
+ GSS_KRB5_MECHANISM->length) != 0)
+ return GSS_S_BAD_MECH;
+ p += mech_len;
+ if (memcmp (p, type, 2) != 0)
+ return GSS_S_DEFECTIVE_TOKEN;
+ p += 2;
+ *str = p;
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `out_data.
+ * Does not copy data, so just free `in_token'.
+ */
+
+OM_uint32
+gssapi_krb5_decapsulate(
+ OM_uint32 *minor_status,
+ gss_buffer_t input_token_buffer,
+ krb5_data *out_data,
+ char *type
+)
+{
+ u_char *p;
+ OM_uint32 ret;
+
+ p = input_token_buffer->value;
+ ret = gssapi_krb5_verify_header(&p,
+ input_token_buffer->length,
+ type);
+ if (ret) {
+ *minor_status = 0;
+ return ret;
+ }
+
+ out_data->length = input_token_buffer->length -
+ (p - (u_char *)input_token_buffer->value);
+ out_data->data = p;
+ return GSS_S_COMPLETE;
+}
--- /dev/null
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 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 "spnegokrb5_locl.h"
+
+void
+gssapi_spnego_encap_length (size_t data_len,
+ size_t *len,
+ size_t *total_len)
+{
+ size_t len_len;
+
+#if 0
+ *len = 1 + 1 + GSS_SPNEGO_MECH->length + 2 + data_len;
+#else
+ *len = 1 + 1 + GSS_SPNEGO_MECH->length + data_len;
+#endif
+
+ len_len = length_len(*len);
+
+ *total_len = 1 + len_len + *len;
+}
+
+u_char *
+gssapi_spnego_make_header (u_char *p,
+ size_t len,
+ u_char *type)
+{
+ int e;
+ size_t len_len, foo;
+
+ *p++ = 0x60;
+ len_len = length_len(len);
+ e = der_put_length (p + len_len - 1, len_len, len, &foo);
+ if(e || foo != len_len)
+ abort ();
+ p += len_len;
+ *p++ = 0x06;
+ *p++ = GSS_SPNEGO_MECH->length;
+ memcpy (p, GSS_SPNEGO_MECH->elements, GSS_SPNEGO_MECH->length);
+ p += GSS_SPNEGO_MECH->length;
+#if 0
+ memcpy (p, type, 2);
+ p += 2;
+#endif
+ return p;
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
+ */
+
+OM_uint32
+gssapi_spnego_encapsulate(
+ OM_uint32 *minor_status,
+ unsigned char *buf,
+ size_t buf_size,
+ gss_buffer_t output_token,
+ u_char *type
+)
+{
+ size_t len, outer_len;
+ u_char *p;
+
+ gssapi_spnego_encap_length (buf_size, &len, &outer_len);
+
+ output_token->length = outer_len;
+ output_token->value = malloc (outer_len);
+ if (output_token->value == NULL) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ p = gssapi_spnego_make_header (output_token->value, len, type);
+ memcpy (p, buf, buf_size);
+ return GSS_S_COMPLETE;
+}
--- /dev/null
+#include "spnegokrb5_locl.h"
+
+static gss_OID_desc gss_krb5_mech_oid_desc =
+ {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
+
+gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
+
+static gss_OID_desc gss_spnego_mech_oid_desc =
+ {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+
+gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
* SPNEGO wrapper for Kerberos5 GSS-API
* kouril@ics.muni.cz, 2003
*/
-#include <stdlib.h>
-#include <errno.h>
-#include <gssapi.h>
-#include <spnego_asn1.h>
+#include "spnegokrb5_locl.h"
#define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
static int
-add_mech(MechTypeList *mech_list, oid *mech)
+add_mech(MechTypeList *mech_list, gss_OID mech)
{
MechType *tmp;
+ int ret;
tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
if (tmp == NULL)
return ENOMEM;
mech_list->val = tmp;
- copy_MechType(mech, mech_list->val + mech_list->len);
+
+ ret = der_get_oid(mech->elements, mech->length,
+ &mech_list->val[mech_list->len], NULL);
+ if (ret)
+ return ret;
+
mech_list->len++;
return 0;
}
size_t buf_size;
size_t len;
int ret;
- unsigned krb5_oid_array[] =
- {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02};
- oid krb5_oid;
memset(&token_init, 0, sizeof(token_init));
- krb5_oid.length = sizeof(krb5_oid_array);
- krb5_oid.components = krb5_oid_array;
-
ALLOC(token_init.mechTypes);
if (token_init.mechTypes == NULL) {
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}
- ret = add_mech(token_init.mechTypes, &krb5_oid);
+ ret = add_mech(token_init.mechTypes, GSS_KRB5_MECH);
if (ret) {
*minor_status = ret;
ret = GSS_S_FAILURE;
goto end;
}
+#if 0
ALLOC(token_init.reqFlags);
if (token_init.reqFlags == NULL) {
*minor_status = ENOMEM;
goto end;
}
set_context_flags(req_flags, token_init.reqFlags);
+#endif
major_status = gss_init_sec_context(minor_status,
initiator_cred_handle,
context_handle,
target_name,
- (gss_OID) &krb5_oid,
+ GSS_KRB5_MECH,
req_flags,
time_req,
input_chan_bindings,
/* The MS implementation of SPNEGO seems to not like the mechListMIC field,
* so we omit it (it's optional anyway) */
- ASN1_MALLOC_ENCODE(NegTokenInit, buf, buf_size, &token_init, &len, ret);
- if (ret || buf_size != len) {
- *minor_status = EINVAL; /* XXX */
- ret = GSS_S_FAILURE;
- goto end;
- }
+ buf_size = 1024;
+ buf = malloc(buf_size);
+
+ do {
+ ret = encode_NegTokenInit(buf + buf_size -1,
+ buf_size,
+ &token_init, &len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - len - 1,
+ buf_size - len,
+ len,
+ CONTEXT,
+ CONS,
+ 0,
+ &tmp);
+ if (ret == 0)
+ 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;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ ret = gssapi_spnego_encapsulate(minor_status,
+ buf + buf_size - len, len,
+ output_token, "\x01\x00");
- output_token->value = buf;
- output_token->length = buf_size;
- buf = NULL;
ret = major_status;
end:
--- /dev/null
+#include <stdlib.h>
+#include <errno.h>
+
+#include <gssapi.h>
+#include <spnego_asn1.h>
+#include <der.h>
+#include <asn1_err.h>
+
+extern gss_OID GSS_KRB5_MECH;
+extern gss_OID GSS_SPNEGO_MECH;