2 * SPNEGO wrapper for Kerberos5 GSS-API
3 * kouril@ics.muni.cz, 2003
9 #include <spnego_asn1.h>
11 #define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
13 #define OID_cmp(o1, o2) \
14 (((o1).length == (o2).length) && \
15 (memcmp((o1).components, (o2).components,(int) (o1).length) == 0))
18 create_reply(OM_uint32 major_status, oid *mech, gss_buffer_t mech_token,
19 gss_buffer_t output_token)
21 NegTokenTarg targ_token;
22 unsigned char *buf = NULL;
27 memset(&targ_token, 0, sizeof(targ_token));
29 ALLOC(targ_token.negResult);
30 if (targ_token.negResult == NULL)
33 *targ_token.negResult = (major_status == 0) ? accept_completed : accept_incomplete;
35 ALLOC(targ_token.supportedMech);
36 if (targ_token.supportedMech == NULL) {
40 copy_MechType(mech, targ_token.supportedMech);
42 if (mech_token->length > 0) {
43 ALLOC(targ_token.responseToken);
44 if (targ_token.responseToken == NULL) {
48 targ_token.responseToken->data = malloc(mech_token->length);
49 memcpy(targ_token.responseToken->data, mech_token->value, mech_token->length);
50 targ_token.responseToken->length = mech_token->length;
53 ASN1_MALLOC_ENCODE(NegTokenTarg, buf, buf_size, &targ_token, &len, ret);
54 if (ret || buf_size != len) {
59 output_token->value = buf;
60 output_token->length = buf_size;
65 free_NegTokenTarg(&targ_token);
70 OM_uint32 gss_accept_sec_context_spnego
71 (OM_uint32 * minor_status,
72 gss_ctx_id_t * context_handle,
73 const gss_cred_id_t acceptor_cred_handle,
74 const gss_buffer_t input_token_buffer,
75 const gss_channel_bindings_t input_chan_bindings,
76 gss_name_t * src_name,
78 gss_buffer_t output_token,
79 OM_uint32 * ret_flags,
81 gss_cred_id_t * delegated_cred_handle)
83 NegTokenInit init_token;
84 OM_uint32 major_status;
85 gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
86 gss_buffer_desc krb5_input_token = GSS_C_EMPTY_BUFFER;
89 unsigned krb5_oid_array[] =
90 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02};
93 krb5_oid.length = sizeof(krb5_oid_array);
94 krb5_oid.components = krb5_oid_array;
96 memset(&init_token, 0, sizeof(init_token));
98 ret = decode_NegTokenInit(input_token_buffer->value,
99 input_token_buffer->length,
102 *minor_status = EINVAL; /* XXX */
103 return GSS_S_DEFECTIVE_TOKEN;
106 if (init_token.mechTypes == NULL || init_token.mechTypes->len == 0 ||
107 OID_cmp(init_token.mechTypes->val[0], krb5_oid)) {
108 *minor_status = EINVAL;
109 ret = GSS_S_BAD_MECH;
113 if (init_token.mechToken) {
114 krb5_input_token.value = init_token.mechToken->data;
115 krb5_input_token.length = init_token.mechToken->length;
118 major_status = gss_accept_sec_context(minor_status,
120 acceptor_cred_handle,
128 delegated_cred_handle);
129 if (GSS_ERROR(major_status)) {
134 ret = create_reply(major_status, &krb5_oid, &krb5_output_token, output_token);
142 free_NegTokenInit(&init_token);