~ubuntu-branches/ubuntu/utopic/moonshot-gss-eap/utopic-backports

« back to all changes in this revision

Viewing changes to mech_eap/export_sec_context.c

  • Committer: Package Import Robot
  • Author(s): Sam Hartman
  • Date: 2014-09-16 08:38:39 UTC
  • Revision ID: package-import@ubuntu.com-20140916083839-ipqco3thb1wcwvs0
Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2011, 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
 * Serialise a security context. On the acceptor, this may be partially
 
35
 * established.
 
36
 */
 
37
 
 
38
#include "gssapiP_eap.h"
 
39
 
 
40
#ifdef GSSEAP_ENABLE_ACCEPTOR
 
41
static OM_uint32
 
42
gssEapExportPartialContext(OM_uint32 *minor,
 
43
                           gss_ctx_id_t ctx,
 
44
                           gss_buffer_t token)
 
45
{
 
46
    OM_uint32 major, tmpMinor;
 
47
    size_t length, serverLen = 0;
 
48
    unsigned char *p;
 
49
    char serverBuf[MAXHOSTNAMELEN];
 
50
    if (ctx->acceptorCtx.radConn != NULL) {
 
51
        if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
 
52
                                     serverBuf, sizeof(serverBuf)) != 0) {
 
53
#if 0
 
54
            return gssEapRadiusMapError(minor,
 
55
                                        rs_err_conn_pop(ctx->acceptorCtx.radConn));
 
56
#else
 
57
            serverBuf[0] = '\0'; /* not implemented yet */
 
58
#endif
 
59
        }
 
60
        serverLen = strlen(serverBuf);
 
61
    }
 
62
    length = 4 + serverLen + 4 + ctx->acceptorCtx.state.length;
 
63
 
 
64
    token->value = GSSEAP_MALLOC(length);
 
65
    if (token->value == NULL) {
 
66
        major = GSS_S_FAILURE;
 
67
        *minor = ENOMEM;
 
68
        goto cleanup;
 
69
    }
 
70
    token->length = length;
 
71
 
 
72
    p = (unsigned char *)token->value;
 
73
 
 
74
    store_uint32_be(serverLen, p);
 
75
    p += 4;
 
76
    if (serverLen != 0) {
 
77
        memcpy(p, serverBuf, serverLen);
 
78
        p += serverLen;
 
79
    }
 
80
 
 
81
    store_uint32_be(ctx->acceptorCtx.state.length, p);
 
82
    p += 4;
 
83
    if (ctx->acceptorCtx.state.length != 0) {
 
84
        memcpy(p, ctx->acceptorCtx.state.value,
 
85
               ctx->acceptorCtx.state.length);
 
86
        p += ctx->acceptorCtx.state.length;
 
87
    }
 
88
 
 
89
    GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
 
90
 
 
91
    major = GSS_S_COMPLETE;
 
92
    *minor = 0;
 
93
 
 
94
cleanup:
 
95
    if (GSS_ERROR(major))
 
96
        gss_release_buffer(&tmpMinor, token);
 
97
 
 
98
    return major;
 
99
}
 
100
#endif /* GSSEAP_ENABLE_ACCEPTOR */
 
101
 
 
102
OM_uint32
 
103
gssEapExportSecContext(OM_uint32 *minor,
 
104
                       gss_ctx_id_t ctx,
 
105
                       gss_buffer_t token)
 
106
{
 
107
    OM_uint32 major, tmpMinor;
 
108
    size_t length;
 
109
    gss_buffer_desc initiatorName = GSS_C_EMPTY_BUFFER;
 
110
    gss_buffer_desc acceptorName = GSS_C_EMPTY_BUFFER;
 
111
    gss_buffer_desc partialCtx = GSS_C_EMPTY_BUFFER;
 
112
    gss_buffer_desc key;
 
113
    unsigned char *p;
 
114
 
 
115
    if ((CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx)) ||
 
116
        ctx->mechanismUsed == GSS_C_NO_OID) {
 
117
        *minor = GSSEAP_CONTEXT_INCOMPLETE;
 
118
        return GSS_S_NO_CONTEXT;
 
119
    }
 
120
 
 
121
    key.length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
 
122
    key.value  = KRB_KEY_DATA(&ctx->rfc3961Key);
 
123
 
 
124
    /*
 
125
     * As a shortcut, we omit the mechanism OID of the initiator name because
 
126
     * we know it will match the context mechanism. The acceptor name mech OID
 
127
     * is always included.
 
128
     */
 
129
    if (ctx->initiatorName != GSS_C_NO_NAME) {
 
130
        major = gssEapExportNameInternal(minor, ctx->initiatorName,
 
131
                                         &initiatorName,
 
132
                                         EXPORT_NAME_FLAG_COMPOSITE);
 
133
        if (GSS_ERROR(major))
 
134
            goto cleanup;
 
135
    }
 
136
 
 
137
    if (ctx->acceptorName != GSS_C_NO_NAME) {
 
138
        major = gssEapExportNameInternal(minor, ctx->acceptorName,
 
139
                                         &acceptorName,
 
140
                                         EXPORT_NAME_FLAG_OID | EXPORT_NAME_FLAG_COMPOSITE);
 
141
        if (GSS_ERROR(major))
 
142
            goto cleanup;
 
143
    }
 
144
 
 
145
#ifdef GSSEAP_ENABLE_ACCEPTOR
 
146
    /*
 
147
     * The partial context is only transmitted for unestablished acceptor
 
148
     * contexts.
 
149
     */
 
150
    if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
 
151
        (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
 
152
        major = gssEapExportPartialContext(minor, ctx, &partialCtx);
 
153
        if (GSS_ERROR(major))
 
154
            goto cleanup;
 
155
    }
 
156
#endif
 
157
 
 
158
    length  = 16;                               /* version, state, flags, */
 
159
    length += 4 + ctx->mechanismUsed->length;   /* mechanismUsed */
 
160
    length += 12 + key.length;                  /* rfc3961Key.value */
 
161
    length += 4 + initiatorName.length;         /* initiatorName.value */
 
162
    length += 4 + acceptorName.length;          /* acceptorName.value */
 
163
    length += 24 + sequenceSize(ctx->seqState); /* seqState */
 
164
 
 
165
    if (partialCtx.value != NULL)
 
166
        length += 4 + partialCtx.length;        /* partialCtx.value */
 
167
 
 
168
    token->value = GSSEAP_MALLOC(length);
 
169
    if (token->value == NULL) {
 
170
        major = GSS_S_FAILURE;
 
171
        *minor = ENOMEM;
 
172
        goto cleanup;
 
173
    }
 
174
    token->length = length;
 
175
 
 
176
    p = (unsigned char *)token->value;
 
177
 
 
178
    store_uint32_be(EAP_EXPORT_CONTEXT_V1, &p[0]);        /* version */
 
179
    store_uint32_be(GSSEAP_SM_STATE(ctx),  &p[4]);
 
180
    store_uint32_be(ctx->flags,            &p[8]);
 
181
    store_uint32_be(ctx->gssFlags,         &p[12]);
 
182
    p = store_oid(ctx->mechanismUsed,      &p[16]);
 
183
 
 
184
    store_uint32_be(ctx->checksumType,     &p[0]);
 
185
    store_uint32_be(ctx->encryptionType,   &p[4]);
 
186
    p = store_buffer(&key,                 &p[8], FALSE);
 
187
 
 
188
    p = store_buffer(&initiatorName,       p, FALSE);
 
189
    p = store_buffer(&acceptorName,        p, FALSE);
 
190
 
 
191
    store_uint64_be(ctx->expiryTime,       &p[0]);
 
192
    store_uint64_be(ctx->sendSeq,          &p[8]);
 
193
    store_uint64_be(ctx->recvSeq,          &p[16]);
 
194
    p += 24;
 
195
 
 
196
    major = sequenceExternalize(minor, ctx->seqState, &p, &length);
 
197
    if (GSS_ERROR(major))
 
198
        goto cleanup;
 
199
 
 
200
    if (partialCtx.value != NULL)
 
201
        p = store_buffer(&partialCtx, p, FALSE);
 
202
 
 
203
    GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
 
204
 
 
205
    major = GSS_S_COMPLETE;
 
206
    *minor = 0;
 
207
 
 
208
cleanup:
 
209
    if (GSS_ERROR(major))
 
210
        gss_release_buffer(&tmpMinor, token);
 
211
    gss_release_buffer(&tmpMinor, &initiatorName);
 
212
    gss_release_buffer(&tmpMinor, &acceptorName);
 
213
    gss_release_buffer(&tmpMinor, &partialCtx);
 
214
 
 
215
    return major;
 
216
}
 
217
 
 
218
OM_uint32 GSSAPI_CALLCONV
 
219
gss_export_sec_context(OM_uint32 *minor,
 
220
                       gss_ctx_id_t *context_handle,
 
221
                       gss_buffer_t interprocess_token)
 
222
{
 
223
    OM_uint32 major, tmpMinor;
 
224
    gss_ctx_id_t ctx = *context_handle;
 
225
 
 
226
    interprocess_token->length = 0;
 
227
    interprocess_token->value = NULL;
 
228
 
 
229
    if (ctx == GSS_C_NO_CONTEXT) {
 
230
        *minor = EINVAL;
 
231
        return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
 
232
    }
 
233
 
 
234
    *minor = 0;
 
235
 
 
236
    GSSEAP_MUTEX_LOCK(&ctx->mutex);
 
237
 
 
238
    major = gssEapExportSecContext(minor, ctx, interprocess_token);
 
239
    if (GSS_ERROR(major)) {
 
240
        GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
 
241
        return major;
 
242
    }
 
243
 
 
244
    *context_handle = GSS_C_NO_CONTEXT;
 
245
 
 
246
    GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
 
247
 
 
248
    gssEapReleaseContext(&tmpMinor, &ctx);
 
249
 
 
250
    return GSS_S_COMPLETE;
 
251
}