}
static OM_uint32
+eapGssSmAcceptIdentity(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t inputToken,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t outputToken)
+{
+ OM_uint32 major;
+ rc_handle *rh;
+ union {
+ struct eap_hdr eap;
+ unsigned char data[5];
+ } pdu;
+ gss_buffer_desc pduBuffer;
+ char *config = RC_CONFIG_FILE;
+
+ if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0)
+ return GSS_S_DEFECTIVE_TOKEN;
+
+ assert(ctx->acceptorCtx.radHandle == NULL);
+
+ if (cred != GSS_C_NO_CREDENTIAL && cred->radiusConfigFile != NULL)
+ config = cred->radiusConfigFile;
+
+ rh = ctx->acceptorCtx.radHandle = rc_read_config(config);
+ if (rh == NULL) {
+ *minor = errno;
+ return GSS_S_FAILURE;
+ }
+
+ if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {
+ *minor = errno;
+ return GSS_S_FAILURE;
+ }
+
+ if (ctx->acceptorName == GSS_C_NO_NAME &&
+ cred != GSS_C_NO_CREDENTIAL &&
+ cred->name != GSS_C_NO_NAME) {
+ major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName);
+ if (GSS_ERROR(major))
+ return major;
+ }
+
+ pdu.eap.code = EAP_CODE_REQUEST;
+ pdu.eap.identifier = 0;
+ pdu.eap.length = htons(sizeof(pdu.data));
+ pdu.data[4] = EAP_TYPE_IDENTITY;
+
+ pduBuffer.length = sizeof(pdu.data);
+ pduBuffer.value = pdu.data;
+
+ major = duplicateBuffer(minor, &pduBuffer, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_AUTHENTICATE;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
eapGssSmAcceptAuthenticate(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_cred_id_t cred,
rc_handle *rh = ctx->acceptorCtx.radHandle;
char msgBuffer[4096];
- if (rh == NULL) {
- rh = ctx->acceptorCtx.radHandle = rc_read_config(RC_CONFIG_FILE);
- if (rh == NULL) {
- *minor = errno;
- major = GSS_S_FAILURE;
- goto cleanup;
- }
-
- if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {
- *minor = errno;
- major = GSS_S_FAILURE;
- goto cleanup;
- }
- }
-
- if (ctx->acceptorName == GSS_C_NO_NAME &&
- cred != GSS_C_NO_CREDENTIAL &&
- cred->name != GSS_C_NO_NAME) {
- major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName);
- if (GSS_ERROR(major))
- goto cleanup;
- }
-
if (rc_avpair_add(rh, &send, PW_EAP_MESSAGE,
inputToken->value, inputToken->length, 0) == NULL) {
*minor = ENOMEM;
gss_channel_bindings_t chanBindings,
gss_buffer_t outputToken)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
gss_iov_buffer_desc iov[2];
outputToken->length = 0;
gss_channel_bindings_t,
gss_buffer_t);
} eapGssAcceptorSm[] = {
+ { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptIdentity },
{ TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate },
-#if 0
- { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL },
- { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL },
-#endif
{ TOK_TYPE_GSS_CB, TOK_TYPE_NONE, eapGssSmAcceptGssChannelBindings },
{ TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished },
};
static OM_uint32
peerConfigInit(OM_uint32 *minor,
gss_cred_id_t cred,
- gss_ctx_id_t ctx,
- int loadConfig)
+ gss_ctx_id_t ctx)
{
krb5_context krbContext;
struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
GSSEAP_KRB_INIT(&krbContext);
- if (loadConfig) {
- eapPeerConfig->fragment_size = 1024;
- wpa_debug_level = 0;
- }
+ eapPeerConfig->fragment_size = 1024;
+ wpa_debug_level = 0;
code = krb5_unparse_name(krbContext, cred->name->krbPrincipal, &identity);
if (code != 0) {
return GSS_S_COMPLETE;
}
+static gss_buffer_desc emptyBuffer = GSS_C_EMPTY_BUFFER;
+
+static OM_uint32
+eapGssSmInitIdentity(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)
+{
+ int initialContextToken;
+ time_t now;
+ OM_uint32 major;
+
+ initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
+ inputToken->length == 0);
+ if (!initialContextToken)
+ return GSS_S_DEFECTIVE_TOKEN;
+
+ time(&now);
+ if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
+ ctx->expiryTime = 0;
+ else
+ ctx->expiryTime = now + timeReq;
+
+ major = gss_duplicate_name(minor, cred->name, &ctx->initiatorName);
+ if (GSS_ERROR(major))
+ return major;
+
+ major = gss_duplicate_name(minor, target, &ctx->acceptorName);
+ if (GSS_ERROR(major))
+ return major;
+
+ if (mech == GSS_C_NULL_OID || oidEqual(mech, GSS_EAP_MECHANISM)) {
+ major = gssEapDefaultMech(minor, &ctx->mechanismUsed);
+ } else if (gssEapIsConcreteMechanismOid(mech)) {
+ if (!gssEapInternalizeOid(mech, &ctx->mechanismUsed))
+ major = duplicateOid(minor, mech, &ctx->mechanismUsed);
+ } else {
+ major = GSS_S_BAD_MECH;
+ }
+ if (GSS_ERROR(major))
+ return major;
+
+ /* If credentials were provided, check they're usable with this mech */
+ if (!gssEapCredAvailable(cred, ctx->mechanismUsed))
+ return GSS_S_BAD_MECH;
+
+ major = duplicateBuffer(minor, &emptyBuffer, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_AUTHENTICATE;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
static OM_uint32
eapGssSmInitAuthenticate(OM_uint32 *minor,
gss_cred_id_t cred,
gss_buffer_t outputToken)
{
OM_uint32 major;
- OM_uint32 tmpMajor, tmpMinor;
- time_t now;
- int initialContextToken = 0, code;
- gss_buffer_desc respBuf = GSS_C_EMPTY_BUFFER;
-
- initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
- inputToken->length == 0);
+ OM_uint32 tmpMinor;
+ int code;
+ struct wpabuf *resp = NULL;
- major = peerConfigInit(minor, cred, ctx, initialContextToken);
+ major = peerConfigInit(minor, cred, ctx);
if (GSS_ERROR(major))
goto cleanup;
- if (initialContextToken) {
+ if (ctx->initiatorCtx.eap == NULL) {
struct eap_config eapConfig;
memset(&eapConfig, 0, sizeof(eapConfig));
&gssEapPolicyCallbacks,
ctx,
&eapConfig);
-
- time(&now);
- if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
- ctx->expiryTime = 0;
- else
- ctx->expiryTime = now + timeReq;
-
- major = gss_duplicate_name(minor, cred->name, &ctx->initiatorName);
- if (GSS_ERROR(major))
- goto cleanup;
-
- major = gss_duplicate_name(minor, target, &ctx->acceptorName);
- if (GSS_ERROR(major))
+ if (ctx->initiatorCtx.eap == NULL) {
+ major = GSS_S_FAILURE;
goto cleanup;
-
- if (mech == GSS_C_NULL_OID || oidEqual(mech, GSS_EAP_MECHANISM)) {
- major = gssEapDefaultMech(minor, &ctx->mechanismUsed);
- } else if (gssEapIsConcreteMechanismOid(mech)) {
- if (!gssEapInternalizeOid(mech, &ctx->mechanismUsed))
- major = duplicateOid(minor, mech, &ctx->mechanismUsed);
- } else {
- major = GSS_S_BAD_MECH;
}
- if (GSS_ERROR(major))
- goto cleanup;
-
- /* If credentials were provided, check they're usable with this mech */
- if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
- major = GSS_S_BAD_MECH;
- goto cleanup;
- }
-
- respBuf.value = ""; /* emit empty inner token */
- major = GSS_S_CONTINUE_NEEDED;
- goto cleanup;
- } else {
- ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
}
+ ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
+
wpabuf_set(&ctx->initiatorCtx.reqData,
inputToken->value, inputToken->length);
code = eap_peer_sm_step(ctx->initiatorCtx.eap);
if (ctx->flags & CTX_FLAG_EAP_RESP) {
- struct wpabuf *resp;
ctx->flags &= ~(CTX_FLAG_EAP_RESP);
resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
if (resp != NULL) {
- respBuf.length = wpabuf_len(resp);
- respBuf.value = (void *)wpabuf_head(resp);
}
} else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
major = initReady(minor, ctx);
}
cleanup:
- if (respBuf.value != NULL) {
+ if (resp != NULL) {
OM_uint32 tmpMajor;
+ gss_buffer_desc respBuf;
assert(major == GSS_S_CONTINUE_NEEDED);
+ respBuf.length = wpabuf_len(resp);
+ respBuf.value = (void *)wpabuf_head(resp);
+
tmpMajor = duplicateBuffer(&tmpMinor, &respBuf, outputToken);
if (GSS_ERROR(tmpMajor)) {
major = tmpMajor;
return major;
}
-#if 0
-static OM_uint32
-eapGssSmInitKeyTransport(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)
-{
- GSSEAP_NOT_IMPLEMENTED;
-}
-
-static OM_uint32
-eapGssSmInitSecureAssoc(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)
-{
- GSSEAP_NOT_IMPLEMENTED;
-}
-#endif
-
static OM_uint32
eapGssSmInitGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred,
gss_buffer_t inputToken,
gss_buffer_t outputToken)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
gss_iov_buffer_desc iov[2];
gss_buffer_desc buf;
gss_buffer_t,
gss_buffer_t);
} eapGssInitiatorSm[] = {
+ { TOK_TYPE_NONE, TOK_TYPE_EAP_RESP, eapGssSmInitIdentity },
{ TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate },
-#if 0
- { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitKeyTransport },
- { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitSecureAssoc },
-#endif
{ TOK_TYPE_NONE, TOK_TYPE_GSS_CB, eapGssSmInitGssChannelBindings },
{ TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmInitEstablished },
};
#include "gssapiP_eap.h"
+static OM_uint32
+setCredRadiusConfigFile(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_OID oid,
+ const gss_buffer_t buffer)
+{
+ OM_uint32 major;
+ gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
+
+ if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
+ major = duplicateBuffer(minor, buffer, &configFileBuffer);
+ if (GSS_ERROR(major))
+ return major;
+ }
+
+ if (cred->radiusConfigFile != NULL)
+ free(cred->radiusConfigFile);
+
+ cred->radiusConfigFile = (char *)configFileBuffer.value;
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
static struct {
gss_OID_desc oid;
- OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t *pCred,
+ OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t cred,
const gss_OID, const gss_buffer_t);
} setCredOps[] = {
+ /* 1.3.6.1.4.1.5322.21.3.3.1 */
+ {
+ { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x15\x03\x03\x01" },
+ setCredRadiusConfigFile,
+ },
};
+gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE = &setCredOps[0].oid;
+
OM_uint32
gssspi_set_cred_option(OM_uint32 *minor,
gss_cred_id_t cred,
for (i = 0; i < sizeof(setCredOps) / sizeof(setCredOps[0]); i++) {
if (oidEqual(&setCredOps[i].oid, desired_object)) {
- major = (*setCredOps[i].setOption)(minor, &cred,
+ major = (*setCredOps[i].setOption)(minor, cred,
desired_object, value);
break;
}