Subject: [kitten] Proposed GSS extension for explicit credential stores

From: Nico Williams <[email-masked]>
Date: Mon, 2 Apr 2012 23:56:42 -0500

Simo and I have a need for extensions for acquiring credentials from,
and storing credentials into, an explicit credential store as opposed
to the one implied by process credentials/context/environment.

For some use cases it is possible to get by without this extension by
just forking/spawning processes that can change their process
credentials and/or environment variables to change their implicit
credential store.  I understand that this argument will come up.  But
this is not a great solution for us.  Particularly since it is not a
portable and generic solution.  The solution we propose will still
involve some elements that are not entirely generic or portable, but
these elements are abstracted into key/value pairs that are easily
configured, thus the resulting applications themselves should be
generic and portable.

The new functions are:

 - GSS_Acquire_cred_from()
 - GSS_Add_cred_from()
 - GSS_Store_cred_into()

These are just like the existing functions that they are based on, but
with one additional argument: a credential store.

The credential store is just an ordered set of key/value pairs where
the keys are URNs (as opposed to OIDs) and the values are octet
strings with formats given by the keys.  In the C bindings the
credential store looks like this:

typedef struct gss_cred_store_element_struct {
   const char *urn;
   const char *value;
} gss_cred_store_element, *gss_cred_store_element_t;
typedef const struct gss_cred_store_element *gss_const_cred_store_element_t;

typedef struct gss_cred_store_struct {
   OM_uint32 count;
   gss_const_cred_store_element_t *elements;
} gss_cred_store, *gss_cred_store_t;
typedef const struct gss_cred_store_struct *gss_const_cred_store_t;

Note the use of the C const keyword.

The abstract API representation of this would probably be

    SET OF SEQUENCE {
        element_type_urn OCTET STRING,
        element OCTET STRING
    }

or perhaps just "CREDENTIAL STORE".  Note that RFC2743 has types with
that much structure, namely: OID sets, or at least the C bindings of
OID SET have that much structure.

URNs will be provided for at least the following:

 - ccache values
  Values will be of the form [<TYPE>:]<ccache-path-or-id>, such as
the familiar "FILE:/tmp/somecc" but also "LSA:" and "CCAPI:...".

 - keytab values
  Same as with ccache values, but naming a keytab.

We'll probably provide URNs for other store element types, such as:

 - PKCS#11 URI
   See http://tools.ietf.org/html/draft-pechanec-pkcs11uri-06

We have debated, but not reached a conclusion, other possible element
types such as:

 - User-ID, username

 - AFS PAG

The complete C bindings would be:

+/* Extension for credential stores */
+typedef struct gss_cred_store_element_struct {
+    const char *urn;
+    const char *value;
+} gss_cred_store_element, *gss_cred_store_element_t;
+typedef const struct gss_cred_store_element *gss_const_cred_store_element_t;
+
+typedef struct gss_cred_store_struct {
+    OM_uint32 count;
+    gss_const_cred_store_element_t *elements;
+} gss_cred_store, *gss_cred_store_t;
+typedef const struct gss_cred_store_struct *gss_const_cred_store_t;

+#define GSS_C_NO_CRED_STORE ((gss_const_cred_store_t) 0)

+OM_uint32 gss_acquire_cred_from(
+            OM_uint32 *minor_status*,
+            const gss_name_t desired_name,
+            OM_uint32 time_req,
+            const gss_OID_set desired_mechs,
+            gss_cred_usage_t cred_usage,
+            gss_const_cred_store_t cred_store,
+            gss_cred_id_t *output_cred_handle,
+            gss_OID_set *actual_mechs,
+            OM_uint32 *time_rec);

+OM_uint32 gss_add_cred_from (
+            OM_uint32 *minor_status,
+            const gss_cred_id_t input_cred_handle,
+            const gss_name_t desired_name,
+            const gss_OID desired_mech,
+            gss_cred_usage_t cred_usage,
+            OM_uint32 initiator_time_req,
+            OM_uint32 acceptor_time_req,
+            gss_const_cred_store_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 gss_store_cred_into(
+              OM_uint32         *minor_status,
+              gss_cred_id_t     input_cred_handle,
+              gss_cred_usage_t  cred_usage,
+              const gss_OID     desired_mech,
+              OM_uint32         overwrite_cred,
+              OM_uint32         default_cred,
+              gss_const_cred_store_t cred_store,
+              gss_OID_set       *elements_stored,
+              gss_cred_usage_t  *cred_usage_stored);

Comments?

Nico
--

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 03 Apr 2012 14:28:52 +0200

> to the one implied by process credentials/context/environment.

I have often needed this too.

>         element_type_urn OCTET STRING,

It seems nice, but I haven't digested it fully yet.

> We have debated, but not reached a conclusion, other possible element

I'd really like to see SAML SP metadata included here initially, and
would be willing to help with writing.  For simplicity, you could have
multiple URns here, right?  I'm thinking something like this:

 urn.ietf.kitten.saml.sp.metadata-file =>
 "/etc/myapp/sp-metadata.xml"

 urn.ietf.kitten.saml.sp.key-file =>
 "/etc/myapp/sp-key.pem"

 urn.ietf.kitten.saml.sp.cert-file =>
 "/etc/myapp/sp-cert.pem"

 urn.ietf.kitten.saml.sp.metadata =>
 "<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ..."

 urn.ietf.kitten.saml.sp.cert =>
 "-----BEGIN CERTIFICATE -----\nMII..."

Alternatively, there could be a "struct" approach for SAML SP
credentials if you wanted to use only one URN for each credential,
however it gets a bit more ugly:

 urn.ietf.kitten.saml.sp =>
 "metadata_file=/etc/myapp/sp-metadata.xml, key_file=/etc/myapp/sp-key.pem, ..."

Thoughts?

/Simon

---

From: Simo Sorce <[email-masked]>
Date: Tue, 03 Apr 2012 09:46:45 -0400

>  "metadata_file=/etc/myapp/sp-metadata.xml, key_file=/etc/myapp/sp-key.pem, ..."

Although values are opaque a rule we try to follow is to not put
credentials directly in there, but always use files and paths for
anything that is longer that a few hundred characters or unprintable.

These strings are supposed to be stored in configuration files, and we
do not want to force admins in a corner by requiring to set credentials
in a config file that also needs to be readable to users that shouldn't
have access to some of the credentials.

This should be the guiding principle in defining the values.

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York

---

From: Nico Williams <[email-masked]>
Date: Tue, 3 Apr 2012 09:35:00 -0500

> multiple URns here, right?  I'm thinking something like this:

Yes, you can have multiple key/value pairs, and the keys are URNs.
And you can have multiple key/value pairs with the same key, so I
think we need to make the abstract type be SEQUENCE OF SEQUENCE { ...
}.

>  "/etc/myapp/sp-metadata.xml"

Sure.

>  urn.ietf.kitten.saml.sp.key-file =>

Sure.

>  urn.ietf.kitten.saml.sp.cert-file =>

Sure.

>  "<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ..."

Sure.

>  "-----BEGIN CERTIFICATE -----\nMII..."

To repeat what Simo said, we shouldn't put secrets (and I know, a cert
is not a secret, but the private key to go with it is) in
configuration files.  Secrets should go in separate files or HSMs.

> however it gets a bit more ugly:

We want multiple key/value pairs, not just one.

For example, it'd make sense to specify both, a keytab and a ccache,
but we want separate key/value pairs for keytab and ccache.  It also
makes sense to specify multiple keytabs.

>  "metadata_file=/etc/myapp/sp-metadata.xml, key_file=/etc/myapp/sp-key.pem, ..."

Sure.

Nico
--