/*
- * Copyright (c) 2010, JANET(UK)
+ * Copyright (c) 2011, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
*/
+/*
+ * Utility functions.
+ */
+
#ifndef _UTIL_H_
#define _UTIL_H_ 1
-/* Helper APIs */
+#include <sys/param.h>
+#include <string.h>
+#include <errno.h>
+
+#include <krb5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MIN
+#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
+#endif
+
+#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
+makeStringBuffer(OM_uint32 *minor,
+ const char *string,
+ gss_buffer_t buffer);
+
+OM_uint32
+bufferToString(OM_uint32 *minor,
+ const gss_buffer_t buffer,
+ char **pString);
+
+OM_uint32
+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);
+
+int
+gssEapVerify(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,
+ int *valid);
+
+#if 0
+OM_uint32
+gssEapEncodeGssChannelBindings(OM_uint32 *minor,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t encodedBindings);
+#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);
-OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
-OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
-
+OM_uint32
+gssEapMakeToken(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t innerToken,
+ enum gss_eap_token_type tokenType,
+ gss_buffer_t outputToken);
+
+OM_uint32
+gssEapVerifyToken(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t inputToken,
+ 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);
+
+/* 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);
-/* Kerberos token services */
-#define KRB_KEYTYPE(key) ((key)->enctype)
+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);
+
+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
int
gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
-/* util_cksum.c */
-int
-gssEapSign(krb5_context context,
- krb5_cksumtype type,
- size_t rrc,
- krb5_keyblock *key,
- krb5_keyusage sign_usage,
- gss_iov_buffer_desc *iov,
- int iov_count);
+OM_uint32
+gssEapDeriveRfc3961Key(OM_uint32 *minor,
+ const unsigned char *key,
+ size_t keyLength,
+ krb5_enctype enctype,
+ krb5_keyblock *pKey);
-int
-gssEapVerify(krb5_context context,
- krb5_cksumtype type,
- size_t rrc,
- krb5_keyblock *key,
- krb5_keyusage sign_usage,
- gss_iov_buffer_desc *iov,
- int iov_count,
- int *valid);
+/* util_krb.c */
+#ifdef HAVE_HEIMDAL_VERSION
-/* util_ordering.c */
-int
-sequenceInternalize(void **vqueue, unsigned char **buf, size_t *lenremain);
+#define KRB_TIME_FOREVER ((time_t)~0L)
-int
-sequenceExternalize(void *vqueue, unsigned char **buf, size_t *lenremain);
+#define KRB_KEY_TYPE(key) ((key)->keytype)
+#define KRB_KEY_DATA(key) ((key)->keyvalue.data)
+#define KRB_KEY_LENGTH(key) ((key)->keyvalue.length)
-int
-sequenceSize(void *vqueue, size_t *sizep);
+#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)
-void
-sequenceFree(void **vqueue);
+#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_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;
+
+#define OID_FLAG_NULL_VALID 0x00000001
+#define OID_FLAG_FAMILY_MECH_VALID 0x00000002
+#define OID_FLAG_MAP_NULL_TO_DEFAULT_MECH 0x00000004
+#define OID_FLAG_MAP_FAMILY_MECH_TO_NULL 0x00000008
+
+OM_uint32
+gssEapCanonicalizeOid(OM_uint32 *minor,
+ const gss_OID oid,
+ OM_uint32 flags,
+ gss_OID *pOid);
+
+OM_uint32
+gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid);
+
+OM_uint32
+gssEapDefaultMech(OM_uint32 *minor,
+ gss_OID *oid);
+
+OM_uint32
+gssEapIndicateMechs(OM_uint32 *minor,
+ gss_OID_set *mechs);
+
+OM_uint32
+gssEapEnctypeToOid(OM_uint32 *minor,
+ krb5_enctype enctype,
+ gss_OID *pOid);
+
+OM_uint32
+gssEapOidToEnctype(OM_uint32 *minor,
+ const gss_OID oid,
+ krb5_enctype *enctype);
int
-sequenceCheck(void **vqueue, uint64_t seqnum);
+gssEapIsMechanismOid(const gss_OID oid);
int
-sequenceInit(void **vqueue, uint64_t seqnum,
+gssEapIsConcreteMechanismOid(const gss_OID oid);
+
+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 */
+#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);
+OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
+ const gss_name_t name,
+ gss_buffer_t exportedName,
+ OM_uint32 flags);
+OM_uint32 gssEapImportName(OM_uint32 *minor,
+ const gss_buffer_t input_name_buffer,
+ const gss_OID input_name_type,
+ const gss_OID input_mech_type,
+ gss_name_t *output_name);
+OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
+ const gss_buffer_t input_name_buffer,
+ gss_name_t *output_name,
+ OM_uint32 flags);
+OM_uint32
+gssEapDuplicateName(OM_uint32 *minor,
+ const gss_name_t input_name,
+ gss_name_t *dest_name);
+
+OM_uint32
+gssEapCanonicalizeName(OM_uint32 *minor,
+ const gss_name_t input_name,
+ const gss_OID mech_type,
+ gss_name_t *dest_name);
+
+OM_uint32
+gssEapDisplayName(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t output_name_buffer,
+ gss_OID *output_name_type);
+
+OM_uint32
+gssEapCompareName(OM_uint32 *minor,
+ gss_name_t name1,
+ gss_name_t name2,
+ int *name_equal);
+
+/* util_oid.c */
+OM_uint32
+composeOid(OM_uint32 *minor_status,
+ const char *prefix,
+ size_t prefix_len,
+ int suffix,
+ gss_OID_desc *oid);
+
+OM_uint32
+decomposeOid(OM_uint32 *minor_status,
+ const char *prefix,
+ size_t prefix_len,
+ gss_OID_desc *oid,
+ int *suffix) ;
+
+OM_uint32
+duplicateOid(OM_uint32 *minor_status,
+ const gss_OID_desc * const oid,
+ gss_OID *new_oid);
+
+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)
+{
+ if (o1 == GSS_C_NO_OID)
+ return (o2 == GSS_C_NO_OID);
+ else if (o2 == GSS_C_NO_OID)
+ return (o1 == GSS_C_NO_OID);
+ else
+ return (o1->length == o2->length &&
+ memcmp(o1->elements, o2->elements, o1->length) == 0);
+}
+
+/* util_ordering.c */
+OM_uint32
+sequenceInternalize(OM_uint32 *minor,
+ 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);
+
+OM_uint32
+sequenceFree(OM_uint32 *minor, void **vqueue);
+
+OM_uint32
+sequenceCheck(OM_uint32 *minor, 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);
+void
+makeTokenHeader(const gss_OID_desc *mech,
+ size_t body_size,
+ unsigned char **buf,
+ enum gss_eap_token_type tok_type);
+
+OM_uint32
+verifyTokenHeader(OM_uint32 *minor,
+ gss_OID mech,
+ size_t *body_size,
+ unsigned char **buf_in,
+ size_t toksize_in,
+ 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"); \
return GSS_S_FAILURE; \
} while (0)
+#include <pthread.h>
+
+#define GSSEAP_MUTEX pthread_mutex_t
+#define GSSEAP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define GSSEAP_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
+#define GSSEAP_MUTEX_DESTROY(m) pthread_mutex_destroy((m))
+#define GSSEAP_MUTEX_LOCK(m) pthread_mutex_lock((m))
+#define GSSEAP_MUTEX_UNLOCK(m) pthread_mutex_unlock((m))
+
+#define GSSEAP_THREAD_KEY pthread_key_t
+#define GSSEAP_KEY_CREATE(k, d) pthread_key_create((k), (d))
+#define GSSEAP_GETSPECIFIC(k) pthread_getspecific((k))
+#define GSSEAP_SETSPECIFIC(k, d) pthread_setspecific((k), (d))
+
+#define GSSEAP_THREAD_ONCE pthread_once_t
+#define GSSEAP_ONCE(o, i) pthread_once((o), (i))
+#define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT
+
/* Helper functions */
static inline void
store_uint16_be(uint16_t val, void *vp)
return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4);
}
-static inline int
-oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2)
+static inline unsigned char *
+store_buffer(gss_buffer_t buffer, void *vp, int wide_nums)
+{
+ unsigned char *p = (unsigned char *)vp;
+
+ if (wide_nums) {
+ store_uint64_be(buffer->length, p);
+ p += 8;
+ } else {
+ store_uint32_be(buffer->length, p);
+ p += 4;
+ }
+
+ if (buffer->value != NULL) {
+ memcpy(p, buffer->value, buffer->length);
+ p += buffer->length;
+ }
+
+ return p;
+}
+
+static inline unsigned char *
+load_buffer(const void *cvp, size_t length, gss_buffer_t buffer)
{
- return (o1->length == o2->length &&
- memcmp(o1->elements, o2->elements, o1->length) == 0);
+ buffer->length = 0;
+ buffer->value = GSSEAP_MALLOC(length);
+ if (buffer->value == NULL)
+ return NULL;
+ buffer->length = length;
+ memcpy(buffer->value, cvp, length);
+ return (unsigned char *)cvp + length;
+}
+
+static inline unsigned char *
+store_oid(gss_OID oid, void *vp)
+{
+ gss_buffer_desc buf;
+
+ if (oid != GSS_C_NO_OID) {
+ buf.length = oid->length;
+ buf.value = oid->elements;
+ } else {
+ buf.length = 0;
+ buf.value = NULL;
+ }
+
+ 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_json.h"
+#include "util_attr.h"
+#include "util_base64.h"
+#ifdef GSSEAP_ENABLE_REAUTH
+#include "util_reauth.h"
+#endif
#endif /* _UTIL_H_ */