More work on creds
authorLuke Howard <lukeh@padl.com>
Wed, 8 Sep 2010 17:34:03 +0000 (19:34 +0200)
committerLuke Howard <lukeh@padl.com>
Wed, 8 Sep 2010 17:34:03 +0000 (19:34 +0200)
mech_eap/acquire_cred.c
mech_eap/acquire_cred_with_password.c
mech_eap/add_cred.c
mech_eap/gssapiP_eap.h
mech_eap/util.h
mech_eap/util_cred.c
mech_eap/util_mech.c
mech_eap/util_name.c
mech_eap/util_oid.c

index 0bb1f1f..c85966e 100644 (file)
@@ -42,5 +42,7 @@ gss_acquire_cred(OM_uint32 *minor,
                  gss_OID_set *actual_mechs,
                  OM_uint32 *time_rec)
 {
-    GSSEAP_NOT_IMPLEMENTED;
+    return gssEapAcquireCred(minor, desired_name, GSS_C_NO_BUFFER,
+                             time_req, desired_mechs, cred_usage,
+                             output_cred_handle, actual_mechs, time_rec);
 }
index 776ecba..e56419e 100644 (file)
@@ -43,5 +43,7 @@ gss_acquire_cred_with_password(OM_uint32 *minor,
                                gss_OID_set *actual_mechs,
                                OM_uint32 *time_rec)
 {
-    GSSEAP_NOT_IMPLEMENTED;
+    return gssEapAcquireCred(minor, desired_name, password,
+                             time_req, desired_mechs, cred_usage,
+                             output_cred_handle, actual_mechs, time_rec);
 }
index 80b4b24..0332150 100644 (file)
 
 #include "gssapiP_eap.h"
 
+/*
+ * Note that this shouldn't really be required to be implemented by anything
+ * apart from the mechanism glue layer. However, Heimdal does call into the
+ * mechanism here.
+ */
 OM_uint32
 gss_add_cred(OM_uint32 *minor,
              gss_cred_id_t input_cred_handle,
@@ -45,5 +50,33 @@ gss_add_cred(OM_uint32 *minor,
              OM_uint32 *initiator_time_rec,
              OM_uint32 *acceptor_time_rec)
 {
-    GSSEAP_NOT_IMPLEMENTED;
+    OM_uint32 major;
+    OM_uint32 time_req, time_rec = 0;
+    gss_OID_set_desc mechs;
+
+    *output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+    if (cred_usage == GSS_C_ACCEPT)
+        time_req = acceptor_time_req;
+    else
+        time_req = initiator_time_req;
+
+    mechs.count = 1;
+    mechs.elements = desired_mech;
+
+    major = gss_acquire_cred(minor,
+                             desired_name,
+                             time_req,
+                             &mechs,
+                             cred_usage,
+                             output_cred_handle,
+                             actual_mechs,
+                             &time_rec);
+
+    if (initiator_time_rec != NULL)
+        *initiator_time_rec = time_rec;
+    if (acceptor_time_rec != NULL)
+        *acceptor_time_rec = time_rec;
+
+    return major;
 }
index 92cadac..267235a 100644 (file)
@@ -74,8 +74,8 @@ struct gss_name_struct {
     struct eap_gss_avp_list *avps;
 };
 
-#define CRED_FLAG_INITIATOR                 0x00000001
-#define CRED_FLAG_ACCEPTOR                  0x00000002
+#define CRED_FLAG_INITIAT                 0x00000001
+#define CRED_FLAG_ACCEPT                    0x00000002
 #define CRED_FLAG_DEFAULT_IDENTITY          0x00000004
 #define CRED_FLAG_PASSWORD                  0x00000008
 
@@ -84,6 +84,7 @@ struct gss_cred_id_struct {
     OM_uint32 flags;
     gss_name_t name;
     gss_buffer_desc password;
+    gss_OID_set mechanisms;
     time_t expiryTime;
 };
 
index cdcabd3..1495857 100644 (file)
@@ -91,6 +91,17 @@ OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
 OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
 OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
 
+OM_uint32
+gssEapAcquireCred(OM_uint32 *minor,
+                  const gss_name_t desiredName,
+                  const gss_buffer_t password,
+                  OM_uint32 timeReq,
+                  const gss_OID_set desiredMechs,
+                  int cred_usage,
+                  gss_cred_id_t *pCred,
+                  gss_OID_set *pActualMechs,
+                  OM_uint32 *timeRec);
+
 /* util_crypt.c */
 int
 gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
@@ -169,6 +180,10 @@ gssEapOidToEnctype(OM_uint32 *minor,
 int
 gssEapIsMechanismOid(const gss_OID oid);
 
+OM_uint32
+gssEapValidateMechs(OM_uint32 *minor,
+                   const gss_OID_set mechs);
+
 /* util_name.c */
 OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
 OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
@@ -196,6 +211,11 @@ decomposeOid(OM_uint32 *minor_status,
              gss_OID_desc *oid,
              int *suffix) ;
 
+OM_uint32
+duplicateOidSet(OM_uint32 *minor,
+                const gss_OID_set src,
+                gss_OID_set *dst);
+
 static inline int
 oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2)
 {
@@ -389,4 +409,31 @@ bufferToString(OM_uint32 *minor,
     *minor = 0;
     return GSS_S_COMPLETE;
 }
+
+static OM_uint32
+duplicateBuffer(OM_uint32 *minor,
+                const gss_buffer_t src,
+                gss_buffer_t dst)
+{
+    dst->length = 0;
+    dst->value = NULL;
+
+    if (src == GSS_C_NO_BUFFER)
+        return GSS_S_COMPLETE;
+
+    dst->value = GSSEAP_MALLOC(src->length + 1);
+    if (dst->value == NULL) {
+        *minor = ENOMEM;
+        return GSS_S_FAILURE;
+    }
+
+    dst->length = src->length;
+    memcpy(dst->value, src->value, dst->length);
+
+    ((unsigned char *)dst->value)[dst->length] = '\0';
+
+    *minor = 0;
+    return GSS_S_COMPLETE;
+}
+
 #endif /* _UTIL_H_ */
index 08ede79..984ebac 100644 (file)
@@ -52,6 +52,8 @@ gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
         return GSS_S_FAILURE;
     }
 
+    cred->expiryTime = ~0;
+
     *pCred = cred;
 
     *minor = 0;
@@ -63,7 +65,6 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
 {
     OM_uint32 tmpMinor;
     gss_cred_id_t cred = *pCred;
-    krb5_context kerbCtx = NULL;
 
     if (cred == GSS_C_NO_CREDENTIAL) {
         return GSS_S_COMPLETE;
@@ -84,3 +85,82 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
     *minor = 0;
     return GSS_S_COMPLETE;
 }
+
+OM_uint32
+gssEapAcquireCred(OM_uint32 *minor,
+                  const gss_name_t desiredName,
+                  const gss_buffer_t password,
+                  OM_uint32 timeReq,
+                  const gss_OID_set desiredMechs,
+                  int credUsage,
+                  gss_cred_id_t *pCred,
+                  gss_OID_set *pActualMechs,
+                  OM_uint32 *timeRec)
+{
+    OM_uint32 major, tmpMinor;
+    gss_cred_id_t cred;
+
+    *pCred = GSS_C_NO_CREDENTIAL;
+
+    major = gssEapAllocCred(minor, &cred);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    if (desiredName != GSS_C_NO_NAME) {
+        major = gss_duplicate_name(minor, desiredName, &cred->name);
+        if (GSS_ERROR(major))
+            goto cleanup;
+    } else {
+        cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
+    }
+
+    if (password != GSS_C_NO_BUFFER) {
+        major = duplicateBuffer(minor, password, &cred->password);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
+        cred->flags |= CRED_FLAG_PASSWORD;
+    }
+
+    major = gssEapValidateMechs(minor, desiredMechs);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    switch (credUsage) {
+    case GSS_C_BOTH:
+        cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT;
+        break;
+    case GSS_C_INITIATE:
+        cred->flags |= CRED_FLAG_INITIATE;
+        break;
+    case GSS_C_ACCEPT:
+        cred->flags |= CRED_FLAG_ACCEPT;
+        break;
+    default:
+        major = GSS_S_FAILURE;
+        goto cleanup;
+        break;
+    }
+
+    if (pActualMechs != NULL) {
+        major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
+        if (GSS_ERROR(major))
+            goto cleanup;
+    }
+
+    if (timeRec != NULL)
+        *timeRec = GSS_C_INDEFINITE;
+
+    *pCred = cred;
+    major = GSS_S_COMPLETE;
+
+cleanup:
+    if (GSS_ERROR(major))
+        gssEapReleaseCred(&tmpMinor, &cred);
+
+    return major;
+}
index 745108f..be83f5e 100644 (file)
  *        mechInvoke(5)
  */
 
-static const gss_OID_desc gssEapMechPrefix = {
+static gss_OID_desc gssEapMechPrefix = {
     /* Note that alone this is not a valid DER encoded OID */
     11, "\x06\x0A\x2B\x06\x01\x04\x01\xA9\x4A\x15\x01\x00"
 };
 
-static const gss_OID_desc gssEapConcreteMechs[] = {
+static gss_OID_desc gssEapConcreteMechs[] = {
     /* 1.3.6.1.4.1.5322.21.1  */
     { 11, "\x06\x0A\x2B\x06\x01\x04\x01\xA9\x4A\x15\x01" },
     /* 1.3.6.1.4.1.5322.21.1.17 */
@@ -82,6 +82,28 @@ gssEapIsMechanismOid(const gss_OID oid)
 }
 
 OM_uint32
+gssEapValidateMechs(OM_uint32 *minor,
+                    const gss_OID_set mechs)
+{
+    int i;
+
+    *minor = 0;
+
+    if (mechs == GSS_C_NO_OID_SET) {
+        return GSS_S_COMPLETE;
+    }
+
+    for (i = 0; i < mechs->count; i++) {
+        gss_OID oid = &mechs->elements[i];
+
+        if (!gssEapIsMechanismOid(oid))
+            return GSS_S_BAD_MECH;
+    }
+
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
 gssEapOidToEnctype(OM_uint32 *minor,
                    const gss_OID oid,
                    krb5_enctype *enctype)
index cc00c42..9f0e219 100644 (file)
@@ -55,7 +55,7 @@
 
 #include "gssapiP_eap.h"
 
-static const gss_OID_desc gssEapNtPrincipalName = {
+static gss_OID_desc gssEapNtPrincipalName = {
     /* 1.3.6.1.4.1.5322.21.2.1  */
     12, "\x06\x0A\x2B\x06\x01\x04\x01\xA9\x4A\x15\x02\x01"
 };
index 34b7c7b..14b5f3b 100644 (file)
@@ -184,3 +184,34 @@ gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid)
     return major;
 }
 #endif
+
+OM_uint32
+duplicateOidSet(OM_uint32 *minor,
+                const gss_OID_set src,
+                gss_OID_set *dst)
+{
+    OM_uint32 major, tmpMinor;
+    int i;
+
+    if (src == GSS_C_NO_OID_SET) {
+        *dst = GSS_C_NO_OID_SET;
+        return GSS_S_COMPLETE;
+    }
+
+    major = gss_create_empty_oid_set(minor, dst);
+    if (GSS_ERROR(major))
+        return major;
+
+    for (i = 0; i < src->count; i++) {
+        gss_OID oid = &src->elements[i];
+
+        major = gss_add_oid_set_member(minor, oid, dst);
+        if (GSS_ERROR(major))
+            break;
+    }
+
+    if (GSS_ERROR(major))
+        gss_release_oid_set(&tmpMinor, dst);
+
+    return major;
+}