Add install-sh
[mod_auth_kerb.git] / spnegokrb5 / init_sec_context.c
index a76a491..70724a4 100644 (file)
@@ -1,29 +1,32 @@
 /*
  *  SPNEGO wrapper for Kerberos5 GSS-API
  *  kouril@ics.muni.cz, 2003
+ *  (mostly based on Heimdal code)
  */
-#include <stdlib.h>
-#include <errno.h>
 
-#include <gssapi.h>
-#include <spnego_asn1.h>
-
-#define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
+#include "spnegokrb5_locl.h"
 
 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;
 }
 
+#if 0
 static int
 set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
 {
@@ -43,8 +46,9 @@ set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
       flags->integFlag = 1;
    return 0;
 }
+#endif
 
-OM_uint32 gss_init_sec_context_spnego(
+OM_uint32 KRB5_LIB_FUNCTION gss_init_sec_context_spnego(
            OM_uint32 * minor_status,
             const gss_cred_id_t initiator_cred_handle,
             gss_ctx_id_t * context_handle,
@@ -66,28 +70,23 @@ OM_uint32 gss_init_sec_context_spnego(
    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;
@@ -95,12 +94,13 @@ OM_uint32 gss_init_sec_context_spnego(
       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,
@@ -129,16 +129,50 @@ OM_uint32 gss_init_sec_context_spnego(
    /* 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,
+                                        KERB_CTXT,
+                                        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, GSS_SPNEGO_MECH);
 
-   output_token->value = buf;
-   output_token->length = buf_size;
-   buf = NULL;
    ret = major_status;
 
 end: