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);
}
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);
}
#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,
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;
}
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
OM_uint32 flags;
gss_name_t name;
gss_buffer_desc password;
+ gss_OID_set mechanisms;
time_t expiryTime;
};
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,
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);
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)
{
*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_ */
return GSS_S_FAILURE;
}
+ cred->expiryTime = ~0;
+
*pCred = cred;
*minor = 0;
{
OM_uint32 tmpMinor;
gss_cred_id_t cred = *pCred;
- krb5_context kerbCtx = NULL;
if (cred == GSS_C_NO_CREDENTIAL) {
return GSS_S_COMPLETE;
*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;
+}
* 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 */
}
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)
#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"
};
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;
+}