ctx->initiatorName->attrCtx = gssEapCreateAttrContext(cred, ctx);
+ *minor = 0;
return GSS_S_COMPLETE;
}
} pkt;
gss_buffer_desc pktBuffer;
- if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0)
+ if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
+ *minor = GSSEAP_WRONG_SIZE;
return GSS_S_DEFECTIVE_TOKEN;
+ }
assert(ctx->acceptorName == GSS_C_NO_NAME);
ctx->state = EAP_STATE_AUTHENTICATE;
+ *minor = 0;
return GSS_S_CONTINUE_NEEDED;
}
assert(rh != NULL);
- /* Awaits further specification */
- if (ctx->acceptorName == GSS_C_NO_NAME)
+ if (ctx->acceptorName == GSS_C_NO_NAME) {
+ *minor = 0;
return GSS_S_COMPLETE;
+ }
+
+ if ((ctx->acceptorName->flags & NAME_FLAG_SERVICE) == 0) {
+ *minor = GSSEAP_BAD_SERVICE_NAME;
+ return GSS_S_BAD_NAME;
+ }
GSSEAP_KRB_INIT(&krbContext);
krbPrinc = ctx->acceptorName->krbPrincipal;
assert(krbPrinc != NULL);
-
- if (krb5_princ_size(krbContext, krbPrinc) < 2)
- return GSS_S_BAD_NAME;
+ assert(krb5_princ_size(krbContext, krbPrinc) >= 2);
/* Acceptor-Service-Name */
krbDataToGssBuffer(krb5_princ_component(krbContext, krbPrinc, 0), &nameBuf);
return major;
}
+ *minor = 0;
return GSS_S_COMPLETE;
}
assert(actx->radConn == NULL);
if (rs_context_create(&actx->radHandle, RS_DICT_FILE) != 0) {
- *minor = GSSEAP_RADSEC_INIT_FAILURE;
+ *minor = GSSEAP_RADSEC_CONTEXT_FAILURE;
return GSS_S_FAILURE;
}
ctx->state = EAP_STATE_EXTENSIONS_REQ;
}
+ *minor = 0;
major = GSS_S_CONTINUE_NEEDED;
cleanup:
ctx->state = EAP_STATE_EXTENSIONS_RESP;
+ *minor = 0;
return GSS_S_CONTINUE_NEEDED;
}
ctx->state = EAP_STATE_ESTABLISHED;
+ *minor = 0;
return GSS_S_COMPLETE;
}
output_token->value = NULL;
if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
goto cleanup;
if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
- *minor = GSSEAP_WRONG_MECH;
+ *minor = GSSEAP_CRED_MECH_MISMATCH;
major = GSS_S_BAD_MECH;
goto cleanup;
}
if (GSS_ERROR(major))
goto cleanup;
}
- if (time_rec != NULL)
- gssEapContextTime(&tmpMinor, ctx, time_rec);
+ if (time_rec != NULL) {
+ major = gssEapContextTime(&tmpMinor, ctx, time_rec);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
}
assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);
ctx->state = EAP_STATE_ESTABLISHED;
+ *minor = 0;
return GSS_S_COMPLETE;
}
ret = eap_peer_tnc_register();
#endif /* EAP_TNC */
- return ret ? GSS_S_FAILURE : GSS_S_COMPLETE;
+ if (ret == 0)
+ return GSS_S_COMPLETE;
+
+ *minor = GSSEAP_LIBEAP_INIT_FAILURE;
+ return GSS_S_FAILURE;
}
static OM_uint32
static OM_uint32
gssEapInitLibRadsec(OM_uint32 *minor)
{
+ if (0) {
+ *minor = GSSEAP_RADSEC_INIT_FAILURE;
+ return GSS_S_FAILURE;
+ }
+
return GSS_S_COMPLETE;
}
assert(p == (unsigned char *)token->value + token->length);
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
cleanup:
if (GSS_ERROR(major))
gss_release_buffer(&tmpMinor, token);
error_table eapg
+#
+# Protocol errors that can be returned in an error token. This should match
+# up with makeErrorToken in accept_sec_context.c.
+#
error_code GSSEAP_RESERVED, ""
error_code GSSEAP_WRONG_SIZE, "Buffer is incorrect size"
error_code GSSEAP_WRONG_MECH, "Mechanism OID is incorrect"
error_code GSSEAP_REFLECT, "Token was reflected"
error_code GSSEAP_CRIT_EXT_UNAVAILABLE, "Critical extension unavailable"
error_code GSSEAP_MISSING_REQUIRED_EXT, "Missing required extension"
-error_code GSSEAP_BAD_SERVICE_NAME, "Could not parse service name"
error_code GSSEAP_KEY_UNAVAILABLE, "EAP key unavailable"
error_code GSSEAP_KEY_TOO_SHORT, "EAP key too short"
error_code GSSEAP_RADIUS_AUTH_FAILURE, "Authentication rejected by RADIUS server"
error_code GSSEAP_UNKNOWN_RADIUS_CODE, "Received unknown response code from RADIUS server"
error_code GSSEAP_MISSING_EAP_REQUEST, "RADIUS response is missing EAP request"
error_code GSSEAP_GENERIC_RADIUS_ERROR, "Generic RADIUS error"
+
+#
+# Context errors
+#
+error_code GSSEAP_CONTEXT_ESTABLISHED, "Context is already fully established"
+error_code GSSEAP_CONTEXT_INCOMPLETE, "Attempt to use incomplete security context"
+error_code GSSEAP_BAD_CONTEXT_TOKEN, "Context token is malformed or corrupt"
+error_code GSSEAP_BAD_ERROR_TOKEN, "Error token is malformed or corrupt"
+error_code GSSEAP_BAD_CONTEXT_OPTION, "Bad context option"
+
+#
+# Name errors
+#
+error_code GSSEAP_BAD_SERVICE_NAME, "Name is not a valid service name"
+error_code GSSEAP_BAD_INITIATOR_NAME, "Initiator identity must be a valid name"
+error_code GSSEAP_NO_HOSTNAME, "Could not determine local host name"
+
+#
+# Credential errors
+#
error_code GSSEAP_BAD_USAGE, "Credential usage type is unknown"
error_code GSSEAP_CRED_USAGE_MISMATCH, "Credential usage does not match requested usage"
+error_code GSSEAP_CRED_MECH_MISMATCH, "Credential is not usable with this mechanism"
+error_code GSSEAP_BAD_CRED_OPTION, "Bad credential option"
+
+#
+# Wrap/unwrap/PRF errors
+#
+error_code GSSEAP_BAD_WRAP_TOKEN, "Bad RFC 4121 wrap or MIC token"
+error_code GSSEAP_MISSING_IOV, "IOV is missing required buffer"
+error_code GSSEAP_BAD_STREAM_IOV, "Stream IOV can only contain a single data buffer"
+error_code GSSEAP_BAD_PADDING_IOV, "Padding IOV is not permitted for RFC 4121 tokens"
+error_code GSSEAP_UNKNOWN_QOP, "Unknown quality of protection specified"
error_code GSSEAP_INPUT_TOO_LONG, "PRF input too long"
-error_code GSSEAP_CONTEXT_ESTABLISHED, "Context is already fully established"
-error_code GSSEAP_CONTEXT_INCOMPLETE, "Attempt to use incomplete security context"
+error_code GSSEAP_BAD_PRF_KEY, "PRF key usage type is unknown"
+
+#
+# libeap errors
+#
+error_code GSSEAP_LIBEAP_INIT_FAILURE, "Failed to initialise EAP library"
+error_code GSSEAP_PEER_SM_INIT_FAILURE, "Failed to create EAP state machine"
+error_code GSSEAP_PEER_AUTH_FAILURE, "EAP peer authentication failure"
+error_code GSSEAP_PEER_BAD_MESSAGE, "Received bad EAP message"
+
+#
+# RadSec initialisation errors
+#
error_code GSSEAP_RADSEC_INIT_FAILURE, "Failed to initialise RadSec library"
+error_code GSSEAP_RADSEC_CONTEXT_FAILURE, "Failed to create RadSec context"
+
+#
+# SAML/Shibboleth/attribute errors
+#
error_code GSSEAP_SAML_INIT_FAILURE, "Failed to initialise SAML library"
error_code GSSEAP_SHIB_INIT_FAILURE, "Failed to initialise Shibboleth"
-error_code GSSEAP_PEER_INIT_FAILURE, "Failed to initialise EAP state machine"
-error_code GSSEAP_PEER_AUTH_FAILURE, "EAP peer authentication failure"
-error_code GSSEAP_PEER_BAD_MESSAGE, "Received bad EAP message"
error_code GSSEAP_NO_ATTR_CONTEXT, "Name has no attributes"
error_code GSSEAP_NO_ATTR_PROVIDERS, "Failed to initialise attribute providers"
error_code GSSEAP_NO_SUCH_ATTR, "Unknown naming attribute"
error_code GSSEAP_BAD_ATTR_TOKEN, "Serialised attributes are malformed or corrupt"
error_code GSSEAP_ATTR_CONTEXT_FAILURE, "Failed to initialise attribute context"
-error_code GSSEAP_BAD_CONTEXT_TOKEN, "Context token is malformed or corrupt"
-error_code GSSEAP_MISSING_IOV, "IOV is missing required buffer"
-error_code GSSEAP_BAD_STREAM_IOV, "Stream IOV can only contain a single data buffer"
-error_code GSSEAP_BAD_PADDING_IOV, "Padding IOV is not permitted for RFC 4121 tokens"
-error_code GSSEAP_BAD_PRF_KEY, "PRF key usage type is unknown"
-error_code GSSEAP_BAD_ERROR_TOKEN, "Error token is malformed or corrupt"
-error_code GSSEAP_BAD_WRAP_TOKEN, "Bad RFC 4121 wrap or MIC token"
+
+#
+# Extensions
+#
error_code GSSEAP_BINDINGS_MISMATCH, "Channel bindings do not match"
error_code GSSEAP_NO_MECHGLUE_SYMBOL, "Could not find symbol in mechanism glue"
-error_code GSSEAP_UNKNOWN_QOP, "Unknown quality of protection specified"
-error_code GSSEAP_NO_HOSTNAME, "Could not determine local host name"
end
#define CHECK_REMAIN(n) do { \
if (remain < (n)) { \
- *minor = GSSEAP_WRONG_SIZE; \
+ *minor = GSSEAP_TOK_TRUNC; \
return GSS_S_DEFECTIVE_TOKEN; \
} \
} while (0)
oidBuf.length = load_uint32_be(p);
if (remain < 4 + oidBuf.length || oidBuf.length == 0) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
gss_buffer_desc tmp;
if (remain < 12) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
}
if (remain - 12 < length) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
gss_buffer_desc tmp;
if (remain < 4) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
tmp.length = load_uint32_be(p);
if (tmp.length != 0) {
if (remain - 4 < tmp.length) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
size_t remain = token->length;
if (remain < 16) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
if (load_uint32_be(&p[0]) != EAP_EXPORT_CONTEXT_V1) {
}
if (remain < 24 + sequenceSize(ctx->seqState)) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
ctx->expiryTime = (time_t)load_uint64_be(&p[0]); /* XXX */
OM_uint32 major, tmpMinor;
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
- *minor = 0;
*context_handle = GSS_C_NO_CONTEXT;
if (interprocess_token == GSS_C_NO_BUFFER ||
- interprocess_token->length == 0)
+ interprocess_token->length == 0) {
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
+ }
major = gssEapAllocContext(minor, &ctx);
if (GSS_ERROR(major))
eapPeerConfig->fragment_size = 1024;
wpa_debug_level = 0;
+ if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) {
+ *minor = GSSEAP_BAD_INITIATOR_NAME;
+ return GSS_S_BAD_NAME;
+ }
+
code = krb5_unparse_name(krbContext, cred->name->krbPrincipal, &identity);
if (code != 0) {
*minor = code;
eapPeerConfig->password = (unsigned char *)cred->password.value;
eapPeerConfig->password_len = cred->password.length;
+ *minor = 0;
return GSS_S_COMPLETE;
}
krb5_free_unparsed_name(krbContext, (char *)eapPeerConfig->identity);
+ *minor = 0;
return GSS_S_COMPLETE;
}
return major;
/* If credentials were provided, check they're usable with this mech */
- if (!gssEapCredAvailable(cred, ctx->mechanismUsed))
+ if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
+ *minor = GSSEAP_CRED_MECH_MISMATCH;
return GSS_S_BAD_MECH;
+ }
+ *minor = 0;
return GSS_S_COMPLETE;
}
ctx->state = EAP_STATE_AUTHENTICATE;
+ *minor = 0;
return GSS_S_CONTINUE_NEEDED;
}
struct wpabuf *resp = NULL;
int initialContextToken;
+ *minor = 0;
+
initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
inputToken->length == 0);
ctx,
&eapConfig);
if (ctx->initiatorCtx.eap == NULL) {
- *minor = GSSEAP_PEER_INIT_FAILURE;
+ *minor = GSSEAP_PEER_SM_INIT_FAILURE;
major = GSS_S_FAILURE;
goto cleanup;
}
ctx->state = EAP_STATE_EXTENSIONS_RESP;
+ *minor = 0;
return GSS_S_CONTINUE_NEEDED;
}
ctx->state = EAP_STATE_ESTABLISHED;
+ *minor = 0;
return GSS_S_COMPLETE;
}
unsigned char *p;
if (inputToken->length < 8) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
return GSS_S_NO_CONTEXT;
}
- *minor = 0;
-
GSSEAP_MUTEX_LOCK(&ctx->mutex);
if (src_name != NULL) {
}
major = GSS_S_COMPLETE;
+ *minor = 0;
cleanup:
GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
{
OM_uint32 major = GSS_S_COMPLETE;
- if (cred == NULL)
+ if (cred == NULL) {
+ *minor = EINVAL;
return GSS_S_NO_CRED;
+ }
GSSEAP_MUTEX_LOCK(&cred->mutex);
goto cleanup;
}
+ *minor = 0;
+ major = GSS_S_COMPLETE;
+
cleanup:
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
OM_uint32 major = GSS_S_UNAVAILABLE;
int i;
- *minor = 0;
*data_set = GSS_C_NO_BUFFER_SET;
- if (cred_handle == GSS_C_NO_CREDENTIAL)
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ *minor = EINVAL;
return GSS_S_NO_CRED;
+ }
GSSEAP_MUTEX_LOCK(&cred_handle->mutex);
+ major = GSS_S_UNAVAILABLE;
+ *minor = GSSEAP_BAD_CRED_OPTION;
+
for (i = 0; i < sizeof(inquireCredOps) / sizeof(inquireCredOps[0]); i++) {
if (oidEqual(&inquireCredOps[i].oid, desired_object)) {
major = (*inquireCredOps[i].inquire)(minor, cred_handle,
}
major = GSS_S_UNAVAILABLE;
+ *minor = GSSEAP_BAD_CONTEXT_OPTION;
for (i = 0; i < sizeof(inquireCtxOps) / sizeof(inquireCtxOps[0]); i++) {
if (oidEqual(&inquireCtxOps[i].oid, desired_object)) {
const gss_OID desired_object,
const gss_buffer_t value)
{
- OM_uint32 major = GSS_S_UNAVAILABLE;
+ OM_uint32 major;
gss_cred_id_t cred = *pCred;
int i;
GSSEAP_MUTEX_LOCK(&cred->mutex);
+ major = GSS_S_UNAVAILABLE;
+ *minor = GSSEAP_BAD_CRED_OPTION;
+
for (i = 0; i < sizeof(setCredOps) / sizeof(setCredOps[0]); i++) {
if (oidEqual(&setCredOps[i].oid, desired_object)) {
major = (*setCredOps[i].setOption)(minor, cred,
const gss_OID desired_object,
const gss_buffer_t value)
{
- OM_uint32 major = GSS_S_UNAVAILABLE;
+ OM_uint32 major;
gss_ctx_id_t ctx = *pCtx;
int i;
+ major = GSS_S_UNAVAILABLE;
+ *minor = GSSEAP_BAD_CONTEXT_OPTION;
+
if (ctx != GSS_C_NO_CONTEXT)
GSSEAP_MUTEX_LOCK(&ctx->mutex);
ptr = (unsigned char *)header->buffer.value;
if (header->buffer.length < 16) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
if (stream->buffer.length < theader->buffer.length +
tpadding->buffer.length +
ttrailer->buffer.length) {
- code = GSSEAP_WRONG_SIZE;
+ code = GSSEAP_TOK_TRUNC;
major = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
}
gss_buffer_desc extension;
if (remain < 8) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
major = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
}
extension.length = load_uint32_be(&p[4]);
if (remain < 8 + extension.length) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
major = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
}
name->krbPrincipal = *principal;
*principal = NULL;
- if (name->krbPrincipal->length == 1) {
- name->flags |= NAME_FLAG_NAI;
- } else {
+ if (name->krbPrincipal->length > 1) {
name->flags |= NAME_FLAG_SERVICE;
+ } else {
+ name->flags |= NAME_FLAG_NAI;
}
*pName = name;
#define CHECK_REMAIN(n) do { \
if (remain < (n)) { \
- *minor = GSSEAP_WRONG_SIZE; \
+ *minor = GSSEAP_TOK_TRUNC; \
major = GSS_S_BAD_NAME; \
goto cleanup; \
} \
void *q;
if (*lenremain < sizeof(queue)) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_DEFECTIVE_TOKEN;
}
int conf_state;
if (message_token->length < 16) {
- *minor = GSSEAP_WRONG_SIZE;
+ *minor = GSSEAP_TOK_TRUNC;
return GSS_S_BAD_SIG;
}