~ubuntu-branches/ubuntu/vivid/moonshot-gss-eap/vivid

« back to all changes in this revision

Viewing changes to mech_eap/util_cred.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
 * Utility routines for credential handles.
 
35
 */
 
36
 
 
37
#include "gssapiP_eap.h"
 
38
 
 
39
#ifdef WIN32
 
40
# include <shlobj.h>     /* may need to use ShFolder.h instead */
 
41
# include <stdio.h>
 
42
#else
 
43
# include <pwd.h>
 
44
#endif
 
45
 
 
46
OM_uint32
 
47
gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
 
48
{
 
49
    OM_uint32 tmpMinor;
 
50
    gss_cred_id_t cred;
 
51
 
 
52
    *pCred = GSS_C_NO_CREDENTIAL;
 
53
 
 
54
    cred = (gss_cred_id_t)GSSEAP_CALLOC(1, sizeof(*cred));
 
55
    if (cred == NULL) {
 
56
        *minor = ENOMEM;
 
57
        return GSS_S_FAILURE;
 
58
    }
 
59
 
 
60
    if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
 
61
        *minor = GSSEAP_GET_LAST_ERROR();
 
62
        gssEapReleaseCred(&tmpMinor, &cred);
 
63
        return GSS_S_FAILURE;
 
64
    }
 
65
 
 
66
    *pCred = cred;
 
67
 
 
68
    *minor = 0;
 
69
    return GSS_S_COMPLETE;
 
70
}
 
71
 
 
72
static void
 
73
zeroAndReleasePassword(gss_buffer_t password)
 
74
{
 
75
    GSSEAP_ASSERT(password != GSS_C_NO_BUFFER);
 
76
 
 
77
    if (password->value != NULL) {
 
78
        memset(password->value, 0, password->length);
 
79
        GSSEAP_FREE(password->value);
 
80
    }
 
81
 
 
82
    password->value = NULL;
 
83
    password->length = 0;
 
84
}
 
85
 
 
86
OM_uint32
 
87
gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
 
88
{
 
89
    OM_uint32 tmpMinor;
 
90
    gss_cred_id_t cred = *pCred;
 
91
    krb5_context krbContext = NULL;
 
92
 
 
93
    if (cred == GSS_C_NO_CREDENTIAL) {
 
94
        return GSS_S_COMPLETE;
 
95
    }
 
96
 
 
97
    GSSEAP_KRB_INIT(&krbContext);
 
98
 
 
99
    gssEapReleaseName(&tmpMinor, &cred->name);
 
100
    gssEapReleaseName(&tmpMinor, &cred->target);
 
101
 
 
102
    zeroAndReleasePassword(&cred->password);
 
103
 
 
104
    gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
 
105
    gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
 
106
    gss_release_buffer(&tmpMinor, &cred->caCertificate);
 
107
    gss_release_buffer(&tmpMinor, &cred->caCertificateBlob);
 
108
    gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
 
109
    gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
 
110
    gss_release_buffer(&tmpMinor, &cred->clientCertificate);
 
111
    gss_release_buffer(&tmpMinor, &cred->privateKey);
 
112
 
 
113
#ifdef GSSEAP_ENABLE_REAUTH
 
114
    if (cred->krbCredCache != NULL) {
 
115
        if (cred->flags & CRED_FLAG_DEFAULT_CCACHE)
 
116
            krb5_cc_close(krbContext, cred->krbCredCache);
 
117
        else
 
118
            krb5_cc_destroy(krbContext, cred->krbCredCache);
 
119
    }
 
120
    if (cred->reauthCred != GSS_C_NO_CREDENTIAL)
 
121
        gssReleaseCred(&tmpMinor, &cred->reauthCred);
 
122
#endif
 
123
 
 
124
    GSSEAP_MUTEX_DESTROY(&cred->mutex);
 
125
    memset(cred, 0, sizeof(*cred));
 
126
    GSSEAP_FREE(cred);
 
127
    *pCred = NULL;
 
128
 
 
129
    *minor = 0;
 
130
    return GSS_S_COMPLETE;
 
131
}
 
132
 
 
133
static OM_uint32
 
134
readStaticIdentityFile(OM_uint32 *minor,
 
135
                       gss_buffer_t defaultIdentity,
 
136
                       gss_buffer_t defaultPassword)
 
137
{
 
138
    OM_uint32 major, tmpMinor;
 
139
    FILE *fp = NULL;
 
140
    char buf[BUFSIZ];
 
141
    char *ccacheName;
 
142
    int i = 0;
 
143
#ifndef WIN32
 
144
    struct passwd *pw = NULL, pwd;
 
145
    char pwbuf[BUFSIZ];
 
146
#endif
 
147
 
 
148
    defaultIdentity->length = 0;
 
149
    defaultIdentity->value = NULL;
 
150
 
 
151
    if (defaultPassword != GSS_C_NO_BUFFER) {
 
152
        defaultPassword->length = 0;
 
153
        defaultPassword->value = NULL;
 
154
    }
 
155
 
 
156
    ccacheName = getenv("GSSEAP_IDENTITY");
 
157
    if (ccacheName == NULL) {
 
158
#ifdef WIN32
 
159
        TCHAR szPath[MAX_PATH];
 
160
 
 
161
        if (!SUCCEEDED(SHGetFolderPath(NULL,
 
162
                                       CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
 
163
                                       NULL, /* User access token */
 
164
                                       0,    /* SHGFP_TYPE_CURRENT */
 
165
                                       szPath))) {
 
166
            major = GSS_S_CRED_UNAVAIL;
 
167
            *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
 
168
            goto cleanup;
 
169
        }
 
170
 
 
171
        snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
 
172
#else
 
173
        if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
 
174
            pw == NULL || pw->pw_dir == NULL) {
 
175
            major = GSS_S_CRED_UNAVAIL;
 
176
            *minor = GSSEAP_GET_LAST_ERROR();
 
177
            goto cleanup;
 
178
        }
 
179
 
 
180
        snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
 
181
#endif /* WIN32 */
 
182
        ccacheName = buf;
 
183
    }
 
184
 
 
185
    fp = fopen(ccacheName, "r");
 
186
    if (fp == NULL) {
 
187
        major = GSS_S_CRED_UNAVAIL;
 
188
        *minor = GSSEAP_NO_DEFAULT_CRED;
 
189
        goto cleanup;
 
190
    }
 
191
 
 
192
    while (fgets(buf, sizeof(buf), fp) != NULL) {
 
193
        gss_buffer_desc src, *dst;
 
194
 
 
195
        src.length = strlen(buf);
 
196
        src.value = buf;
 
197
 
 
198
        if (src.length == 0)
 
199
            break;
 
200
 
 
201
        if (buf[src.length - 1] == '\n') {
 
202
            buf[src.length - 1] = '\0';
 
203
            if (--src.length == 0)
 
204
                break;
 
205
        }
 
206
 
 
207
        if (i == 0)
 
208
            dst = defaultIdentity;
 
209
        else if (i == 1)
 
210
            dst = defaultPassword;
 
211
        else
 
212
            break;
 
213
 
 
214
        if (dst != GSS_C_NO_BUFFER) {
 
215
            major = duplicateBuffer(minor, &src, dst);
 
216
            if (GSS_ERROR(major))
 
217
                goto cleanup;
 
218
        }
 
219
 
 
220
        i++;
 
221
    }
 
222
 
 
223
    if (defaultIdentity->length == 0) {
 
224
        major = GSS_S_CRED_UNAVAIL;
 
225
        *minor = GSSEAP_NO_DEFAULT_CRED;
 
226
        goto cleanup;
 
227
    }
 
228
 
 
229
    major = GSS_S_COMPLETE;
 
230
    *minor = 0;
 
231
 
 
232
cleanup:
 
233
    if (fp != NULL)
 
234
        fclose(fp);
 
235
 
 
236
    if (GSS_ERROR(major)) {
 
237
        gss_release_buffer(&tmpMinor, defaultIdentity);
 
238
        zeroAndReleasePassword(defaultPassword);
 
239
    }
 
240
 
 
241
    memset(buf, 0, sizeof(buf));
 
242
 
 
243
    return major;
 
244
}
 
245
 
 
246
gss_OID
 
247
gssEapPrimaryMechForCred(gss_cred_id_t cred)
 
248
{
 
249
    gss_OID credMech = GSS_C_NO_OID;
 
250
 
 
251
    if (cred != GSS_C_NO_CREDENTIAL &&
 
252
        cred->mechanisms != GSS_C_NO_OID_SET &&
 
253
        cred->mechanisms->count == 1)
 
254
        credMech = &cred->mechanisms->elements[0];
 
255
 
 
256
    return credMech;
 
257
}
 
258
 
 
259
OM_uint32
 
260
gssEapAcquireCred(OM_uint32 *minor,
 
261
                  const gss_name_t desiredName,
 
262
                  OM_uint32 timeReq GSSEAP_UNUSED,
 
263
                  const gss_OID_set desiredMechs,
 
264
                  int credUsage,
 
265
                  gss_cred_id_t *pCred,
 
266
                  gss_OID_set *pActualMechs,
 
267
                  OM_uint32 *timeRec)
 
268
{
 
269
    OM_uint32 major, tmpMinor;
 
270
    gss_cred_id_t cred;
 
271
 
 
272
    /* XXX TODO validate with changed set_cred_option API */
 
273
    *pCred = GSS_C_NO_CREDENTIAL;
 
274
 
 
275
    major = gssEapAllocCred(minor, &cred);
 
276
    if (GSS_ERROR(major))
 
277
        goto cleanup;
 
278
 
 
279
    switch (credUsage) {
 
280
    case GSS_C_BOTH:
 
281
        cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT;
 
282
        break;
 
283
    case GSS_C_INITIATE:
 
284
        cred->flags |= CRED_FLAG_INITIATE;
 
285
        break;
 
286
    case GSS_C_ACCEPT:
 
287
        cred->flags |= CRED_FLAG_ACCEPT;
 
288
        break;
 
289
    default:
 
290
        major = GSS_S_FAILURE;
 
291
        *minor = GSSEAP_BAD_USAGE;
 
292
        goto cleanup;
 
293
        break;
 
294
    }
 
295
 
 
296
    major = gssEapValidateMechs(minor, desiredMechs);
 
297
    if (GSS_ERROR(major))
 
298
        goto cleanup;
 
299
 
 
300
    major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
 
301
    if (GSS_ERROR(major))
 
302
        goto cleanup;
 
303
 
 
304
    if (desiredName != GSS_C_NO_NAME) {
 
305
        GSSEAP_MUTEX_LOCK(&desiredName->mutex);
 
306
 
 
307
        major = gssEapDuplicateName(minor, desiredName, &cred->name);
 
308
        if (GSS_ERROR(major)) {
 
309
            GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
 
310
            goto cleanup;
 
311
        }
 
312
 
 
313
        GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
 
314
    }
 
315
 
 
316
#ifdef GSSEAP_ENABLE_ACCEPTOR
 
317
    if (cred->flags & CRED_FLAG_ACCEPT) {
 
318
        struct rs_context *radContext;
 
319
 
 
320
        major = gssEapCreateRadiusContext(minor, cred, &radContext);
 
321
        if (GSS_ERROR(major))
 
322
            goto cleanup;
 
323
 
 
324
        rs_context_destroy(radContext);
 
325
    }
 
326
#endif
 
327
 
 
328
    if (pActualMechs != NULL) {
 
329
        major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
 
330
        if (GSS_ERROR(major))
 
331
            goto cleanup;
 
332
    }
 
333
 
 
334
    if (timeRec != NULL)
 
335
        *timeRec = GSS_C_INDEFINITE;
 
336
 
 
337
    *pCred = cred;
 
338
 
 
339
    major = GSS_S_COMPLETE;
 
340
    *minor = 0;
 
341
 
 
342
cleanup:
 
343
    if (GSS_ERROR(major))
 
344
        gssEapReleaseCred(&tmpMinor, &cred);
 
345
 
 
346
    return major;
 
347
}
 
348
 
 
349
/*
 
350
 * Return TRUE if cred available for mechanism. Caller need no acquire
 
351
 * lock because mechanisms list is immutable.
 
352
 */
 
353
int
 
354
gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech)
 
355
{
 
356
    OM_uint32 minor;
 
357
    int present = 0;
 
358
 
 
359
    GSSEAP_ASSERT(mech != GSS_C_NO_OID);
 
360
 
 
361
    if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
 
362
        return TRUE;
 
363
 
 
364
    gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present);
 
365
 
 
366
    return present;
 
367
}
 
368
 
 
369
static OM_uint32
 
370
staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
 
371
                                         const gss_cred_id_t cred,
 
372
                                         gss_name_t *pName)
 
373
{
 
374
    OM_uint32 major, tmpMinor;
 
375
    gss_OID nameMech = gssEapPrimaryMechForCred(cred);
 
376
    gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
 
377
 
 
378
    *pName = GSS_C_NO_NAME;
 
379
 
 
380
    major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
 
381
    if (major == GSS_S_COMPLETE) {
 
382
        major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
 
383
                                 nameMech, pName);
 
384
    }
 
385
 
 
386
    gss_release_buffer(&tmpMinor, &defaultIdentity);
 
387
 
 
388
    return major;
 
389
}
 
390
 
 
391
static OM_uint32
 
392
gssEapResolveCredIdentity(OM_uint32 *minor,
 
393
                          gss_cred_id_t cred)
 
394
{
 
395
    OM_uint32 major;
 
396
    gss_OID nameMech = gssEapPrimaryMechForCred(cred);
 
397
 
 
398
    if (cred->name != GSS_C_NO_NAME) {
 
399
        *minor = 0;
 
400
        return GSS_S_COMPLETE;
 
401
    }
 
402
 
 
403
    if (cred->flags & CRED_FLAG_ACCEPT) {
 
404
        gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
 
405
        char serviceName[5 + MAXHOSTNAMELEN];
 
406
 
 
407
        /* default host-based service is host@localhost */
 
408
        memcpy(serviceName, "host@", 5);
 
409
        if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
 
410
            *minor = GSSEAP_NO_HOSTNAME;
 
411
            return GSS_S_FAILURE;
 
412
        }
 
413
 
 
414
        nameBuf.value = serviceName;
 
415
        nameBuf.length = strlen((char *)nameBuf.value);
 
416
 
 
417
        major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
 
418
                                 nameMech, &cred->name);
 
419
        if (GSS_ERROR(major))
 
420
            return major;
 
421
    } else if (cred->flags & CRED_FLAG_INITIATE) {
 
422
#ifdef HAVE_MOONSHOT_GET_IDENTITY
 
423
        major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
 
424
        if (major == GSS_S_CRED_UNAVAIL)
 
425
#endif
 
426
            major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
 
427
        if (major != GSS_S_CRED_UNAVAIL)
 
428
            return major;
 
429
    }
 
430
 
 
431
    *minor = 0;
 
432
    return GSS_S_COMPLETE;
 
433
}
 
434
 
 
435
OM_uint32
 
436
gssEapInquireCred(OM_uint32 *minor,
 
437
                  gss_cred_id_t cred,
 
438
                  gss_name_t *name,
 
439
                  OM_uint32 *pLifetime,
 
440
                  gss_cred_usage_t *cred_usage,
 
441
                  gss_OID_set *mechanisms)
 
442
{
 
443
    OM_uint32 major;
 
444
    time_t now, lifetime;
 
445
 
 
446
    if (name != NULL) {
 
447
        major = gssEapResolveCredIdentity(minor, cred);
 
448
        if (GSS_ERROR(major))
 
449
            goto cleanup;
 
450
 
 
451
        if (cred->name != GSS_C_NO_NAME) {
 
452
            major = gssEapDuplicateName(minor, cred->name, name);
 
453
            if (GSS_ERROR(major))
 
454
                goto cleanup;
 
455
        } else
 
456
            *name = GSS_C_NO_NAME;
 
457
    }
 
458
 
 
459
    if (cred_usage != NULL) {
 
460
        OM_uint32 flags = (cred->flags & (CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT));
 
461
 
 
462
        switch (flags) {
 
463
        case CRED_FLAG_INITIATE:
 
464
            *cred_usage = GSS_C_INITIATE;
 
465
            break;
 
466
        case CRED_FLAG_ACCEPT:
 
467
            *cred_usage = GSS_C_ACCEPT;
 
468
            break;
 
469
        default:
 
470
            *cred_usage = GSS_C_BOTH;
 
471
            break;
 
472
        }
 
473
    }
 
474
 
 
475
    if (mechanisms != NULL) {
 
476
        if (cred->mechanisms != GSS_C_NO_OID_SET)
 
477
            major = duplicateOidSet(minor, cred->mechanisms, mechanisms);
 
478
        else
 
479
            major = gssEapIndicateMechs(minor, mechanisms);
 
480
        if (GSS_ERROR(major))
 
481
            goto cleanup;
 
482
    }
 
483
 
 
484
    if (cred->expiryTime == 0) {
 
485
        lifetime = GSS_C_INDEFINITE;
 
486
    } else  {
 
487
        now = time(NULL);
 
488
        lifetime = now - cred->expiryTime;
 
489
        if (lifetime < 0)
 
490
            lifetime = 0;
 
491
    }
 
492
 
 
493
    if (pLifetime != NULL) {
 
494
        *pLifetime = lifetime;
 
495
    }
 
496
 
 
497
    if (lifetime == 0) {
 
498
        major = GSS_S_CREDENTIALS_EXPIRED;
 
499
        *minor = GSSEAP_CRED_EXPIRED;
 
500
        goto cleanup;
 
501
    }
 
502
 
 
503
    major = GSS_S_COMPLETE;
 
504
    *minor = 0;
 
505
 
 
506
cleanup:
 
507
    return major;
 
508
}
 
509
 
 
510
OM_uint32
 
511
gssEapSetCredPassword(OM_uint32 *minor,
 
512
                      gss_cred_id_t cred,
 
513
                      const gss_buffer_t password)
 
514
{
 
515
    OM_uint32 major, tmpMinor;
 
516
    gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
 
517
 
 
518
    if (cred->flags & CRED_FLAG_RESOLVED) {
 
519
        major = GSS_S_FAILURE;
 
520
        *minor = GSSEAP_CRED_RESOLVED;
 
521
        goto cleanup;
 
522
    }
 
523
 
 
524
    if (password != GSS_C_NO_BUFFER) {
 
525
        major = duplicateBuffer(minor, password, &newPassword);
 
526
        if (GSS_ERROR(major))
 
527
            goto cleanup;
 
528
 
 
529
        cred->flags |= CRED_FLAG_PASSWORD;
 
530
    } else {
 
531
        cred->flags &= ~(CRED_FLAG_PASSWORD);
 
532
    }
 
533
 
 
534
    gss_release_buffer(&tmpMinor, &cred->password);
 
535
    cred->password = newPassword;
 
536
 
 
537
    major = GSS_S_COMPLETE;
 
538
    *minor = 0;
 
539
 
 
540
cleanup:
 
541
    return major;
 
542
}
 
543
 
 
544
/*
 
545
 * Currently only the privateKey path is exposed to the application
 
546
 * (via gss_set_cred_option() or the third line in ~/.gss_eap_id).
 
547
 * At some point in the future we may add support for setting the
 
548
 * client certificate separately.
 
549
 */
 
550
OM_uint32
 
551
gssEapSetCredClientCertificate(OM_uint32 *minor,
 
552
                              gss_cred_id_t cred,
 
553
                              const gss_buffer_t clientCert,
 
554
                              const gss_buffer_t privateKey)
 
555
{
 
556
    OM_uint32 major, tmpMinor;
 
557
    gss_buffer_desc newClientCert = GSS_C_EMPTY_BUFFER;
 
558
    gss_buffer_desc newPrivateKey = GSS_C_EMPTY_BUFFER;
 
559
 
 
560
    if (cred->flags & CRED_FLAG_RESOLVED) {
 
561
        major = GSS_S_FAILURE;
 
562
        *minor = GSSEAP_CRED_RESOLVED;
 
563
        goto cleanup;
 
564
    }
 
565
 
 
566
    if (clientCert == GSS_C_NO_BUFFER &&
 
567
        privateKey == GSS_C_NO_BUFFER) {
 
568
        cred->flags &= ~(CRED_FLAG_CERTIFICATE);
 
569
        major = GSS_S_COMPLETE;
 
570
        *minor = 0;
 
571
        goto cleanup;
 
572
    }
 
573
 
 
574
    if (clientCert != GSS_C_NO_BUFFER) {
 
575
        major = duplicateBuffer(minor, clientCert, &newClientCert);
 
576
        if (GSS_ERROR(major))
 
577
            goto cleanup;
 
578
    }
 
579
 
 
580
    if (privateKey != GSS_C_NO_BUFFER) {
 
581
        major = duplicateBuffer(minor, privateKey, &newPrivateKey);
 
582
        if (GSS_ERROR(major))
 
583
            goto cleanup;
 
584
    }
 
585
 
 
586
    cred->flags |= CRED_FLAG_CERTIFICATE;
 
587
 
 
588
    gss_release_buffer(&tmpMinor, &cred->clientCertificate);
 
589
    cred->clientCertificate = newClientCert;
 
590
 
 
591
    gss_release_buffer(&tmpMinor, &cred->privateKey);
 
592
    cred->privateKey = newPrivateKey;
 
593
 
 
594
    major = GSS_S_COMPLETE;
 
595
    *minor = 0;
 
596
 
 
597
cleanup:
 
598
    if (GSS_ERROR(major)) {
 
599
        gss_release_buffer(&tmpMinor, &newClientCert);
 
600
        gss_release_buffer(&tmpMinor, &newPrivateKey);
 
601
    }
 
602
 
 
603
    return major;
 
604
}
 
605
 
 
606
OM_uint32
 
607
gssEapSetCredService(OM_uint32 *minor,
 
608
                     gss_cred_id_t cred,
 
609
                     const gss_name_t target)
 
610
{
 
611
    OM_uint32 major, tmpMinor;
 
612
    gss_name_t newTarget = GSS_C_NO_NAME;
 
613
 
 
614
    if (cred->flags & CRED_FLAG_RESOLVED) {
 
615
        major = GSS_S_FAILURE;
 
616
        *minor = GSSEAP_CRED_RESOLVED;
 
617
        goto cleanup;
 
618
    }
 
619
 
 
620
    if (target != GSS_C_NO_NAME) {
 
621
        major = gssEapDuplicateName(minor, target, &newTarget);
 
622
        if (GSS_ERROR(major))
 
623
            goto cleanup;
 
624
 
 
625
        cred->flags |= CRED_FLAG_TARGET;
 
626
    } else {
 
627
        cred->flags &= ~(CRED_FLAG_TARGET);
 
628
    }
 
629
 
 
630
    gssEapReleaseName(&tmpMinor, &cred->target);
 
631
    cred->target = newTarget;
 
632
 
 
633
    major = GSS_S_COMPLETE;
 
634
    *minor = 0;
 
635
 
 
636
cleanup:
 
637
    return major;
 
638
}
 
639
 
 
640
static OM_uint32
 
641
gssEapDuplicateCred(OM_uint32 *minor,
 
642
                    const gss_cred_id_t src,
 
643
                    gss_cred_id_t *pDst)
 
644
{
 
645
    OM_uint32 major, tmpMinor;
 
646
    gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
 
647
 
 
648
    *pDst = GSS_C_NO_CREDENTIAL;
 
649
 
 
650
    major = gssEapAllocCred(minor, &dst);
 
651
    if (GSS_ERROR(major))
 
652
        goto cleanup;
 
653
 
 
654
    dst->flags = src->flags;
 
655
 
 
656
    if (src->name != GSS_C_NO_NAME) {
 
657
        major = gssEapDuplicateName(minor, src->name, &dst->name);
 
658
        if (GSS_ERROR(major))
 
659
            goto cleanup;
 
660
    }
 
661
 
 
662
    if (src->target != GSS_C_NO_NAME) {
 
663
        major = gssEapDuplicateName(minor, src->target, &dst->target);
 
664
        if (GSS_ERROR(major))
 
665
            goto cleanup;
 
666
    }
 
667
 
 
668
    if (src->password.value != NULL) {
 
669
        major = duplicateBuffer(minor, &src->password, &dst->password);
 
670
        if (GSS_ERROR(major))
 
671
            goto cleanup;
 
672
    }
 
673
 
 
674
    major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
 
675
    if (GSS_ERROR(major))
 
676
        goto cleanup;
 
677
 
 
678
    dst->expiryTime = src->expiryTime;
 
679
 
 
680
    if (src->radiusConfigFile.value != NULL)
 
681
        duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
 
682
    if (src->radiusConfigStanza.value != NULL)
 
683
        duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
 
684
    if (src->caCertificate.value != NULL)
 
685
        duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
 
686
    if (src->caCertificateBlob.value != NULL)
 
687
        duplicateBufferOrCleanup(&src->caCertificateBlob, &dst->caCertificateBlob);
 
688
    if (src->subjectNameConstraint.value != NULL)
 
689
        duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
 
690
    if (src->subjectAltNameConstraint.value != NULL)
 
691
        duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
 
692
    if (src->clientCertificate.value != NULL)
 
693
        duplicateBufferOrCleanup(&src->clientCertificate, &dst->clientCertificate);
 
694
    if (src->privateKey.value != NULL)
 
695
        duplicateBufferOrCleanup(&src->privateKey, &dst->privateKey);
 
696
 
 
697
#ifdef GSSEAP_ENABLE_REAUTH
 
698
    /* XXX krbCredCache, reauthCred */
 
699
#endif
 
700
 
 
701
    *pDst = dst;
 
702
    dst = GSS_C_NO_CREDENTIAL;
 
703
 
 
704
    major = GSS_S_COMPLETE;
 
705
    *minor = 0;
 
706
 
 
707
cleanup:
 
708
    gssEapReleaseCred(&tmpMinor, &dst);
 
709
 
 
710
    return major;
 
711
}
 
712
 
 
713
static OM_uint32
 
714
staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
 
715
{
 
716
    OM_uint32 major, tmpMinor;
 
717
    gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
 
718
    gss_name_t defaultIdentityName = GSS_C_NO_NAME;
 
719
    gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
 
720
    int isDefaultIdentity = FALSE;
 
721
 
 
722
    major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
 
723
    if (GSS_ERROR(major))
 
724
        goto cleanup;
 
725
 
 
726
    major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
 
727
                             gssEapPrimaryMechForCred(cred), &defaultIdentityName);
 
728
    if (GSS_ERROR(major))
 
729
        goto cleanup;
 
730
 
 
731
    if (defaultIdentityName == GSS_C_NO_NAME) {
 
732
        if (cred->name == GSS_C_NO_NAME) {
 
733
            major = GSS_S_CRED_UNAVAIL;
 
734
            *minor = GSSEAP_NO_DEFAULT_IDENTITY;
 
735
            goto cleanup;
 
736
        }
 
737
    } else {
 
738
        if (cred->name == GSS_C_NO_NAME) {
 
739
            cred->name = defaultIdentityName;
 
740
            defaultIdentityName = GSS_C_NO_NAME;
 
741
            isDefaultIdentity = TRUE;
 
742
        } else {
 
743
            major = gssEapCompareName(minor, cred->name,
 
744
                                      defaultIdentityName, 0,
 
745
                                      &isDefaultIdentity);
 
746
            if (GSS_ERROR(major))
 
747
                goto cleanup;
 
748
        }
 
749
    }
 
750
 
 
751
    if (isDefaultIdentity &&
 
752
        (cred->flags & CRED_FLAG_PASSWORD) == 0) {
 
753
        major = gssEapSetCredPassword(minor, cred, &defaultPassword);
 
754
        if (GSS_ERROR(major))
 
755
            goto cleanup;
 
756
    }
 
757
 
 
758
cleanup:
 
759
    gssEapReleaseName(&tmpMinor, &defaultIdentityName);
 
760
    zeroAndReleasePassword(&defaultPassword);
 
761
    gss_release_buffer(&tmpMinor, &defaultIdentity);
 
762
 
 
763
    return major;
 
764
}
 
765
 
 
766
OM_uint32
 
767
gssEapResolveInitiatorCred(OM_uint32 *minor,
 
768
                           const gss_cred_id_t cred,
 
769
                           const gss_name_t targetName
 
770
#ifndef HAVE_MOONSHOT_GET_IDENTITY
 
771
                                                       GSSEAP_UNUSED
 
772
#endif
 
773
                           ,
 
774
                           gss_cred_id_t *pResolvedCred)
 
775
{
 
776
    OM_uint32 major, tmpMinor;
 
777
    gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
 
778
 
 
779
    if (cred == GSS_C_NO_CREDENTIAL) {
 
780
        major = gssEapAcquireCred(minor,
 
781
                                  GSS_C_NO_NAME,
 
782
                                  GSS_C_INDEFINITE,
 
783
                                  GSS_C_NO_OID_SET,
 
784
                                  GSS_C_INITIATE,
 
785
                                  &resolvedCred,
 
786
                                  NULL,
 
787
                                  NULL);
 
788
        if (GSS_ERROR(major))
 
789
            goto cleanup;
 
790
    } else {
 
791
        if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
 
792
            major = GSS_S_NO_CRED;
 
793
            *minor = GSSEAP_CRED_USAGE_MISMATCH;
 
794
            goto cleanup;
 
795
        }
 
796
 
 
797
        major = gssEapDuplicateCred(minor, cred, &resolvedCred);
 
798
        if (GSS_ERROR(major))
 
799
            goto cleanup;
 
800
    }
 
801
 
 
802
    if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
 
803
#ifdef HAVE_MOONSHOT_GET_IDENTITY
 
804
        major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
 
805
        if (major == GSS_S_CRED_UNAVAIL)
 
806
#endif
 
807
            major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
 
808
        if (GSS_ERROR(major) && major != GSS_S_CRED_UNAVAIL)
 
809
            goto cleanup;
 
810
 
 
811
        /* If we have a caller-supplied password, the credential is resolved. */
 
812
        if ((resolvedCred->flags &
 
813
             (CRED_FLAG_PASSWORD | CRED_FLAG_CERTIFICATE)) == 0) {
 
814
            major = GSS_S_CRED_UNAVAIL;
 
815
            *minor = GSSEAP_NO_DEFAULT_CRED;
 
816
            goto cleanup;
 
817
        }
 
818
 
 
819
        resolvedCred->flags |= CRED_FLAG_RESOLVED;
 
820
    }
 
821
 
 
822
    *pResolvedCred = resolvedCred;
 
823
    resolvedCred = GSS_C_NO_CREDENTIAL;
 
824
 
 
825
    major = GSS_S_COMPLETE;
 
826
    *minor = 0;
 
827
 
 
828
cleanup:
 
829
    gssEapReleaseCred(&tmpMinor, &resolvedCred);
 
830
 
 
831
    return major;
 
832
}