2 * Copyright (c) 2011, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Utility routines for context handles.
37 #include "gssapiP_eap.h"
40 gssEapAllocContext(OM_uint32 *minor,
46 assert(*pCtx == GSS_C_NO_CONTEXT);
48 ctx = (gss_ctx_id_t)GSSEAP_CALLOC(1, sizeof(*ctx));
54 if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
56 gssEapReleaseContext(&tmpMinor, &ctx);
60 ctx->state = GSSEAP_STATE_INITIAL;
63 * Integrity, confidentiality, sequencing and replay detection are
64 * always available. Regardless of what flags are requested in
65 * GSS_Init_sec_context, implementations MUST set the flag corresponding
66 * to these services in the output of GSS_Init_sec_context and
67 * GSS_Accept_sec_context.
69 ctx->gssFlags = GSS_C_TRANS_FLAG | /* exporting contexts */
70 GSS_C_INTEG_FLAG | /* integrity */
71 GSS_C_CONF_FLAG | /* confidentiality */
72 GSS_C_SEQUENCE_FLAG | /* sequencing */
73 GSS_C_REPLAY_FLAG; /* replay detection */
77 return GSS_S_COMPLETE;
81 releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx)
83 eap_peer_sm_deinit(ctx->eap);
87 releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
91 if (ctx->radConn != NULL)
92 rs_conn_destroy(ctx->radConn);
93 if (ctx->radContext != NULL)
94 rs_context_destroy(ctx->radContext);
95 if (ctx->radServer != NULL)
96 GSSEAP_FREE(ctx->radServer);
97 gss_release_buffer(&tmpMinor, &ctx->state);
99 gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
103 gssEapReleaseContext(OM_uint32 *minor,
107 gss_ctx_id_t ctx = *pCtx;
108 krb5_context krbContext = NULL;
110 if (ctx == GSS_C_NO_CONTEXT) {
111 return GSS_S_COMPLETE;
114 gssEapKerberosInit(&tmpMinor, &krbContext);
116 #ifdef GSSEAP_ENABLE_REAUTH
117 if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
118 gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
121 if (CTX_IS_INITIATOR(ctx)) {
122 releaseInitiatorContext(&ctx->initiatorCtx);
124 releaseAcceptorContext(&ctx->acceptorCtx);
127 krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
128 gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
129 gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
130 gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
131 sequenceFree(&tmpMinor, &ctx->seqState);
132 gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
133 gss_release_buffer(&tmpMinor, &ctx->conversation);
135 GSSEAP_MUTEX_DESTROY(&ctx->mutex);
137 memset(ctx, 0, sizeof(*ctx));
139 *pCtx = GSS_C_NO_CONTEXT;
142 return GSS_S_COMPLETE;
146 gssEapGetConversationMIC(OM_uint32 *minor,
148 gss_buffer_t convMIC)
151 gss_iov_buffer_desc iov[2];
153 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
154 iov[0].buffer = ctx->conversation;
156 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
157 iov[1].buffer.length = 0;
158 iov[1].buffer.value = NULL;
160 major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL, iov, 2, TOK_TYPE_MIC);
161 if (GSS_ERROR(major))
164 *convMIC = iov[1].buffer;
167 return GSS_S_COMPLETE;
171 gssEapVerifyConversationMIC(OM_uint32 *minor,
173 const gss_buffer_t convMIC)
176 gss_iov_buffer_desc iov[3];
178 size_t tokenHeaderLength;
180 if (convMIC == GSS_C_NO_BUFFER || convMIC->length < 16) {
181 *minor = GSSEAP_TOK_TRUNC;
182 return GSS_S_BAD_SIG;
185 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
186 iov[0].buffer = ctx->conversation;
189 * The conversation state already includes the MIC and its
190 * TLV header, as well as a header for emiting a subsequent
191 * token. These should not be included as input to verifyMIC.
193 tokenHeaderLength = ITOK_HEADER_LENGTH + convMIC->length
194 + 2 + ctx->mechanismUsed->length + 2;
195 assert(ctx->conversation.length > tokenHeaderLength);
196 iov[0].buffer.length -= tokenHeaderLength;
198 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
199 iov[1].buffer.length = 16;
200 iov[1].buffer.value = convMIC->value;
202 iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
203 iov[2].buffer.length = convMIC->length - 16;
204 iov[2].buffer.value = (unsigned char *)convMIC->value + 16;
206 major = gssEapUnwrapOrVerifyMIC(minor, ctx, &confState, NULL,
207 iov, 3, TOK_TYPE_MIC);