Added the accepting part
authorkouril <kouril>
Sat, 6 Sep 2003 21:05:24 +0000 (21:05 +0000)
committerkouril <kouril>
Sat, 6 Sep 2003 21:05:24 +0000 (21:05 +0000)
spnegokrb5/Makefile
spnegokrb5/accept_sec_context.c
spnegokrb5/decapsulate.c
spnegokrb5/encapsulate.c
spnegokrb5/init_sec_context.c
spnegokrb5/spnegokrb5.h
spnegokrb5/spnegokrb5_locl.h

index 010fa1a..337926a 100644 (file)
@@ -16,12 +16,22 @@ asn1_files =                        \
        der_free.c              \
        der_length.c            \
        der_copy.c              \
-       timegm.c                                
+       timegm.c
+
+spnegokrb5_files =             \
+       init_sec_context.c      \
+       accept_sec_context.c    \
+       encapsulate.c           \
+       decapsulate.c           \
+       external.c
 
 all: libspnegokrb5.a
 
-libspnegokrb5.a: $(gen_files:.c=.o) $(asn1_files:.c=.o) init_sec_context.o accept_sec_context.o 
+libspnegokrb5.a: $(gen_files:.c=.o) $(asn1_files:.c=.o) $(spnegokrb5_files:.c=.o)
        ar -rscu libspnegokrb5.a $^
 
+test:
+       $(CC) -g -o test -I/usr/heimdal-0.6/include test.c libspnegokrb5.a -L/usr/heimdal-0.6/lib -lgssapi
+       
 clean:
        $(RM) *.o core libspnegokrb5.a
index c603b7b..1ea9ec0 100644 (file)
 /*
  * SPNEGO wrapper for Kerberos5 GSS-API 
  * kouril@ics.muni.cz, 2003
+ * (mostly based on Heimdal code)
  */
 
 #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))
 
-static int
-create_reply(OM_uint32 major_status, gss_OID mech, gss_buffer_t mech_token,
-             gss_buffer_t output_token)
+static OM_uint32
+code_NegTokenArg(OM_uint32 *minor_status,
+                const NegTokenTarg *targ,
+                unsigned char **outbuf,
+                size_t *outbuf_size)
 {
-   NegTokenTarg targ_token;
-   unsigned char *buf = NULL;
-   size_t buf_size;
-   size_t len;
-   int ret;
+    OM_uint32 ret;
+    u_char *buf;
+    size_t buf_size, buf_len;
 
-   memset(&targ_token, 0, sizeof(targ_token));
-   
-   ALLOC(targ_token.negResult);
-   if (targ_token.negResult == NULL)
-      return ENOMEM;
+    buf_size = 1024;
+    buf = malloc(buf_size);
+    if (buf == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
 
-   *targ_token.negResult = (major_status == 0) ? accept_completed : accept_incomplete;
+    do {
+       ret = encode_NegTokenTarg(buf + buf_size -1,
+                                 buf_size,
+                                 targ, &buf_len);
+       if (ret == 0) {
+           size_t tmp;
 
-   ALLOC(targ_token.supportedMech);
-   if (targ_token.supportedMech == NULL) {
-      ret = ENOMEM;
-      goto end;
-   }
-   copy_MechType((oid*)mech, targ_token.supportedMech);
+           ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+                                        buf_size - buf_len,
+                                        buf_len,
+                                        CONTEXT,
+                                        CONS,
+                                        1,
+                                        &tmp);
+           if (ret == 0)
+               buf_len += tmp;
+       }
+       if (ret) {
+           if (ret == ASN1_OVERFLOW) {
+               u_char *tmp;
 
-   if (mech_token->length > 0) {
-      ALLOC(targ_token.responseToken);
-      if (targ_token.responseToken == NULL) {
-        ret = ENOMEM;
-        goto end;
-      }
-      targ_token.responseToken->data = malloc(mech_token->length);
-      memcpy(targ_token.responseToken->data, mech_token->value, mech_token->length);
-      targ_token.responseToken->length = mech_token->length;
-   }
+               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);
 
-   ASN1_MALLOC_ENCODE(NegTokenTarg, buf, buf_size, &targ_token, &len, ret);
-   if (ret || buf_size != len) {
-      ret = EINVAL;
-      goto end;
-   }
+    *outbuf      = buf + buf_size - buf_len;
+    *outbuf_size = buf_len;
+    return GSS_S_COMPLETE;
+}
 
-   output_token->value = buf;
-   output_token->length = buf_size;
-   buf = NULL;
-   ret = 0;
+static OM_uint32
+send_reject (OM_uint32 *minor_status,
+            gss_buffer_t output_token)
+{
+    NegTokenTarg targ;
+    u_char *buf;
+    size_t buf_size;
+    OM_uint32 ret;
 
-end:
-   free_NegTokenTarg(&targ_token);
+    targ.negResult = malloc(sizeof(*targ.negResult));
+    if (targ.negResult == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    *(targ.negResult) = reject;
+    targ.supportedMech = NULL;
+    targ.responseToken = NULL;
+    targ.mechListMIC   = NULL;
+    
+    ret = code_NegTokenArg (minor_status, &targ, &buf, &buf_size);
+    free_NegTokenTarg(&targ);
+    if (ret)
+       return ret;
 
-   return ret;
+    ret = gssapi_spnego_encapsulate(minor_status,
+                                   buf, buf_size,
+                                   output_token,
+                                   GSS_SPNEGO_MECH);
+    free(buf);
+    if (ret)
+       return ret;
+    return GSS_S_BAD_MECH;
+}
+
+static OM_uint32
+send_accept (OM_uint32 *minor_status,
+            gss_buffer_t output_token,
+            gss_buffer_t mech_token)
+{
+    NegTokenTarg targ;
+    u_char *buf;
+    size_t buf_size;
+    OM_uint32 ret;
+
+    memset(&targ, 0, sizeof(targ));
+    targ.negResult = malloc(sizeof(*targ.negResult));
+    if (targ.negResult == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    *(targ.negResult) = accept_completed;
+
+    targ.supportedMech = malloc(sizeof(*targ.supportedMech));
+    if (targ.supportedMech == NULL) {
+       free_NegTokenTarg(&targ);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    ret = der_get_oid(GSS_KRB5_MECH->elements,
+                     GSS_KRB5_MECH->length,
+                     targ.supportedMech,
+                     NULL);
+    if (ret) {
+       free_NegTokenTarg(&targ);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    if (mech_token != NULL && mech_token->length != 0) {
+       targ.responseToken = malloc(sizeof(*targ.responseToken));
+       if (targ.responseToken == NULL) {
+           free_NegTokenTarg(&targ);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       targ.responseToken->length = mech_token->length;
+       targ.responseToken->data   = mech_token->value;
+       mech_token->length = 0;
+       mech_token->value  = NULL;
+    } else {
+       targ.responseToken = NULL;
+    }
+
+    ret = code_NegTokenArg (minor_status, &targ, &buf, &buf_size);
+    free_NegTokenTarg(&targ);
+    if (ret)
+       return ret;
+
+    ret = gssapi_spnego_encapsulate(minor_status,
+                                   buf, buf_size,
+                                   output_token,
+                                   GSS_SPNEGO_MECH);
+    free(buf);
+    if (ret)
+       return ret;
+    return GSS_S_COMPLETE;
 }
 
 OM_uint32 gss_accept_sec_context_spnego
@@ -79,59 +183,81 @@ OM_uint32 gss_accept_sec_context_spnego
 {
    NegTokenInit init_token;
    OM_uint32 major_status;
-   gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
-   gss_buffer_desc krb5_input_token = GSS_C_EMPTY_BUFFER;
-   size_t len;
-   int ret;
+   gss_buffer_desc ibuf, obuf;
+   gss_buffer_t ot = NULL;
+   OM_uint32 minor;
+   unsigned char *buf;
+   size_t buf_size;
+   size_t len, taglen, ni_len;
+   int found = 0;
+   int ret, i;
 
    memset(&init_token, 0, sizeof(init_token));
 
-   ret = decode_NegTokenInit(input_token_buffer->value, 
-                            input_token_buffer->length,
-                            &init_token, &len);
+   ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
+                                  &buf, &buf_size, GSS_SPNEGO_MECH);
+   if (ret)
+      return ret;
+
+   ret = der_match_tag_and_length(buf, buf_size, CONTEXT, CONS,
+                                 0, &len, &taglen);
+   if (ret)
+      return ret;
+
+   ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
    if (ret) {
       *minor_status = EINVAL; /* XXX */
       return GSS_S_DEFECTIVE_TOKEN;
    }
 
-   if (init_token.mechTypes == NULL || init_token.mechTypes->len == 0 ||
-       OID_cmp(&init_token.mechTypes->val[0], (oid *)GSS_KRB5_MECH)) {
-      *minor_status = EINVAL;
-      ret = GSS_S_BAD_MECH;
-      goto end;
-   }
-       
-   if (init_token.mechToken) {
-      krb5_input_token.value = init_token.mechToken->data;
-      krb5_input_token.length = init_token.mechToken->length;
-   }
-   
-   major_status = gss_accept_sec_context(minor_status,
-                                        context_handle,
-                                        acceptor_cred_handle,
-                                        &krb5_input_token,
-                                        input_chan_bindings,
-                                        src_name,
-                                        mech_type,
-                                        &krb5_output_token,
-                                        ret_flags,
-                                        time_rec,
-                                        delegated_cred_handle);
-   if (GSS_ERROR(major_status)) {
-      ret = major_status;
-      goto end;
+   if (init_token.mechTypes == NULL)
+      return send_reject (minor_status, output_token);
+
+   for (i = 0; !found && i < init_token.mechTypes->len; ++i) {
+      char mechbuf[17];
+      size_t mech_len;
+
+      ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1,
+                         sizeof(mechbuf),
+                         &init_token.mechTypes->val[i],
+                         &mech_len);
+      if (ret)
+          return GSS_S_DEFECTIVE_TOKEN;
+      if (mech_len == GSS_KRB5_MECH->length
+          && memcmp(GSS_KRB5_MECH->elements,
+                    mechbuf + sizeof(mechbuf) - mech_len,
+                    mech_len) == 0)
+          found = 1;
    }
 
-   ret = create_reply(major_status, GSS_KRB5_MECH, &krb5_output_token, output_token);
-   if (ret) {
-      *minor_status = ret;
-      ret = GSS_S_FAILURE;
-      free(output_token);
+   if (!found)
+      return send_reject (minor_status, output_token);
+
+   if (init_token.mechToken != NULL) {
+      ibuf.length = init_token.mechToken->length;
+      ibuf.value  = init_token.mechToken->data;
+
+      major_status = gss_accept_sec_context(&minor,
+                                           context_handle,
+                                           acceptor_cred_handle,
+                                           &ibuf,
+                                           input_chan_bindings,
+                                           src_name,
+                                           mech_type,
+                                           &obuf,
+                                           ret_flags,
+                                           time_rec,
+                                           delegated_cred_handle);
+      if (GSS_ERROR(major_status)) {
+        send_reject (minor_status, output_token);
+        return major_status;
+      }
+      ot = &obuf;
    }
 
-end:
-   free_NegTokenInit(&init_token);
+   ret = send_accept (minor_status, output_token, ot);
+   if (ot != NULL)
+      gss_release_buffer(&minor, ot);
 
    return ret;
 }
-
index 949280c..2dcb6a3 100644 (file)
  * SUCH DAMAGE. 
  */
 
-#include "gssapi_locl.h"
+#include "spnegokrb5_locl.h"
 
+#if 0
 RCSID("$Id$");
+#endif
 
 OM_uint32
-gssapi_krb5_verify_header(u_char **str,
+gssapi_verify_mech_header(u_char **str,
                          size_t total_len,
-                         char *type)
+                         const gss_OID mech)
 {
     size_t len, len_len, mech_len, foo;
     int e;
@@ -59,47 +61,45 @@ gssapi_krb5_verify_header(u_char **str,
     if (e)
        return GSS_S_DEFECTIVE_TOKEN;
     p += foo;
-    if (mech_len != GSS_KRB5_MECHANISM->length)
+    if (mech_len != mech->length)
        return GSS_S_BAD_MECH;
     if (memcmp(p,
-              GSS_KRB5_MECHANISM->elements,
-              GSS_KRB5_MECHANISM->length) != 0)
+              mech->elements,
+              mech->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.
+ * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size'
  * Does not copy data, so just free `in_token'.
  */
 
 OM_uint32
-gssapi_krb5_decapsulate(
+gssapi_spnego_decapsulate(
                        OM_uint32 *minor_status,    
                        gss_buffer_t input_token_buffer,
-                       krb5_data *out_data,
-                       char *type
+                       unsigned char **buf,
+                       size_t *buf_len, 
+                       const gss_OID mech
 )
 {
     u_char *p;
     OM_uint32 ret;
 
     p = input_token_buffer->value;
-    ret = gssapi_krb5_verify_header(&p,
+    ret = gssapi_verify_mech_header(&p,
                                    input_token_buffer->length,
-                                   type);
+                                   mech);
     if (ret) {
-       *minor_status = 0;
-       return ret;
+       *minor_status = ret;
+       return GSS_S_FAILURE;
     }
 
-    out_data->length = input_token_buffer->length -
+    *buf_len = input_token_buffer->length -
        (p - (u_char *)input_token_buffer->value);
-    out_data->data   = p;
+    *buf = p;
     return GSS_S_COMPLETE;
 }
index 2fc95f4..fbc1e00 100644 (file)
 #include "spnegokrb5_locl.h"
 
 void
-gssapi_spnego_encap_length (size_t data_len,
-                           size_t *len,
-                           size_t *total_len)
+gssapi_encap_length (size_t data_len,
+                    size_t *len,
+                    size_t *total_len,
+                    const gss_OID mech)
 {
     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 = 1 + 1 + mech->length + data_len;
 
     len_len = length_len(*len);
 
@@ -52,9 +49,9 @@ gssapi_spnego_encap_length (size_t data_len,
 }
 
 u_char *
-gssapi_spnego_make_header (u_char *p,
-                          size_t len,
-                          u_char *type)
+gssapi_mech_make_header (u_char *p,
+                        size_t len,
+                        const gss_OID mech)
 {
     int e;
     size_t len_len, foo;
@@ -66,13 +63,9 @@ gssapi_spnego_make_header (u_char *p,
        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
+    *p++ = mech->length;
+    memcpy (p, mech->elements, mech->length);
+    p += mech->length;
     return p;
 }
 
@@ -86,13 +79,13 @@ gssapi_spnego_encapsulate(
                        unsigned char *buf,
                        size_t buf_size,
                        gss_buffer_t output_token,
-                       u_char *type
+                       const gss_OID mech
 )
 {
     size_t len, outer_len;
     u_char *p;
 
-    gssapi_spnego_encap_length (buf_size, &len, &outer_len);
+    gssapi_encap_length (buf_size, &len, &outer_len, mech);
     
     output_token->length = outer_len;
     output_token->value  = malloc (outer_len);
@@ -101,7 +94,7 @@ gssapi_spnego_encapsulate(
        return GSS_S_FAILURE;
     }  
 
-    p = gssapi_spnego_make_header (output_token->value, len, type);
+    p = gssapi_mech_make_header (output_token->value, len, mech);
     memcpy (p, buf, buf_size);
     return GSS_S_COMPLETE;
 }
index 9f79dee..3d08625 100644 (file)
@@ -1,12 +1,11 @@
 /*
  *  SPNEGO wrapper for Kerberos5 GSS-API
  *  kouril@ics.muni.cz, 2003
+ *  (mostly based on Heimdal code)
  */
 
 #include "spnegokrb5_locl.h"
 
-#define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
-
 static int
 add_mech(MechTypeList *mech_list, gss_OID mech)
 {
@@ -27,6 +26,7 @@ add_mech(MechTypeList *mech_list, gss_OID mech)
    return 0;
 }
 
+#if 0
 static int
 set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
 {
@@ -46,6 +46,7 @@ set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
       flags->integFlag = 1;
    return 0;
 }
+#endif
 
 OM_uint32 gss_init_sec_context_spnego(
            OM_uint32 * minor_status,
@@ -170,7 +171,7 @@ OM_uint32 gss_init_sec_context_spnego(
 
     ret = gssapi_spnego_encapsulate(minor_status,
                                    buf + buf_size - len, len,
-                                   output_token, "\x01\x00");
+                                   output_token, GSS_SPNEGO_MECH);
 
    ret = major_status;
 
index e8e7f7c..84a4db8 100644 (file)
@@ -8,32 +8,32 @@ extern "C" {
 #include <gssapi.h>
 
 OM_uint32 gss_init_sec_context_spnego(
-            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 *,
+            const gss_cred_id_t,
+            gss_ctx_id_t *,
+            const gss_name_t,
+            const gss_OID,
+            OM_uint32,
+            OM_uint32,
+            const gss_channel_bindings_t,
+            const gss_buffer_t,
+            gss_OID *,
+            gss_buffer_t,
+            OM_uint32 *,
+            OM_uint32 *);
 
 OM_uint32 gss_accept_sec_context_spnego
-           (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_ctx_id_t *,
+            const gss_cred_id_t,
+            const gss_buffer_t,
+            const gss_channel_bindings_t,
+            gss_name_t *,
+            gss_OID *,
+            gss_buffer_t,
+            OM_uint32 *,
+            OM_uint32 *,
+            gss_cred_id_t *);
 
 #ifdef  __cplusplus
 }
index 6dba1ca..57fa9b2 100644 (file)
@@ -3,8 +3,27 @@
 
 #include <gssapi.h>
 #include <spnego_asn1.h>
+#include <spnegokrb5.h>
 #include <der.h>
 #include <asn1_err.h>
 
+#define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
+
 extern gss_OID GSS_KRB5_MECH;
 extern gss_OID GSS_SPNEGO_MECH;
+
+OM_uint32
+gssapi_spnego_encapsulate(
+                        OM_uint32 *,
+                        unsigned char *,
+                        size_t,
+                        gss_buffer_t,
+                        const gss_OID);
+
+OM_uint32
+gssapi_spnego_decapsulate(
+                        OM_uint32 *,
+                        gss_buffer_t,
+                        unsigned char **,
+                        size_t *,
+                        const gss_OID);