More sensical mech selection for gss_acquire_cred/accept_sec_context
authorGreg Hudson <ghudson@mit.edu>
Mon, 4 Apr 2011 23:06:09 +0000 (23:06 +0000)
committerGreg Hudson <ghudson@mit.edu>
Mon, 4 Apr 2011 23:06:09 +0000 (23:06 +0000)
If a caller passes an empty mech set to gss_acquire_cred, get a cred
for all mechs instead of just the krb5 mech, as we don't know what
mechanism the cred is going to be used with (particularly in the
acceptor case).  As a related fix, if a caller passes a credential to
gss_accept_sec_context and it does not contain a mech-specific cred
for the token's mech, error out instead of using the default cred with
the token's mechanism.

ticket: 6894

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24840 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/mechglue/g_accept_sec_context.c
src/lib/gssapi/mechglue/g_acquire_cred.c

index 8714f3fb7b325285b229c963825d1b15fc7d8351..8e0b7c5a08079c6e5d0e67e262859b527180db7d 100644 (file)
@@ -115,7 +115,6 @@ gss_cred_id_t *             d_cred;
     OM_uint32          status, temp_status, temp_minor_status;
     OM_uint32          temp_ret_flags = 0;
     gss_union_ctx_id_t union_ctx_id;
-    gss_union_cred_t   union_cred;
     gss_cred_id_t      input_cred_handle = GSS_C_NO_CREDENTIAL;
     gss_cred_id_t      tmp_d_cred = GSS_C_NO_CREDENTIAL;
     gss_name_t         internal_name = GSS_C_NO_NAME;
@@ -181,11 +180,17 @@ gss_cred_id_t *           d_cred;
 
     /*
      * get the appropriate cred handle from the union cred struct.
-     * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
-     * use the default credential.
      */
-    union_cred = (gss_union_cred_t) verifier_cred_handle;
-    input_cred_handle = gssint_get_mechanism_cred(union_cred, token_mech_type);
+    if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
+       input_cred_handle =
+           gssint_get_mechanism_cred((gss_union_cred_t)verifier_cred_handle,
+                                     token_mech_type);
+       if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+           /* verifier credential specified but no acceptor credential found */
+           status = GSS_S_NO_CRED;
+           goto error_out;
+       }
+    }
 
     /*
      * now select the approprate underlying mechanism routine and
index 6dfc65f7b290e68f9005d5f8828537ce9d677165..71bbf9e21241f558e6cf91cf669d3704376c4231 100644 (file)
@@ -103,14 +103,11 @@ gss_OID_set *             actual_mechs;
 OM_uint32 *            time_rec;
 
 {
-    OM_uint32 major = GSS_S_FAILURE;
+    OM_uint32 major = GSS_S_FAILURE, tmpMinor;
     OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
-    gss_OID_set_desc default_OID_set;
-    gss_OID_set mechs;
-    gss_OID_desc default_OID;
-    gss_mechanism mech;
+    gss_OID_set mechs = GSS_C_NO_OID_SET;
     unsigned int i;
-    gss_union_cred_t creds;
+    gss_union_cred_t creds = NULL;
 
     major = val_acq_cred_args(minor_status,
                              desired_name,
@@ -121,44 +118,37 @@ OM_uint32 *               time_rec;
                              actual_mechs,
                              time_rec);
     if (major != GSS_S_COMPLETE)
-       return (major);
-
-    /* Initial value needed below. */
-    major = GSS_S_FAILURE;
+       goto cleanup;
 
     /*
-     * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
-     * appropriate default.  We use the first mechanism in the
-     * mechansim list as the default. This set is created with
-     * statics thus needs not be freed
+     * if desired_mechs equals GSS_C_NULL_OID_SET, then try to
+     * acquire credentials for all mechanisms.
      */
-    if(desired_mechs == GSS_C_NULL_OID_SET) {
-       mech = gssint_get_mechanism(NULL);
-       if (mech == NULL)
-           return (GSS_S_BAD_MECH);
-
-       mechs = &default_OID_set;
-       default_OID_set.count = 1;
-       default_OID_set.elements = &default_OID;
-       default_OID.length = mech->mech_type.length;
-       default_OID.elements = mech->mech_type.elements;
+    if (desired_mechs == GSS_C_NULL_OID_SET) {
+       major = gss_indicate_mechs(minor_status, &mechs);
+       if (major != GSS_S_COMPLETE)
+           goto cleanup;
     } else
        mechs = desired_mechs;
 
-    if (mechs->count == 0)
-       return (GSS_S_BAD_MECH);
+    if (mechs->count == 0) {
+       major = GSS_S_BAD_MECH;
+       goto cleanup;
+    }
 
     /* allocate the output credential structure */
-    creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
-    if (creds == NULL)
-       return (GSS_S_FAILURE);
+    creds = (gss_union_cred_t)calloc(1, sizeof (gss_union_cred_desc));
+    if (creds == NULL) {
+       major = GSS_S_FAILURE;
+       *minor_status = ENOMEM;
+       goto cleanup;
+    }
 
-    /* initialize to 0s */
-    (void) memset(creds, 0, sizeof (gss_union_cred_desc));
+    creds->count = 0;
     creds->loopback = creds;
 
     /* for each requested mech attempt to obtain a credential */
-    for (i = 0; i < mechs->count; i++) {
+    for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) {
        major = gss_add_cred(minor_status, (gss_cred_id_t)creds,
                             desired_name,
                             &mechs->elements[i],
@@ -188,10 +178,8 @@ OM_uint32 *                time_rec;
     } /* for */
 
     /* ensure that we have at least one credential element */
-    if (creds->count < 1) {
-       free(creds);
-       return (major);
-    }
+    if (creds->count < 1)
+       goto cleanup;
 
     /*
      * fill in output parameters
@@ -204,20 +192,22 @@ OM_uint32 *               time_rec;
        oids.elements = creds->mechs_array;
 
        major = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs);
-       if (GSS_ERROR(major)) {
-           (void) gss_release_cred(minor_status,
-                                   (gss_cred_id_t *)&creds);
-           return (major);
-       }
+       if (GSS_ERROR(major))
+           goto cleanup;
     }
 
     if (time_rec)
        *time_rec = outTime;
 
-
-    creds->loopback = creds;
     *output_cred_handle = (gss_cred_id_t)creds;
-    return (GSS_S_COMPLETE);
+
+cleanup:
+    if (GSS_ERROR(major))
+       gss_release_cred(&tmpMinor, (gss_cred_id_t *)&creds);
+    if (desired_mechs == GSS_C_NO_OID_SET)
+        generic_gss_release_oid_set(&tmpMinor, &mechs);
+
+    return (major);
 }
 
 static OM_uint32