From 90add3365b3e4f893bc6665932b28da8a5650fbb Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Wed, 8 Sep 2010 19:34:03 +0200 Subject: [PATCH] More work on creds --- mech_eap/acquire_cred.c | 4 +- mech_eap/acquire_cred_with_password.c | 4 +- mech_eap/add_cred.c | 35 ++++++++++++++- mech_eap/gssapiP_eap.h | 5 ++- mech_eap/util.h | 47 ++++++++++++++++++++ mech_eap/util_cred.c | 82 ++++++++++++++++++++++++++++++++++- mech_eap/util_mech.c | 26 ++++++++++- mech_eap/util_name.c | 2 +- mech_eap/util_oid.c | 31 +++++++++++++ 9 files changed, 227 insertions(+), 9 deletions(-) diff --git a/mech_eap/acquire_cred.c b/mech_eap/acquire_cred.c index 0bb1f1f..c85966e 100644 --- a/mech_eap/acquire_cred.c +++ b/mech_eap/acquire_cred.c @@ -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); } diff --git a/mech_eap/acquire_cred_with_password.c b/mech_eap/acquire_cred_with_password.c index 776ecba..e56419e 100644 --- a/mech_eap/acquire_cred_with_password.c +++ b/mech_eap/acquire_cred_with_password.c @@ -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); } diff --git a/mech_eap/add_cred.c b/mech_eap/add_cred.c index 80b4b24..0332150 100644 --- a/mech_eap/add_cred.c +++ b/mech_eap/add_cred.c @@ -32,6 +32,11 @@ #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; } diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h index 92cadac..267235a 100644 --- a/mech_eap/gssapiP_eap.h +++ b/mech_eap/gssapiP_eap.h @@ -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_INITIATE 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; }; diff --git a/mech_eap/util.h b/mech_eap/util.h index cdcabd3..1495857 100644 --- a/mech_eap/util.h +++ b/mech_eap/util.h @@ -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_ */ diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c index 08ede79..984ebac 100644 --- a/mech_eap/util_cred.c +++ b/mech_eap/util_cred.c @@ -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; +} diff --git a/mech_eap/util_mech.c b/mech_eap/util_mech.c index 745108f..be83f5e 100644 --- a/mech_eap/util_mech.c +++ b/mech_eap/util_mech.c @@ -47,12 +47,12 @@ * 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) diff --git a/mech_eap/util_name.c b/mech_eap/util_name.c index cc00c42..9f0e219 100644 --- a/mech_eap/util_name.c +++ b/mech_eap/util_name.c @@ -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" }; diff --git a/mech_eap/util_oid.c b/mech_eap/util_oid.c index 34b7c7b..14b5f3b 100644 --- a/mech_eap/util_oid.c +++ b/mech_eap/util_oid.c @@ -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; +} -- 2.1.4