]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Introduce credential store extensions
authorSimo Sorce <simo@redhat.com>
Fri, 2 Mar 2012 23:27:49 +0000 (18:27 -0500)
committerGreg Hudson <ghudson@mit.edu>
Fri, 20 Jul 2012 18:02:31 +0000 (14:02 -0400)
Add new APIs gss_acquire_cred_from, gss_add_cred_from, and
gss_store_cred_into, which take additional argments to specify the
location of the credential storage using a key-value map, where keys
are interpreted by the mechanisms.

ticket: 7217 (new)

src/lib/gssapi/generic/gssapi_ext.h
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi/mechglue/g_acquire_cred.c
src/lib/gssapi/mechglue/g_store_cred.c
src/lib/gssapi/mechglue/mglueP.h

index b4f8a77ada2d57c928604ba71a1e06b6fefeb1bf..05f1ed7fb4a6b64481f221539a295b9ca14a4f94 100644 (file)
@@ -461,6 +461,62 @@ int KRB5_CALLCONV gss_oid_equal
     gss_const_OID       /* second_oid */
 );
 
+/* Credential store extensions */
+
+struct gss_key_value_element_struct {
+    const char *key;
+    const char *value;
+};
+typedef struct gss_key_value_element_struct gss_key_value_element_desc;
+
+struct gss_key_value_set_struct {
+    OM_uint32 count;
+    gss_key_value_element_desc *elements;
+};
+typedef struct gss_key_value_set_struct gss_key_value_set_desc;
+typedef const gss_key_value_set_desc *gss_const_key_value_set_t;
+
+#define GSS_C_NO_CRED_STORE ((gss_const_key_value_set_t) 0)
+
+OM_uint32 KRB5_CALLCONV
+gss_acquire_cred_from(
+    OM_uint32 *,               /* minor_status */
+    gss_name_t,                /* desired_name */
+    OM_uint32,                 /* time_req */
+    gss_OID_set,               /* desired_mechs */
+    gss_cred_usage_t,          /* cred_usage */
+    gss_const_key_value_set_t, /* cred_store */
+    gss_cred_id_t *,           /* output_cred_handle */
+    gss_OID_set *,             /* actual_mechs */
+    OM_uint32 *);              /* time_rec */
+
+OM_uint32 KRB5_CALLCONV
+gss_add_cred_from(
+    OM_uint32 *,               /* minor_status */
+    gss_cred_id_t,             /* input_cred_handle */
+    gss_name_t,                /* desired_name */
+    gss_OID,                   /* desired_mech */
+    gss_cred_usage_t,          /* cred_usage */
+    OM_uint32,                 /* initiator_time_req */
+    OM_uint32,                 /* acceptor_time_req */
+    gss_const_key_value_set_t, /* cred_store */
+    gss_cred_id_t *,           /* output_cred_handle */
+    gss_OID_set *,             /* actual_mechs */
+    OM_uint32 *,               /* initiator_time_rec */
+    OM_uint32 *);              /* acceptor_time_rec */
+
+OM_uint32 KRB5_CALLCONV
+gss_store_cred_into(
+    OM_uint32 *,               /* minor_status */
+    gss_cred_id_t,             /* input_cred_handle */
+    gss_cred_usage_t,          /* input_usage */
+    gss_OID,                   /* desired_mech */
+    OM_uint32,                 /* overwrite_cred */
+    OM_uint32,                 /* default_cred */
+    gss_const_key_value_set_t, /* cred_store */
+    gss_OID_set *,             /* elements_stored */
+    gss_cred_usage_t *);       /* cred_usage_stored */
+
 #ifdef __cplusplus
 }
 #endif
index 58111aa63fc420ccdb08cf4dd54d650997a59130..a8ee3f2447e1bfd8ace6ab3f7d31a369e0e42373 100644 (file)
@@ -148,3 +148,6 @@ krb5_gss_dbg_client_expcreds
 krb5_gss_register_acceptor_identity
 krb5_gss_use_kdc_context
 gss_inquire_name
+gss_acquire_cred_from
+gss_add_cred_from
+gss_store_cred_into
index ad4e99b7e76028d8b223d32427492b3066769634..c28bf720e3fc98f18bfa50852253483fd85be4b4 100644 (file)
@@ -42,6 +42,7 @@ val_acq_cred_args(
     OM_uint32 time_req,
     gss_OID_set desired_mechs,
     int cred_usage,
+    gss_const_key_value_set_t cred_store,
     gss_cred_id_t *output_cred_handle,
     gss_OID_set *actual_mechs,
     OM_uint32 *time_rec)
@@ -79,6 +80,12 @@ val_acq_cred_args(
        return GSS_S_FAILURE;
     }
 
+    if (cred_store != NULL && cred_store->count == 0) {
+       *minor_status = EINVAL;
+       map_errcode(minor_status);
+       return GSS_S_FAILURE;
+    }
+
     return (GSS_S_COMPLETE);
 }
 
@@ -102,6 +109,33 @@ gss_cred_id_t *            output_cred_handle;
 gss_OID_set *          actual_mechs;
 OM_uint32 *            time_rec;
 
+{
+    return gss_acquire_cred_from(minor_status, desired_name, time_req,
+                                desired_mechs, cred_usage, NULL,
+                                output_cred_handle, actual_mechs, time_rec);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_acquire_cred_from(minor_status,
+                     desired_name,
+                     time_req,
+                     desired_mechs,
+                     cred_usage,
+                     cred_store,
+                     output_cred_handle,
+                     actual_mechs,
+                     time_rec)
+
+OM_uint32 *                    minor_status;
+gss_name_t                     desired_name;
+OM_uint32                      time_req;
+gss_OID_set                    desired_mechs;
+int                            cred_usage;
+gss_const_key_value_set_t      cred_store;
+gss_cred_id_t *                        output_cred_handle;
+gss_OID_set *                  actual_mechs;
+OM_uint32 *                    time_rec;
+
 {
     OM_uint32 major = GSS_S_FAILURE, tmpMinor;
     OM_uint32 first_major = GSS_S_COMPLETE, first_minor = 0;
@@ -115,6 +149,7 @@ OM_uint32 *         time_rec;
                              time_req,
                              desired_mechs,
                              cred_usage,
+                             cred_store,
                              output_cred_handle,
                              actual_mechs,
                              time_rec);
@@ -150,11 +185,11 @@ OM_uint32 *               time_rec;
 
     /* for each requested mech attempt to obtain a credential */
     for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) {
-       major = gss_add_cred(&tmpMinor, (gss_cred_id_t)creds,
-                            desired_name,
-                            &mechs->elements[i],
-                            cred_usage, time_req, time_req, NULL,
-                            NULL, &initTimeOut, &acceptTimeOut);
+       major = gss_add_cred_from(&tmpMinor, (gss_cred_id_t)creds,
+                                 desired_name, &mechs->elements[i],
+                                 cred_usage, time_req, time_req,
+                                 cred_store, NULL, NULL, &initTimeOut,
+                                 &acceptTimeOut);
        if (major == GSS_S_COMPLETE) {
            /* update the credential's time */
            if (cred_usage == GSS_C_ACCEPT) {
@@ -226,6 +261,7 @@ val_add_cred_args(
     gss_name_t desired_name,
     gss_OID desired_mech,
     gss_cred_usage_t cred_usage,
+    gss_const_key_value_set_t cred_store,
     OM_uint32 initiator_time_req,
     OM_uint32 acceptor_time_req,
     gss_cred_id_t *output_cred_handle,
@@ -270,6 +306,12 @@ val_add_cred_args(
        return GSS_S_FAILURE;
     }
 
+    if (cred_store != NULL && cred_store->count == 0) {
+       *minor_status = EINVAL;
+       map_errcode(minor_status);
+       return GSS_S_FAILURE;
+    }
+
     return (GSS_S_COMPLETE);
 }
 
@@ -292,6 +334,34 @@ gss_add_cred(minor_status, input_cred_handle,
     gss_OID_set                *actual_mechs;
     OM_uint32          *initiator_time_rec;
     OM_uint32          *acceptor_time_rec;
+{
+    return gss_add_cred_from(minor_status, input_cred_handle, desired_name,
+                            desired_mech, cred_usage, initiator_time_req,
+                            acceptor_time_req, NULL, output_cred_handle,
+                            actual_mechs, initiator_time_rec,
+                            acceptor_time_rec);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_add_cred_from(minor_status, input_cred_handle,
+                 desired_name, desired_mech,
+                 cred_usage,
+                 initiator_time_req, acceptor_time_req,
+                 cred_store,
+                 output_cred_handle, actual_mechs,
+                 initiator_time_rec, acceptor_time_rec)
+    OM_uint32          *minor_status;
+    gss_cred_id_t      input_cred_handle;
+    gss_name_t         desired_name;
+    gss_OID            desired_mech;
+    gss_cred_usage_t   cred_usage;
+    OM_uint32          initiator_time_req;
+    OM_uint32          acceptor_time_req;
+    gss_const_key_value_set_t  cred_store;
+    gss_cred_id_t      *output_cred_handle;
+    gss_OID_set                *actual_mechs;
+    OM_uint32          *initiator_time_rec;
+    OM_uint32          *acceptor_time_rec;
 {
     OM_uint32          status, temp_minor_status;
     OM_uint32          time_req, time_rec;
@@ -309,6 +379,7 @@ gss_add_cred(minor_status, input_cred_handle,
                               desired_name,
                               desired_mech,
                               cred_usage,
+                              cred_store,
                               initiator_time_req,
                               acceptor_time_req,
                               output_cred_handle,
@@ -330,15 +401,16 @@ gss_add_cred(minor_status, input_cred_handle,
            return (GSS_S_FAILURE);
 
        (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
-
-       /* for default credentials we will use GSS_C_NO_NAME */
-       internal_name = GSS_C_NO_NAME;
     } else {
        union_cred = (gss_union_cred_t)input_cred_handle;
        if (gssint_get_mechanism_cred(union_cred, desired_mech) !=
            GSS_C_NO_CREDENTIAL)
            return (GSS_S_DUPLICATE_ELEMENT);
+    }
 
+    /* for default credentials we will use GSS_C_NO_NAME */
+    if (input_cred_handle != GSS_C_NO_CREDENTIAL ||
+        cred_store != GSS_C_NO_CRED_STORE) {
        /* may need to create a mechanism specific name */
        if (desired_name) {
            union_name = (gss_union_name_t)desired_name;
@@ -367,10 +439,18 @@ gss_add_cred(minor_status, input_cred_handle,
     else
        time_req = 0;
 
-    status = mech->gss_acquire_cred(minor_status,
-                                   internal_name, time_req,
-                                   GSS_C_NULL_OID_SET, cred_usage,
-                                   &cred, NULL, &time_rec);
+    if (mech->gss_acquire_cred_from) {
+       status = mech->gss_acquire_cred_from(minor_status, internal_name,
+                                            time_req, GSS_C_NULL_OID_SET,
+                                            cred_usage, cred_store, &cred,
+                                            NULL, &time_rec);
+    } else if (cred_store == GSS_C_NO_CRED_STORE) {
+       status = mech->gss_acquire_cred(minor_status, internal_name, time_req,
+                                       GSS_C_NULL_OID_SET, cred_usage, &cred,
+                                       NULL, &time_rec);
+    } else {
+       return GSS_S_UNAVAILABLE;
+    }
 
     if (status != GSS_S_COMPLETE) {
        map_error(minor_status, mech);
index f7de1d613a9d374074f3107edbcd429014b6f7b0..a68a5878f4530b83bc7773be01618b4d11c00330 100644 (file)
 
 #include <mglueP.h>
 
+static OM_uint32
+store_cred_fallback(
+       OM_uint32 *minor_status,
+       gss_mechanism mech,
+       gss_cred_id_t mech_cred,
+       gss_cred_usage_t cred_usage,
+       gss_OID desired_mech,
+       OM_uint32 overwrite_cred,
+       OM_uint32 default_cred,
+       gss_const_key_value_set_t cred_store,
+       gss_OID_set *elements_stored,
+       gss_cred_usage_t *cred_usage_stored)
+{
+       if (mech->gss_store_cred_into != NULL) {
+               return mech->gss_store_cred_into(minor_status, mech_cred,
+                                                cred_usage, desired_mech,
+                                                overwrite_cred, default_cred,
+                                                cred_store, elements_stored,
+                                                cred_usage_stored);
+       } else if (cred_store == GSS_C_NO_CRED_STORE) {
+               return mech->gss_store_cred(minor_status, mech_cred,
+                                           cred_usage, desired_mech,
+                                           overwrite_cred, default_cred,
+                                           elements_stored,
+                                           cred_usage_stored);
+       } else {
+               return GSS_S_UNAVAILABLE;
+       }
+}
+
 static OM_uint32
 val_store_cred_args(
        OM_uint32 *minor_status,
@@ -19,6 +49,7 @@ val_store_cred_args(
        const gss_OID desired_mech,
        OM_uint32 overwrite_cred,
        OM_uint32 default_cred,
+       gss_const_key_value_set_t cred_store,
        gss_OID_set *elements_stored,
        gss_cred_usage_t *cred_usage_stored)
 {
@@ -49,6 +80,12 @@ val_store_cred_args(
            return GSS_S_FAILURE;
        }
 
+       if (cred_store != NULL && cred_store->count == 0) {
+               *minor_status = EINVAL;
+               map_errcode(minor_status);
+               return GSS_S_FAILURE;
+       }
+
        return (GSS_S_COMPLETE);
 }
 
@@ -72,6 +109,34 @@ OM_uint32            default_cred;
 gss_OID_set            *elements_stored;
 gss_cred_usage_t       *cred_usage_stored;
 
+{
+       return gss_store_cred_into(minor_status, input_cred_handle, cred_usage,
+                                  desired_mech, overwrite_cred, default_cred,
+                                  GSS_C_NO_CRED_STORE, elements_stored,
+                                  cred_usage_stored);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_store_cred_into(minor_status,
+                   input_cred_handle,
+                   cred_usage,
+                   desired_mech,
+                   overwrite_cred,
+                   default_cred,
+                   cred_store,
+                   elements_stored,
+                   cred_usage_stored)
+
+OM_uint32                       *minor_status;
+gss_cred_id_t                   input_cred_handle;
+gss_cred_usage_t                cred_usage;
+gss_OID                                 desired_mech;
+OM_uint32                       overwrite_cred;
+OM_uint32                       default_cred;
+gss_const_key_value_set_t       cred_store;
+gss_OID_set                     *elements_stored;
+gss_cred_usage_t                *cred_usage_stored;
+
 {
        OM_uint32               major_status = GSS_S_FAILURE;
        gss_union_cred_t        union_cred;
@@ -86,6 +151,7 @@ gss_cred_usage_t     *cred_usage_stored;
                                           desired_mech,
                                           overwrite_cred,
                                           default_cred,
+                                          cred_store,
                                           elements_stored,
                                           cred_usage_stored);
        if (major_status != GSS_S_COMPLETE)
@@ -105,22 +171,25 @@ gss_cred_usage_t  *cred_usage_stored;
                if (mech == NULL)
                        return (GSS_S_BAD_MECH);
 
-               if (mech->gss_store_cred == NULL)
+               if (mech->gss_store_cred_into == NULL &&
+                   cred_store != GSS_C_NO_CRED_STORE)
+                       return (major_status);
+
+               if (mech->gss_store_cred == NULL &&
+                   mech->gss_store_cred_into == NULL)
                        return (major_status);
 
                mech_cred = gssint_get_mechanism_cred(union_cred, desired_mech);
                if (mech_cred == GSS_C_NO_CREDENTIAL)
                        return (GSS_S_NO_CRED);
 
-               major_status = mech->gss_store_cred(
-                                                   minor_status,
-                                                   (gss_cred_id_t)mech_cred,
-                                                   cred_usage,
-                                                   desired_mech,
-                                                   overwrite_cred,
-                                                   default_cred,
-                                                   elements_stored,
-                                                   cred_usage_stored);
+               major_status = store_cred_fallback(minor_status, mech,
+                                                  mech_cred, cred_usage,
+                                                  desired_mech,
+                                                  overwrite_cred,
+                                                  default_cred, cred_store,
+                                                  elements_stored,
+                                                  cred_usage_stored);
                if (major_status != GSS_S_COMPLETE)
                    map_error(minor_status, mech);
                return major_status;
@@ -137,22 +206,23 @@ gss_cred_usage_t  *cred_usage_stored;
                if (mech == NULL)
                        continue;
 
-               if (mech->gss_store_cred == NULL)
+               if (mech->gss_store_cred_into == NULL &&
+                   cred_store != GSS_C_NO_CRED_STORE)
+                       continue;
+
+               if (mech->gss_store_cred == NULL &&
+                   mech->gss_store_cred_into == NULL)
                        continue;
 
                mech_cred = gssint_get_mechanism_cred(union_cred, dmech);
                if (mech_cred == GSS_C_NO_CREDENTIAL)
                        continue; /* can't happen, but safe to ignore */
 
-               major_status = mech->gss_store_cred(
-                                               minor_status,
-                                               (gss_cred_id_t)mech_cred,
-                                               cred_usage,
-                                               dmech,
-                                               overwrite_cred,
-                                               default_cred,
-                                               NULL,
-                                               cred_usage_stored);
+               major_status = store_cred_fallback(minor_status, mech,
+                                                  mech_cred, cred_usage,
+                                                  dmech, overwrite_cred,
+                                                  default_cred, cred_store,
+                                                  NULL, cred_usage_stored);
                if (major_status != GSS_S_COMPLETE) {
                    map_error(minor_status, mech);
                    continue;
index 577f5730855a61b2898dab99aec721c872dc128f..efbb370232f706876878253464ab0ecbe208a6ab 100644 (file)
@@ -605,6 +605,34 @@ typedef struct gss_config {
            gss_OID_set *               /* known_mech_attrs */
        /* */);
 
+       /* Credential store extensions */
+
+       OM_uint32       (KRB5_CALLCONV *gss_acquire_cred_from)
+       (
+           OM_uint32 *,                /* minor_status */
+           gss_name_t,                 /* desired_name */
+           OM_uint32,                  /* time_req */
+           gss_OID_set,                /* desired_mechs */
+           gss_cred_usage_t,           /* cred_usage */
+           gss_const_key_value_set_t,  /* cred_store */
+           gss_cred_id_t *,            /* output_cred_handle */
+           gss_OID_set *,              /* actual_mechs */
+           OM_uint32 *                 /* time_rec */
+       /* */);
+
+       OM_uint32       (KRB5_CALLCONV *gss_store_cred_into)
+       (
+           OM_uint32 *,                /* minor_status */
+           gss_cred_id_t,              /* input_cred_handle */
+           gss_cred_usage_t,           /* input_usage */
+           gss_OID,                    /* desired_mech */
+           OM_uint32,                  /* overwrite_cred */
+           OM_uint32,                  /* default_cred */
+           gss_const_key_value_set_t,  /* cred_store */
+           gss_OID_set *,              /* elements_stored */
+           gss_cred_usage_t *          /* cred_usage_stored */
+       /* */);
+
 } *gss_mechanism;
 
 /* This structure MUST NOT be used by any code outside libgss */