MIT build fixes
[mech_eap.orig] / util_context.c
1 /*
2  * Copyright (c) 2010, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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
30  * SUCH DAMAGE.
31  */
32
33 /*
34  * Utility routines for context handles.
35  */
36
37 #include "gssapiP_eap.h"
38
39 OM_uint32
40 gssEapAllocContext(OM_uint32 *minor,
41                    gss_ctx_id_t *pCtx)
42 {
43     OM_uint32 tmpMinor;
44     gss_ctx_id_t ctx;
45
46     assert(*pCtx == GSS_C_NO_CONTEXT);
47
48     ctx = (gss_ctx_id_t)GSSEAP_CALLOC(1, sizeof(*ctx));
49     if (ctx == NULL) {
50         *minor = ENOMEM;
51         return GSS_S_FAILURE;
52     }
53
54     if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
55         *minor = errno;
56         gssEapReleaseContext(&tmpMinor, &ctx);
57         return GSS_S_FAILURE;
58     }
59
60     ctx->state = GSSEAP_STATE_IDENTITY;
61
62     /*
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.
68     */
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 */
74
75     *pCtx = ctx;
76
77     return GSS_S_COMPLETE;
78 }
79
80 static void
81 releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx)
82 {
83     OM_uint32 minor;
84
85     gssEapReleaseCred(&minor, &ctx->defaultCred);
86     eap_peer_sm_deinit(ctx->eap);
87 }
88
89 static void
90 releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
91 {
92     OM_uint32 tmpMinor;
93
94     if (ctx->radConn != NULL)
95         rs_conn_destroy(ctx->radConn);
96     if (ctx->radContext != NULL)
97         rs_context_destroy(ctx->radContext);
98     if (ctx->radServer != NULL)
99         GSSEAP_FREE(ctx->radServer);
100     gss_release_buffer(&tmpMinor, &ctx->state);
101     if (ctx->vps != NULL)
102         gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
103 }
104
105 OM_uint32
106 gssEapReleaseContext(OM_uint32 *minor,
107                      gss_ctx_id_t *pCtx)
108 {
109     OM_uint32 tmpMinor;
110     gss_ctx_id_t ctx = *pCtx;
111     krb5_context krbContext = NULL;
112
113     if (ctx == GSS_C_NO_CONTEXT) {
114         return GSS_S_COMPLETE;
115     }
116
117     gssEapKerberosInit(&tmpMinor, &krbContext);
118
119 #ifdef GSSEAP_ENABLE_REAUTH
120     if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
121         gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
122     } else
123 #endif
124     if (CTX_IS_INITIATOR(ctx)) {
125         releaseInitiatorContext(&ctx->initiatorCtx);
126     } else {
127         releaseAcceptorContext(&ctx->acceptorCtx);
128     }
129
130     krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
131     gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
132     gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
133     gss_release_oid(&tmpMinor, &ctx->mechanismUsed);
134     sequenceFree(&tmpMinor, &ctx->seqState);
135
136     GSSEAP_MUTEX_DESTROY(&ctx->mutex);
137
138     memset(ctx, 0, sizeof(*ctx));
139     GSSEAP_FREE(ctx);
140     *pCtx = GSS_C_NO_CONTEXT;
141
142     *minor = 0;
143     return GSS_S_COMPLETE;
144 }
145
146 OM_uint32
147 gssEapMakeToken(OM_uint32 *minor,
148                 gss_ctx_id_t ctx,
149                 const gss_buffer_t innerToken,
150                 enum gss_eap_token_type tokenType,
151                 gss_buffer_t outputToken)
152 {
153     unsigned char *p;
154
155     outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
156     outputToken->value = GSSEAP_MALLOC(outputToken->length);
157     if (outputToken->value == NULL) {
158         *minor = ENOMEM;
159         return GSS_S_FAILURE;
160     }
161
162     p = (unsigned char *)outputToken->value;
163     makeTokenHeader(ctx->mechanismUsed, innerToken->length, &p, tokenType);
164     memcpy(p, innerToken->value, innerToken->length);
165
166     *minor = 0;
167     return GSS_S_COMPLETE;
168 }
169
170 OM_uint32
171 gssEapVerifyToken(OM_uint32 *minor,
172                   gss_ctx_id_t ctx,
173                   const gss_buffer_t inputToken,
174                   enum gss_eap_token_type *actualToken,
175                   gss_buffer_t innerInputToken)
176 {
177     OM_uint32 major;
178     size_t bodySize;
179     unsigned char *p = (unsigned char *)inputToken->value;
180     gss_OID_desc oidBuf;
181     gss_OID oid;
182
183     if (ctx->mechanismUsed != GSS_C_NO_OID) {
184         oid = ctx->mechanismUsed;
185     } else {
186         oidBuf.elements = NULL;
187         oidBuf.length = 0;
188         oid = &oidBuf;
189     }
190
191     major = verifyTokenHeader(minor, oid, &bodySize, &p,
192                               inputToken->length, actualToken);
193     if (GSS_ERROR(major))
194         return major;
195
196     if (ctx->mechanismUsed == GSS_C_NO_OID) {
197         if (!gssEapIsConcreteMechanismOid(oid)) {
198             *minor = GSSEAP_WRONG_MECH;
199             return GSS_S_BAD_MECH;
200         }
201
202         if (!gssEapInternalizeOid(oid, &ctx->mechanismUsed)) {
203             major = duplicateOid(minor, oid, &ctx->mechanismUsed);
204             if (GSS_ERROR(major))
205                 return major;
206         }
207     }
208
209     innerInputToken->length = bodySize;
210     innerInputToken->value = p;
211
212     *minor = 0;
213     return GSS_S_COMPLETE;
214 }
215
216 OM_uint32
217 gssEapContextTime(OM_uint32 *minor,
218                   gss_ctx_id_t context_handle,
219                   OM_uint32 *time_rec)
220 {
221     if (context_handle->expiryTime == 0) {
222         *time_rec = GSS_C_INDEFINITE;
223     } else {
224         time_t now, lifetime;
225
226         time(&now);
227         lifetime = context_handle->expiryTime - now;
228         if (lifetime <= 0) {
229             *time_rec = 0;
230             return GSS_S_CONTEXT_EXPIRED;
231         }
232         *time_rec = lifetime;
233     }
234
235     return GSS_S_COMPLETE;
236 }