return GSS_S_FAILURE;
}
- if (cred->radiusConfigFile != NULL)
- configFile = cred->radiusConfigFile;
- if (cred->radiusConfigStanza != NULL)
- configStanza = cred->radiusConfigStanza;
+ if (cred->radiusConfigFile.value != NULL)
+ configFile = (const char *)cred->radiusConfigFile.value;
+ if (cred->radiusConfigStanza.value != NULL)
+ configStanza = (const char *)cred->radiusConfigStanza.value;
ralloc.calloc = GSSEAP_CALLOC;
ralloc.malloc = GSSEAP_MALLOC;
}
static OM_uint32
+eapGssSmAcceptGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char *p;
+ OM_uint32 initiatorGssFlags;
+
+ assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
+
+ if (inputToken->length < 4) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ /* allow flags to grow for future expansion */
+ p = (unsigned char *)inputToken->value + inputToken->length - 4;
+
+ initiatorGssFlags = load_uint32_be(p);
+ initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
+
+ ctx->gssFlags |= initiatorGssFlags;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_buffer_t outputToken GSSEAP_UNUSED,
OM_uint32 *smFlags GSSEAP_UNUSED)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
gss_iov_buffer_desc iov[2];
iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
iov[0].buffer.length = 0;
iov[0].buffer.value = NULL;
- iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM;
- iov[1].buffer = *inputToken;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED;
+
+ /* XXX necessary because decrypted in place and we verify it later */
+ major = duplicateBuffer(minor, inputToken, &iov[1].buffer);
+ if (GSS_ERROR(major))
+ return major;
major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
iov, 2, TOK_TYPE_WRAP);
- if (GSS_ERROR(major))
+ if (GSS_ERROR(major)) {
+ gssEapReleaseIov(iov, 2);
return major;
+ }
if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
!bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
*minor = 0;
}
- gss_release_buffer(&tmpMinor, &iov[0].buffer);
+ gssEapReleaseIov(iov, 2);
return major;
}
+static OM_uint32
+eapGssSmAcceptInitiatorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ OM_uint32 major;
+
+ major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ GSSEAP_SM_TRANSITION_NEXT(ctx);
+
+ *minor = 0;
+ return GSS_S_CONTINUE_NEEDED;
+}
+
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
eapGssSmAcceptReauthCreds(OM_uint32 *minor,
#endif
static OM_uint32
-eapGssSmAcceptCompleteInitiatorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags GSSEAP_UNUSED)
+eapGssSmAcceptAcceptorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags)
{
- GSSEAP_SM_TRANSITION_NEXT(ctx);
-
- *minor = 0;
+ OM_uint32 major;
- return GSS_S_CONTINUE_NEEDED;
-}
+ major = gssEapMakeTokenMIC(minor, ctx, outputToken);
+ if (GSS_ERROR(major))
+ return major;
-static OM_uint32
-eapGssSmAcceptCompleteAcceptorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags)
-{
GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
*minor = 0;
- *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
+ *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
return GSS_S_COMPLETE;
}
eapGssSmAcceptAuthenticate
},
{
+ ITOK_TYPE_GSS_FLAGS,
+ ITOK_TYPE_NONE,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmAcceptGssFlags
+ },
+ {
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
ITOK_TYPE_NONE,
GSSEAP_STATE_INITIATOR_EXTS,
eapGssSmAcceptGssChannelBindings,
},
{
- ITOK_TYPE_NONE,
+ ITOK_TYPE_INITIATOR_MIC,
ITOK_TYPE_NONE,
GSSEAP_STATE_INITIATOR_EXTS,
- 0,
- eapGssSmAcceptCompleteInitiatorExts,
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmAcceptInitiatorMIC,
},
#ifdef GSSEAP_ENABLE_REAUTH
{
#endif
{
ITOK_TYPE_NONE,
- ITOK_TYPE_NONE,
+ ITOK_TYPE_ACCEPTOR_MIC,
GSSEAP_STATE_ACCEPTOR_EXTS,
0,
- eapGssSmAcceptCompleteAcceptorExts
+ eapGssSmAcceptAcceptorMIC
},
};
GSSEAP_MUTEX_LOCK(&ctx->mutex);
if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
major = gssEapAcquireCred(minor,
GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
GSS_C_INDEFINITE,
GSS_C_NO_OID_SET,
GSS_C_ACCEPT,
- &ctx->defaultCred,
+ &ctx->cred,
NULL,
NULL);
if (GSS_ERROR(major))
goto cleanup;
}
- cred = ctx->defaultCred;
+ cred = ctx->cred;
}
GSSEAP_MUTEX_LOCK(&cred->mutex);
- if (cred->name != GSS_C_NO_NAME) {
- major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ /*
+ * Calling gssEapInquireCred() forces the default acceptor credential name
+ * to be resolved.
+ */
+ major = gssEapInquireCred(minor, cred, &ctx->acceptorName, NULL, NULL, NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
major = gssEapSmStep(minor,
cred,
#define CRED_FLAG_INITIATE 0x00010000
#define CRED_FLAG_ACCEPT 0x00020000
- #define CRED_FLAG_DEFAULT_IDENTITY 0x00040000
- #define CRED_FLAG_PASSWORD 0x00080000
- #define CRED_FLAG_DEFAULT_CCACHE 0x00100000
+ #define CRED_FLAG_PASSWORD 0x00040000
+ #define CRED_FLAG_DEFAULT_CCACHE 0x00080000
+ #define CRED_FLAG_RESOLVED 0x00100000
#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
#ifdef HAVE_HEIMDAL_VERSION
GSSEAP_MUTEX mutex;
OM_uint32 flags;
gss_name_t name;
+ gss_name_t target; /* for initiator */
gss_buffer_desc password;
gss_OID_set mechanisms;
time_t expiryTime;
- char *radiusConfigFile;
- char *radiusConfigStanza;
+ gss_buffer_desc radiusConfigFile;
+ gss_buffer_desc radiusConfigStanza;
+ gss_buffer_desc caCertificate;
+ gss_buffer_desc subjectNameConstraint;
+ gss_buffer_desc subjectAltNameConstraint;
#ifdef GSSEAP_ENABLE_REAUTH
krb5_ccache krbCredCache;
gss_cred_id_t reauthCred;
time_t expiryTime;
uint64_t sendSeq, recvSeq;
void *seqState;
- gss_cred_id_t defaultCred;
+ gss_cred_id_t cred;
union {
struct gss_eap_initiator_ctx initiator;
#define initiatorCtx ctxU.initiator
#define reauthCtx ctxU.reauth
#endif
} ctxU;
+ const struct gss_eap_token_buffer_set *inputTokens;
+ const struct gss_eap_token_buffer_set *outputTokens;
};
#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01
#endif
static OM_uint32
- peerConfigInit(OM_uint32 *minor,
- gss_cred_id_t cred,
- gss_ctx_id_t ctx)
+ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
{
OM_uint32 major;
krb5_context krbContext;
struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
+ gss_cred_id_t cred = ctx->cred;
eapPeerConfig->identity = NULL;
eapPeerConfig->identity_len = 0;
eapPeerConfig->password = (unsigned char *)cred->password.value;
eapPeerConfig->password_len = cred->password.length;
+ /* certs */
+ eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
+ eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
+ eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
+
*minor = 0;
return GSS_S_COMPLETE;
}
static OM_uint32
initBegin(OM_uint32 *minor,
- gss_cred_id_t cred,
gss_ctx_id_t ctx,
gss_name_t target,
gss_OID mech,
gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
{
OM_uint32 major;
+ gss_cred_id_t cred = ctx->cred;
assert(cred != GSS_C_NO_CREDENTIAL);
static OM_uint32
eapGssSmInitAuthenticate(OM_uint32 *minor,
- gss_cred_id_t cred,
+ gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_name_t target GSSEAP_UNUSED,
gss_OID mech GSSEAP_UNUSED,
{
OM_uint32 major;
OM_uint32 tmpMinor;
- int code;
struct wpabuf *resp = NULL;
*minor = 0;
assert(inputToken != GSS_C_NO_BUFFER);
- major = peerConfigInit(minor, cred, ctx);
+ major = peerConfigInit(minor, ctx);
if (GSS_ERROR(major))
goto cleanup;
major = GSS_S_CONTINUE_NEEDED;
- code = eap_peer_sm_step(ctx->initiatorCtx.eap);
+ eap_peer_sm_step(ctx->initiatorCtx.eap);
if (ctx->flags & CTX_FLAG_EAP_RESP) {
ctx->flags &= ~(CTX_FLAG_EAP_RESP);
}
static OM_uint32
+eapGssSmInitGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char wireFlags[4];
+ gss_buffer_desc flagsBuf;
+
+ store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
+
+ flagsBuf.length = sizeof(wireFlags);
+ flagsBuf.value = wireFlags;
+
+ return duplicateBuffer(minor, &flagsBuf, outputToken);
+}
+
+static OM_uint32
eapGssSmInitGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
return GSS_S_CONTINUE_NEEDED;
}
+static OM_uint32
+eapGssSmInitInitiatorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags)
+{
+ OM_uint32 major;
+
+ major = gssEapMakeTokenMIC(minor, ctx, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ GSSEAP_SM_TRANSITION_NEXT(ctx);
+
+ *minor = 0;
+ *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
eapGssSmInitReauthCreds(OM_uint32 *minor,
#endif /* GSSEAP_ENABLE_REAUTH */
static OM_uint32
-eapGssSmInitCompleteInitiatorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags)
+eapGssSmInitAcceptorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
{
- GSSEAP_SM_TRANSITION_NEXT(ctx);
-
- *minor = 0;
- *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
+ OM_uint32 major;
- return GSS_S_CONTINUE_NEEDED;
-}
+ major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
+ if (GSS_ERROR(major))
+ return major;
-static OM_uint32
-eapGssSmInitCompleteAcceptorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags GSSEAP_UNUSED)
-{
GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
*minor = 0;
},
{
ITOK_TYPE_NONE,
+ ITOK_TYPE_GSS_FLAGS,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmInitGssFlags
+ },
+ {
+ ITOK_TYPE_NONE,
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
GSSEAP_STATE_INITIATOR_EXTS,
SM_ITOK_FLAG_REQUIRED,
},
{
ITOK_TYPE_NONE,
- ITOK_TYPE_NONE,
+ ITOK_TYPE_INITIATOR_MIC,
GSSEAP_STATE_INITIATOR_EXTS,
- 0,
- eapGssSmInitCompleteInitiatorExts
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmInitInitiatorMIC
},
#ifdef GSSEAP_ENABLE_REAUTH
{
#endif
/* other extensions go here */
{
- ITOK_TYPE_NONE,
+ ITOK_TYPE_ACCEPTOR_MIC,
ITOK_TYPE_NONE,
GSSEAP_STATE_ACCEPTOR_EXTS,
- 0,
- eapGssSmInitCompleteAcceptorExts
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmInitAcceptorMIC
}
};
GSSEAP_MUTEX_LOCK(&ctx->mutex);
- if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
- major = gssEapAcquireCred(minor,
- GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
- time_req,
- GSS_C_NO_OID_SET,
- GSS_C_INITIATE,
- &ctx->defaultCred,
- NULL,
- NULL);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ if (cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_LOCK(&cred->mutex);
- cred = ctx->defaultCred;
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ assert(ctx->cred != GSS_C_NO_CREDENTIAL);
}
- GSSEAP_MUTEX_LOCK(&cred->mutex);
+ GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
- if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
- major = GSS_S_NO_CRED;
- *minor = GSSEAP_CRED_USAGE_MISMATCH;
- goto cleanup;
- }
+ assert(ctx->cred->flags & CRED_FLAG_RESOLVED);
+ assert(ctx->cred->flags & CRED_FLAG_INITIATE);
if (initialContextToken) {
- major = initBegin(minor, cred, ctx, target_name, mech_type,
+ major = initBegin(minor, ctx, target_name, mech_type,
req_flags, time_req, input_chan_bindings);
if (GSS_ERROR(major))
goto cleanup;
cleanup:
if (cred != GSS_C_NO_CREDENTIAL)
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
+ if (ctx->cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_UNLOCK(&ctx->cred->mutex);
GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
if (GSS_ERROR(major))
#endif
#if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
- #define GSSEAP_UNUSED __attribute__ ((__unused__))
+ #define GSSEAP_UNUSED __attribute__ ((__unused__))
#else
#define GSSEAP_UNUSED
#endif
const char *string,
gss_buffer_t buffer);
+ #define makeStringBufferOrCleanup(src, dst) \
+ do { \
+ major = makeStringBuffer((minor), (src), (dst));\
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
OM_uint32
bufferToString(OM_uint32 *minor,
const gss_buffer_t buffer,
const gss_buffer_t src,
gss_buffer_t dst);
+ #define duplicateBufferOrCleanup(src, dst) \
+ do { \
+ major = duplicateBuffer((minor), (src), (dst)); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
static inline int
bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
{
#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */
#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */
+#define ITOK_TYPE_GSS_FLAGS 0x0000000C /* optional */
+#define ITOK_TYPE_INITIATOR_MIC 0x0000000D /* critical, required, if not reauth */
+#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000E /* TBD */
#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))
+#define GSSEAP_WIRE_FLAGS_MASK GSS_C_MUTUAL_FLAG
+
OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
gss_ctx_id_t context_handle,
OM_uint32 *time_rec);
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC);
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC);
+
/* 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);
+ gss_OID
+ gssEapPrimaryMechForCred(gss_cred_id_t cred);
+
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_OID_set *pActualMechs,
OM_uint32 *timeRec);
+ OM_uint32
+ gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password);
+
+ OM_uint32
+ gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target);
+
+ OM_uint32
+ gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t target,
+ gss_cred_id_t *resolvedCred);
+
int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
OM_uint32
gss_OID
gssEapSaslNameToOid(const gss_buffer_t name);
+ /* util_moonshot.c */
+ OM_uint32
+ libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName);
+
+ OM_uint32
+ libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName);
+
/* util_name.c */
#define EXPORT_NAME_FLAG_OID 0x1
#define EXPORT_NAME_FLAG_COMPOSITE 0x2
gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
/* util_token.c */
+struct gss_eap_token_buffer_set {
+ gss_buffer_set_desc buffers; /* pointers only */
+ OM_uint32 *types;
+};
+
OM_uint32
gssEapEncodeInnerTokens(OM_uint32 *minor,
- gss_buffer_set_t extensions,
- OM_uint32 *types,
+ struct gss_eap_token_buffer_set *tokens,
gss_buffer_t buffer);
OM_uint32
gssEapDecodeInnerTokens(OM_uint32 *minor,
const gss_buffer_t buffer,
- gss_buffer_set_t *pExtensions,
- OM_uint32 **pTypes);
+ struct gss_eap_token_buffer_set *tokens);
+
+OM_uint32
+gssEapReleaseInnerTokens(OM_uint32 *minor,
+ struct gss_eap_token_buffer_set *tokens,
+ int freeBuffers);
+
+OM_uint32
+gssEapAllocInnerTokens(OM_uint32 *minor,
+ size_t count,
+ struct gss_eap_token_buffer_set *tokens);
size_t
tokenSize(const gss_OID_desc *mech, size_t body_size);
GSS_C_INTEG_FLAG | /* integrity */
GSS_C_CONF_FLAG | /* confidentiality */
GSS_C_SEQUENCE_FLAG | /* sequencing */
- GSS_C_REPLAY_FLAG| /* replay detection */
- GSS_C_MUTUAL_FLAG; /*xxx big hack */
+ GSS_C_REPLAY_FLAG; /* replay detection */
*pCtx = ctx;
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
sequenceFree(&tmpMinor, &ctx->seqState);
- gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
+ gssEapReleaseCred(&tmpMinor, &ctx->cred);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
return GSS_S_COMPLETE;
}
+
+static OM_uint32
+gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC,
+ int verifyMIC)
+{
+ OM_uint32 major;
+ gss_iov_buffer_desc *iov = NULL;
+ size_t i = 0, j;
+ enum gss_eap_token_type tokType;
+ OM_uint32 micTokType;
+ unsigned char wireTokType[2];
+ unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL;
+ const struct gss_eap_token_buffer_set *tokens;
+
+ tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens;
+
+ assert(tokens != NULL);
+
+ iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov));
+ if (iov == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokTypes == NULL) {
+ *minor = ENOMEM;
+ major = GSS_S_FAILURE;
+ goto cleanup;
+ }
+
+ innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokLengths == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Mechanism OID */
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = ctx->mechanismUsed->length;
+ iov[i].buffer.value = ctx->mechanismUsed->elements;
+ i++;
+
+ /* Token type */
+ if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) {
+ tokType = TOK_TYPE_INITIATOR_CONTEXT;
+ micTokType = ITOK_TYPE_INITIATOR_MIC;
+ } else {
+ tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
+ micTokType = ITOK_TYPE_ACCEPTOR_MIC;
+ }
+ store_uint16_be(tokType, wireTokType);
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = sizeof(wireTokType);
+ iov[i].buffer.value = wireTokType;
+ i++;
+
+ for (j = 0; j < tokens->buffers.count; j++) {
+ if (verifyMIC &&
+ (tokens->types[j] & ITOK_TYPE_MASK) == micTokType)
+ continue; /* will use this slot for trailer */
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokTypes[j * 4];
+ store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED),
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokLengths[j * 4];
+ store_uint32_be(tokens->buffers.elements[j].length,
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer = tokens->buffers.elements[j];
+ i++;
+ }
+
+ if (verifyMIC) {
+ assert(tokenMIC->length >= 16);
+
+ assert(i < 2 + (3 * tokens->buffers.count));
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[i].buffer.length = 16;
+ iov[i].buffer.value = tokenMIC->value;
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[i].buffer.length = tokenMIC->length - 16;
+ iov[i].buffer.value = (unsigned char *)tokenMIC->value + 16;
+ i++;
+
+ major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
+ iov, i, TOK_TYPE_MIC);
+ } else {
+ iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
+ iov, i, TOK_TYPE_MIC);
+ if (!GSS_ERROR(major))
+ *tokenMIC = iov[i - 1].buffer;
+ }
+
+cleanup:
+ if (iov != NULL)
+ gssEapReleaseIov(iov, tokens->buffers.count);
+ if (innerTokTypes != NULL)
+ GSSEAP_FREE(innerTokTypes);
+ if (innerTokLengths != NULL)
+ GSSEAP_FREE(innerTokLengths);
+
+ return major;
+}
+
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC)
+{
+ tokenMIC->length = 0;
+ tokenMIC->value = NULL;
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE);
+}
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC)
+{
+ if (tokenMIC->length < 16) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_BAD_SIG;
+ }
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE);
+}