X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=util.h;h=ddf95a9d1686307b82423181d8759fb1c855d8f7;hp=bc88681753ccf4d1c6ffd1a5a54bceb0c888e2b0;hb=ae79fdae047f980d01b2b4e84ccea52e24d8c7a0;hpb=70b02ff081eff826695916c70e166b128769f4ca diff --git a/util.h b/util.h index bc88681..ddf95a9 100644 --- a/util.h +++ b/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, JANET(UK) + * Copyright (c) 2011, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,9 +54,14 @@ * */ +/* + * Utility functions. + */ + #ifndef _UTIL_H_ #define _UTIL_H_ 1 +#include #include #include @@ -66,31 +71,15 @@ extern "C" { #endif -#include "util_saml.h" -#include "util_radius.h" - -#define KRB_KEY_TYPE(key) ((key)->enctype) -#define KRB_KEY_DATA(key) ((key)->contents) -#define KRB_KEY_LENGTH(key) ((key)->length) -#define KRB_KEY_INIT(key) do { \ - KRB_KEY_TYPE(key) = ENCTYPE_NULL; \ - KRB_KEY_DATA(key) = NULL; \ - KRB_KEY_LENGTH(key) = 0; \ - } while (0) - -enum gss_eap_token_type { - TOK_TYPE_NONE = 0x0000, /* no token */ - TOK_TYPE_MIC = 0x0404, /* RFC 4121 MIC token */ - TOK_TYPE_WRAP = 0x0504, /* RFC 4121 wrap token */ - TOK_TYPE_EXPORT_NAME = 0x0401, /* RFC 2743 exported name */ - TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* draft-ietf-kitten-gss-naming */ - TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */ - TOK_TYPE_EAP_RESP = 0x0601, /* draft-howlett-eap-gss */ - TOK_TYPE_EAP_REQ = 0x0602, /* draft-howlett-eap-gss */ - TOK_TYPE_GSS_CB = 0x0603, /* draft-howlett-eap-gss */ -}; +#ifndef MIN +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif -#define EAP_EXPORT_CONTEXT_V1 1 +#if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define GSSEAP_UNUSED __attribute__ ((__unused__)) +#else +#define GSSEAP_UNUSED +#endif /* util_buffer.c */ OM_uint32 @@ -108,12 +97,34 @@ duplicateBuffer(OM_uint32 *minor, const gss_buffer_t src, gss_buffer_t dst); +static inline int +bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2) +{ + return (b1->length == b2->length && + memcmp(b1->value, b2->value, b2->length) == 0); +} + +static inline int +bufferEqualString(const gss_buffer_t b1, const char *s) +{ + gss_buffer_desc b2; + + b2.length = strlen(s); + b2.value = (char *)s; + + return bufferEqual(b1, &b2); +} + /* util_cksum.c */ int gssEapSign(krb5_context context, krb5_cksumtype type, size_t rrc, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto crypto, +#else krb5_keyblock *key, +#endif krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, int iov_count); @@ -121,8 +132,12 @@ gssEapSign(krb5_context context, int gssEapVerify(krb5_context context, krb5_cksumtype type, - size_t rrc, + size_t rrc, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto crypto, +#else krb5_keyblock *key, +#endif krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, int iov_count, @@ -136,6 +151,38 @@ gssEapEncodeGssChannelBindings(OM_uint32 *minor, #endif /* util_context.c */ +#define EAP_EXPORT_CONTEXT_V1 1 + +enum gss_eap_token_type { + TOK_TYPE_NONE = 0x0000, /* no token */ + TOK_TYPE_MIC = 0x0404, /* RFC 4121 MIC token */ + TOK_TYPE_WRAP = 0x0504, /* RFC 4121 wrap token */ + TOK_TYPE_EXPORT_NAME = 0x0401, /* RFC 2743 exported name */ + TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* exported composite name */ + TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */ + TOK_TYPE_INITIATOR_CONTEXT = 0x0601, /* initiator-sent context token */ + TOK_TYPE_ACCEPTOR_CONTEXT = 0x0602, /* acceptor-sent context token */ +}; + +/* inner token types and flags */ +#define ITOK_TYPE_NONE 0x00000000 +#define ITOK_TYPE_CONTEXT_ERR 0x00000001 /* critical */ +#define ITOK_TYPE_ACCEPTOR_NAME_REQ 0x00000002 /* TBD */ +#define ITOK_TYPE_ACCEPTOR_NAME_RESP 0x00000003 /* TBD */ +#define ITOK_TYPE_EAP_RESP 0x00000004 /* critical, required, if not reauth */ +#define ITOK_TYPE_EAP_REQ 0x00000005 /* critical, required, if not reauth */ +#define ITOK_TYPE_GSS_CHANNEL_BINDINGS 0x00000006 /* critical, required, if not reauth */ +#define ITOK_TYPE_REAUTH_CREDS 0x00000007 /* optional */ +#define ITOK_TYPE_REAUTH_REQ 0x00000008 /* optional */ +#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */ +#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */ +#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */ + +#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */ +#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */ + +#define ITOK_TYPE_MASK (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED)) + OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx); @@ -150,9 +197,20 @@ OM_uint32 gssEapVerifyToken(OM_uint32 *minor, gss_ctx_id_t ctx, const gss_buffer_t inputToken, - enum gss_eap_token_type tokenType, + enum gss_eap_token_type *tokenType, gss_buffer_t innerInputToken); +OM_uint32 +gssEapContextTime(OM_uint32 *minor, + gss_ctx_id_t context_handle, + OM_uint32 *time_rec); + +OM_uint32 +gssEapDisplayName(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type); + /* util_cred.c */ OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred); OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred); @@ -173,15 +231,27 @@ int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech); /* util_crypt.c */ int gssEapEncrypt(krb5_context context, int dce_style, size_t ec, - size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, + size_t rrc, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto crypto, +#else + krb5_keyblock *key, +#endif + int usage, gss_iov_buffer_desc *iov, int iov_count); int gssEapDecrypt(krb5_context context, int dce_style, size_t ec, - size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv, + size_t rrc, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto crypto, +#else + krb5_keyblock *key, +#endif + int usage, gss_iov_buffer_desc *iov, int iov_count); -krb5_cryptotype +int gssEapMapCryptoFlag(OM_uint32 type); gss_iov_buffer_t @@ -212,28 +282,142 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, krb5_keyblock *pKey); /* util_krb.c */ -OM_uint32 -gssEapKerberosInit(OM_uint32 *minor, krb5_context *context); +#ifdef HAVE_HEIMDAL_VERSION -OM_uint32 -rfc3961ChecksumTypeForKey(OM_uint32 *minor, - krb5_keyblock *key, - krb5_cksumtype *cksumtype); +#define KRB_TIME_FOREVER ((time_t)~0L) + +#define KRB_KEY_TYPE(key) ((key)->keytype) +#define KRB_KEY_DATA(key) ((key)->keyvalue.data) +#define KRB_KEY_LENGTH(key) ((key)->keyvalue.length) + +#define KRB_PRINC_LENGTH(princ) ((princ)->name.name_string.len) +#define KRB_PRINC_TYPE(princ) ((princ)->name.name_type) +#define KRB_PRINC_NAME(princ) ((princ)->name.name_string.val) +#define KRB_PRINC_REALM(princ) ((princ)->realm) + +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->keyblock) +#define KRB_KT_ENT_FREE(c, e) krb5_kt_free_entry((c), (e)) + +#define KRB_CRYPTO_CONTEXT(ctx) (krbCrypto) + +#else + +#define KRB_TIME_FOREVER KRB5_INT32_MAX + +#define KRB_KEY_TYPE(key) ((key)->enctype) +#define KRB_KEY_DATA(key) ((key)->contents) +#define KRB_KEY_LENGTH(key) ((key)->length) + +#define KRB_PRINC_LENGTH(princ) (krb5_princ_size(NULL, (princ))) +#define KRB_PRINC_TYPE(princ) (krb5_princ_type(NULL, (princ))) +#define KRB_PRINC_NAME(princ) (krb5_princ_name(NULL, (princ))) +#define KRB_PRINC_REALM(princ) (krb5_princ_realm(NULL, (princ))) + +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->key) +#define KRB_KT_ENT_FREE(c, e) krb5_free_keytab_entry_contents((c), (e)) + +#define KRB_CRYPTO_CONTEXT(ctx) (&(ctx)->rfc3961Key) + +#endif /* HAVE_HEIMDAL_VERSION */ + +#define KRB_KEY_INIT(key) do { \ + KRB_KEY_TYPE(key) = ENCTYPE_NULL; \ + KRB_KEY_DATA(key) = NULL; \ + KRB_KEY_LENGTH(key) = 0; \ + } while (0) #define GSSEAP_KRB_INIT(ctx) do { \ OM_uint32 tmpMajor; \ + \ tmpMajor = gssEapKerberosInit(minor, ctx); \ if (GSS_ERROR(tmpMajor)) { \ return tmpMajor; \ } \ } while (0) +OM_uint32 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context); + +OM_uint32 +rfc3961ChecksumTypeForKey(OM_uint32 *minor, + krb5_keyblock *key, + krb5_cksumtype *cksumtype); + +krb5_const_principal +krbAnonymousPrincipal(void); + +krb5_error_code +krbCryptoLength(krb5_context krbContext, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto, +#else + krb5_keyblock *key, +#endif + int type, + size_t *length); + +krb5_error_code +krbPaddingLength(krb5_context krbContext, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto, +#else + krb5_keyblock *key, +#endif + size_t dataLength, + size_t *padLength); + +krb5_error_code +krbBlockSize(krb5_context krbContext, +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto, +#else + krb5_keyblock *key, +#endif + size_t *blockSize); + +krb5_error_code +krbEnctypeToString(krb5_context krbContext, + krb5_enctype enctype, + const char *prefix, + gss_buffer_t string); + +krb5_error_code +krbMakeAuthDataKdcIssued(krb5_context context, + const krb5_keyblock *key, + krb5_const_principal issuer, +#ifdef HAVE_HEIMDAL_VERSION + const AuthorizationData *authdata, + AuthorizationData *adKdcIssued +#else + krb5_authdata *const *authdata, + krb5_authdata ***adKdcIssued +#endif + ); + +krb5_error_code +krbMakeCred(krb5_context context, + krb5_auth_context authcontext, + krb5_creds *creds, + krb5_data *data); + +/* util_lucid.c */ +OM_uint32 +gssEapExportLucidSecContext(OM_uint32 *minor, + gss_ctx_id_t ctx, + const gss_OID desiredObject, + gss_buffer_set_t *data_set); + /* util_mech.c */ +extern gss_OID GSS_EAP_MECHANISM; + int gssEapInternalizeOid(const gss_OID oid, gss_OID *const pInternalizedOid); OM_uint32 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid); + +OM_uint32 gssEapDefaultMech(OM_uint32 *minor, gss_OID *oid); @@ -261,46 +445,44 @@ OM_uint32 gssEapValidateMechs(OM_uint32 *minor, const gss_OID_set mechs); +gss_buffer_t +gssEapOidToSaslName(const gss_OID oid); + +gss_OID +gssEapSaslNameToOid(const gss_buffer_t name); + /* util_name.c */ -enum gss_eap_attribute_type { - ATTR_TYPE_NONE = 0, - ATTR_TYPE_SAML_AAA_ASSERTION = 1, - ATTR_TYPE_SAML_ATTR = 2, - ATTR_TYPE_RADIUS_AVP = 3 -}; +#define EXPORT_NAME_FLAG_OID 0x1 +#define EXPORT_NAME_FLAG_COMPOSITE 0x2 OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName); OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName); OM_uint32 gssEapExportName(OM_uint32 *minor, const gss_name_t name, - gss_buffer_t exportedName, - int composite); + gss_buffer_t exportedName); +OM_uint32 gssEapExportNameInternal(OM_uint32 *minor, + const gss_name_t name, + gss_buffer_t exportedName, + unsigned int flags); OM_uint32 gssEapImportName(OM_uint32 *minor, const gss_buffer_t input_name_buffer, gss_OID input_name_type, gss_name_t *output_name); - -enum gss_eap_attribute_type -gssEapAttributePrefixToType(const gss_buffer_t prefix); -gss_buffer_t -gssEapAttributeTypeToPrefix(enum gss_eap_attribute_type type); +OM_uint32 gssEapImportNameInternal(OM_uint32 *minor, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name, + unsigned int flags); OM_uint32 -decomposeAttributeName(OM_uint32 *minor, - const gss_buffer_t attribute, - gss_buffer_t prefix, - gss_buffer_t suffix); -OM_uint32 -composeAttributeName(OM_uint32 *minor, - const gss_buffer_t prefix, - const gss_buffer_t suffix, - gss_buffer_t attribute); +gssEapDuplicateName(OM_uint32 *minor, + const gss_name_t input_name, + gss_name_t *dest_name); /* util_oid.c */ OM_uint32 composeOid(OM_uint32 *minor_status, const char *prefix, size_t prefix_len, - int suffix, + int suffix, gss_OID_desc *oid); OM_uint32 @@ -333,26 +515,114 @@ oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2) } /* util_ordering.c */ -int -sequenceInternalize(void **vqueue, unsigned char **buf, size_t *lenremain); +OM_uint32 +sequenceInternalize(OM_uint32 *minor, + void **vqueue, + unsigned char **buf, + size_t *lenremain); -int -sequenceExternalize(void *vqueue, unsigned char **buf, size_t *lenremain); +OM_uint32 +sequenceExternalize(OM_uint32 *minor, + void *vqueue, + unsigned char **buf, + size_t *lenremain); size_t sequenceSize(void *vqueue); -void -sequenceFree(void **vqueue); +OM_uint32 +sequenceFree(OM_uint32 *minor, void **vqueue); -int -sequenceCheck(void **vqueue, uint64_t seqnum); +OM_uint32 +sequenceCheck(OM_uint32 *minor, void **vqueue, uint64_t seqnum); -int -sequenceInit(void **vqueue, uint64_t seqnum, +OM_uint32 +sequenceInit(OM_uint32 *minor, void **vqueue, uint64_t seqnum, int do_replay, int do_sequence, int wide_nums); +/* util_sm.c */ +enum gss_eap_state { + GSSEAP_STATE_INITIAL = 0x01, /* initial state */ + GSSEAP_STATE_AUTHENTICATE = 0x02, /* exchange EAP messages */ + GSSEAP_STATE_INITIATOR_EXTS = 0x04, /* initiator extensions */ + GSSEAP_STATE_ACCEPTOR_EXTS = 0x08, /* acceptor extensions */ +#ifdef GSSEAP_ENABLE_REAUTH + GSSEAP_STATE_REAUTHENTICATE = 0x10, /* GSS reauthentication messages */ +#endif + GSSEAP_STATE_ESTABLISHED = 0x20, /* context established */ + GSSEAP_STATE_ALL = 0x3F +}; + +#define GSSEAP_STATE_NEXT(s) ((s) << 1) + +#define GSSEAP_SM_STATE(ctx) ((ctx)->state) + +#ifdef GSSEAP_DEBUG +void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state); +#define GSSEAP_SM_TRANSITION(ctx, state) gssEapSmTransition((ctx), (state)) +#else +#define GSSEAP_SM_TRANSITION(ctx, newstate) do { (ctx)->state = (newstate); } while (0) +#endif + +#define GSSEAP_SM_TRANSITION_NEXT(ctx) GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT(GSSEAP_SM_STATE((ctx)))) + +/* state machine entry */ +struct gss_eap_sm { + OM_uint32 inputTokenType; + OM_uint32 outputTokenType; + enum gss_eap_state validStates; + OM_uint32 itokFlags; + OM_uint32 (*processToken)(OM_uint32 *, + gss_cred_id_t, + gss_ctx_id_t, + gss_name_t, + gss_OID, + OM_uint32, + OM_uint32, + gss_channel_bindings_t, + gss_buffer_t, + gss_buffer_t, + OM_uint32 *); +}; + +/* state machine flags, set by handler */ +#define SM_FLAG_FORCE_SEND_TOKEN 0x00000001 /* send token even if no inner tokens */ +#define SM_FLAG_OUTPUT_TOKEN_CRITICAL 0x00000002 /* output token is critical */ + +/* state machine flags, set by state machine */ +#define SM_FLAG_INPUT_TOKEN_CRITICAL 0x10000000 /* input token was critical */ + +#define SM_ITOK_FLAG_REQUIRED 0x00000001 /* received tokens must be present */ + +OM_uint32 +gssEapSmStep(OM_uint32 *minor, + gss_cred_id_t cred, + gss_ctx_id_t ctx, + gss_name_t target, + gss_OID mech, + OM_uint32 reqFlags, + OM_uint32 timeReq, + gss_channel_bindings_t chanBindings, + gss_buffer_t inputToken, + gss_buffer_t outputToken, + struct gss_eap_sm *sm, + size_t smCount); + +void +gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state); + /* util_token.c */ +OM_uint32 +gssEapEncodeInnerTokens(OM_uint32 *minor, + gss_buffer_set_t extensions, + OM_uint32 *types, + gss_buffer_t buffer); +OM_uint32 +gssEapDecodeInnerTokens(OM_uint32 *minor, + const gss_buffer_t buffer, + gss_buffer_set_t *pExtensions, + OM_uint32 **pTypes); + size_t tokenSize(const gss_OID_desc *mech, size_t body_size); @@ -368,13 +638,14 @@ verifyTokenHeader(OM_uint32 *minor, size_t *body_size, unsigned char **buf_in, size_t toksize_in, - enum gss_eap_token_type tok_type); + enum gss_eap_token_type *ret_tok_type); /* Helper macros */ -#define GSSEAP_CALLOC(count, size) (calloc((count), (size))) -#define GSSEAP_FREE(ptr) (free((ptr))) -#define GSSEAP_MALLOC(size) (malloc((size))) -#define GSSEAP_REALLOC(ptr, size) (realloc((ptr), (size))) + +#define GSSEAP_CALLOC calloc +#define GSSEAP_MALLOC malloc +#define GSSEAP_FREE free +#define GSSEAP_REALLOC realloc #define GSSEAP_NOT_IMPLEMENTED do { \ assert(0 && "not implemented"); \ @@ -512,8 +783,51 @@ store_oid(gss_OID oid, void *vp) return store_buffer(&buf, vp, FALSE); } +static inline void +krbDataToGssBuffer(krb5_data *data, gss_buffer_t buffer) +{ + buffer->value = (void *)data->data; + buffer->length = data->length; +} + +static inline void +krbPrincComponentToGssBuffer(krb5_principal krbPrinc, + int index, gss_buffer_t buffer) +{ +#ifdef HAVE_HEIMDAL_VERSION + buffer->value = (void *)KRB_PRINC_NAME(krbPrinc)[index]; + buffer->length = strlen((char *)buffer->value); +#else + buffer->value = (void *)krb5_princ_component(NULL, krbPrinc, index)->data; + buffer->length = krb5_princ_component(NULL, krbPrinc, index)->length; +#endif /* HAVE_HEIMDAL_VERSION */ +} + +static inline void +krbPrincRealmToGssBuffer(krb5_principal krbPrinc, gss_buffer_t buffer) +{ +#ifdef HAVE_HEIMDAL_VERSION + buffer->value = (void *)KRB_PRINC_REALM(krbPrinc); + buffer->length = strlen((char *)buffer->value); +#else + krbDataToGssBuffer(KRB_PRINC_REALM(krbPrinc), buffer); +#endif +} + +static inline void +gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data) +{ + data->data = (char *)buffer->value; + data->length = buffer->length; +} + #ifdef __cplusplus } #endif +#include "util_attr.h" +#ifdef GSSEAP_ENABLE_REAUTH +#include "util_reauth.h" +#endif + #endif /* _UTIL_H_ */