X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=import_sec_context.c;h=1e05f93edea2cc9676285a5e54980373f155ca5d;hb=15c93f06ee6ddefa7e7b095351f6e66698c7cc9e;hp=a64a6186543618dccbbf3947fc75a9f5e71f6d09;hpb=2f177997f0fd336c95567772c7fe0df36a4fa4bd;p=mech_eap.git diff --git a/import_sec_context.c b/import_sec_context.c index a64a618..1e05f93 100644 --- a/import_sec_context.c +++ b/import_sec_context.c @@ -32,29 +32,69 @@ #include "gssapiP_eap.h" +#define UPDATE_REMAIN(n) do { \ + p += (n); \ + remain -= (n); \ + } while (0) + +#define CHECK_REMAIN(n) do { \ + if (remain < (n)) { \ + *minor = GSSEAP_WRONG_SIZE; \ + return GSS_S_DEFECTIVE_TOKEN; \ + } \ + } while (0) + static OM_uint32 gssEapImportPartialContext(OM_uint32 *minor, unsigned char **pBuf, size_t *pRemain, gss_ctx_id_t ctx) { + OM_uint32 major; unsigned char *p = *pBuf; size_t remain = *pRemain; gss_buffer_desc buf; + size_t serverLen; - if (remain < 4) { - *minor = ERANGE; - return GSS_S_DEFECTIVE_TOKEN; + /* Selected RADIUS server */ + CHECK_REMAIN(4); + serverLen = load_uint32_be(p); + UPDATE_REMAIN(4); + + if (serverLen != 0) { + CHECK_REMAIN(serverLen); + + ctx->acceptorCtx.radServer = GSSEAP_MALLOC(serverLen + 1); + if (ctx->acceptorCtx.radServer == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(ctx->acceptorCtx.radServer, p, serverLen); + ctx->acceptorCtx.radServer[serverLen] = '\0'; + + UPDATE_REMAIN(serverLen); } + /* RADIUS state blob */ + CHECK_REMAIN(4); buf.length = load_uint32_be(p); + UPDATE_REMAIN(4); if (buf.length != 0) { - *minor = EINVAL; - return GSS_S_DEFECTIVE_TOKEN; + CHECK_REMAIN(buf.length); + + buf.value = p; + + major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state); + if (GSS_ERROR(major)) + return major; + + UPDATE_REMAIN(buf.length); } - *minor = 0; + *pBuf = p; + *pRemain = remain; + return GSS_S_COMPLETE; } @@ -71,13 +111,14 @@ importMechanismOid(OM_uint32 *minor, oidBuf.length = load_uint32_be(p); if (remain < 4 + oidBuf.length || oidBuf.length == 0) { - *minor = ERANGE; + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } oidBuf.elements = &p[4]; if (!gssEapIsConcreteMechanismOid(&oidBuf)) { + *minor = GSSEAP_WRONG_MECH; return GSS_S_BAD_MECH; } @@ -98,6 +139,8 @@ static OM_uint32 importKerberosKey(OM_uint32 *minor, unsigned char **pBuf, size_t *pRemain, + krb5_cksumtype *checksumType, + krb5_enctype *pEncryptionType, krb5_keyblock *key) { unsigned char *p = *pBuf; @@ -106,25 +149,26 @@ importKerberosKey(OM_uint32 *minor, OM_uint32 length; gss_buffer_desc tmp; - if (remain < 8) { - *minor = ERANGE; + if (remain < 12) { + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } - encryptionType = load_uint32_be(&p[0]); - length = load_uint32_be(&p[4]); + *checksumType = load_uint32_be(&p[0]); + encryptionType = load_uint32_be(&p[4]); + length = load_uint32_be(&p[8]); if ((length != 0) != (encryptionType != ENCTYPE_NULL)) { - *minor = ERANGE; + *minor = GSSEAP_BAD_CONTEXT_TOKEN; return GSS_S_DEFECTIVE_TOKEN; } - if (remain - 8 < length) { - *minor = ERANGE; + if (remain - 12 < length) { + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } - if (load_buffer(&p[8], length, &tmp) == NULL) { + if (load_buffer(&p[12], length, &tmp) == NULL) { *minor = ENOMEM; return GSS_S_FAILURE; } @@ -133,8 +177,9 @@ importKerberosKey(OM_uint32 *minor, KRB_KEY_LENGTH(key) = tmp.length; KRB_KEY_DATA(key) = (unsigned char *)tmp.value; - *pBuf += 8 + length; - *pRemain -= 8 + length; + *pBuf += 12 + length; + *pRemain -= 12 + length; + *pEncryptionType = encryptionType; *minor = 0; return GSS_S_COMPLETE; @@ -152,20 +197,21 @@ importName(OM_uint32 *minor, gss_buffer_desc tmp; if (remain < 4) { - *minor = ERANGE; + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } tmp.length = load_uint32_be(p); if (tmp.length != 0) { if (remain - 4 < tmp.length) { - *minor = ERANGE; + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } tmp.value = p + 4; - major = gssEapImportName(minor, &tmp, GSS_C_NT_EXPORT_NAME, pName); + major = gssEapImportNameInternal(minor, &tmp, pName, + EXPORT_NAME_FLAG_COMPOSITE); if (GSS_ERROR(major)) return major; } @@ -187,11 +233,11 @@ gssEapImportContext(OM_uint32 *minor, size_t remain = token->length; if (remain < 16) { - *minor = ERANGE; + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } if (load_uint32_be(&p[0]) != EAP_EXPORT_CONTEXT_V1) { - *minor = EINVAL; + *minor = GSSEAP_BAD_CONTEXT_TOKEN; return GSS_S_DEFECTIVE_TOKEN; } ctx->state = load_uint32_be(&p[4]); @@ -201,7 +247,7 @@ gssEapImportContext(OM_uint32 *minor, remain -= 16; /* Validate state */ - if (ctx->state < EAP_STATE_AUTHENTICATE || + if (ctx->state < EAP_STATE_IDENTITY || ctx->state > EAP_STATE_ESTABLISHED) return GSS_S_DEFECTIVE_TOKEN; @@ -213,12 +259,13 @@ gssEapImportContext(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - major = importKerberosKey(minor, &p, &remain, &ctx->rfc3961Key); + major = importKerberosKey(minor, &p, &remain, + &ctx->checksumType, + &ctx->encryptionType, + &ctx->rfc3961Key); if (GSS_ERROR(major)) return major; - ctx->encryptionType = KRB_KEY_TYPE(&ctx->rfc3961Key); - major = importName(minor, &p, &remain, &ctx->initiatorName); if (GSS_ERROR(major)) return major; @@ -235,7 +282,7 @@ gssEapImportContext(OM_uint32 *minor, } if (remain < 24 + sequenceSize(ctx->seqState)) { - *minor = ERANGE; + *minor = GSSEAP_WRONG_SIZE; return GSS_S_DEFECTIVE_TOKEN; } ctx->expiryTime = (time_t)load_uint64_be(&p[0]); /* XXX */ @@ -244,21 +291,25 @@ gssEapImportContext(OM_uint32 *minor, p += 24; remain -= 24; - *minor = sequenceInternalize(&ctx->seqState, &p, &remain); - if (*minor != 0) - return GSS_S_FAILURE; + major = sequenceInternalize(minor, &ctx->seqState, &p, &remain); + if (GSS_ERROR(major)) + return major; /* * The partial context should only be expected for unestablished * acceptor contexts. */ if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx)) { + assert((ctx->flags & CTX_FLAG_KRB_REAUTH_GSS) == 0); + major = gssEapImportPartialContext(minor, &p, &remain, ctx); if (GSS_ERROR(major)) return major; } +#ifdef GSSEAP_DEBUG assert(remain == 0); +#endif *minor = 0; major = GSS_S_COMPLETE; @@ -274,6 +325,7 @@ gss_import_sec_context(OM_uint32 *minor, 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 ||