~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/windows/identity/plugins/common/krb5common.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-10-30 10:28:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20061030102853-x7v876vw4af46v0m
Tags: 1.4.4-3ubuntu1
* Merge with Debian; only Ubuntu change:
  - src/include/k5-thread.h: Define__USE_GNU when #include'ing pthread.h to
    fix FTBFS (from 1.4.3-9ubuntu1).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2004 Massachusetts Institute of Technology
 
2
 * Copyright (c) 2005 Massachusetts Institute of Technology
3
3
 *
4
4
 * Permission is hereby granted, free of charge, to any person
5
5
 * obtaining a copy of this software and associated documentation
25
25
/* $Id$ */
26
26
 
27
27
#include<windows.h>
28
 
#include<kcreddb.h>
29
 
#include<kherror.h>
 
28
#include<netidmgr.h>
30
29
#include<dynimport.h>
 
30
#include<krb5common.h>
 
31
#ifdef DEBUG
 
32
#include<assert.h>
 
33
#endif
 
34
#include<strsafe.h>
31
35
 
32
36
/**************************************/
33
37
/* khm_krb5_error():           */
88
92
 
89
93
    LPCSTR          functionName;
90
94
    int             freeContextFlag;
91
 
    krb5_error_code     rc;
 
95
    krb5_error_code     rc = 0;
92
96
    krb5_flags          flags = 0;
93
97
 
94
98
    if (pkrb5_init_context == NULL)
95
99
        return 1;
96
100
 
97
 
    if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx)))
98
 
    {
 
101
    if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) {
99
102
        functionName = "krb5_init_context()";
100
103
        freeContextFlag = 0;
101
104
        goto on_error;
102
105
    }
103
106
 
104
107
    if(*cache == 0) {
105
 
        wchar_t wccname[256];
 
108
        wchar_t wccname[MAX_PATH];
106
109
        khm_size cbwccname;
107
110
 
108
111
        if(ident != NULL) {
110
113
            do {
111
114
                char ccname[256];
112
115
 
113
 
                if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName", NULL, wccname, &cbwccname)))
114
 
                    break;
 
116
                if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName",
 
117
                                                       NULL, wccname,
 
118
                                                       &cbwccname))) {
 
119
                    cbwccname = sizeof(wccname);
 
120
                    if (KHM_FAILED
 
121
                        (khm_krb5_find_ccache_for_identity(ident,
 
122
                                                           ctx,
 
123
                                                           wccname,
 
124
                                                           &cbwccname))) {
 
125
#ifdef DEBUG_LIKE_A_MADMAN
 
126
                        assert(FALSE);
 
127
#endif
 
128
                        break;
 
129
                    }
 
130
                }
115
131
 
116
132
                if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0)
117
133
                    break;
124
140
            } while(FALSE);
125
141
        }
126
142
 
127
 
        if (*cache == 0 && (rc = (*pkrb5_cc_default)(*ctx, cache)))
128
 
        {
 
143
#ifndef FAILOVER_TO_DEFAULT_CCACHE
 
144
        rc = 1;
 
145
#endif
 
146
        if (*cache == 0
 
147
#ifdef FAILOVER_TO_DEFAULT_CCACHE
 
148
            && (rc = (*pkrb5_cc_default)(*ctx, cache))
 
149
#endif
 
150
            ) {
129
151
            functionName = "krb5_cc_default()";
130
152
            freeContextFlag = 1;
131
153
            goto on_error;
141
163
        if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND)
142
164
            khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx, 
143
165
            cache);
144
 
        else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL)
145
 
        {
 
166
        else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) {
146
167
            if (*cache != NULL)
147
168
                (*pkrb5_cc_close)(*ctx, *cache);
148
169
        }
154
175
    return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
155
176
#endif //!NO_KRB5
156
177
}
 
178
 
 
179
#define TIMET_TOLERANCE (60*5)
 
180
 
 
181
khm_int32 KHMAPI
 
182
khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, 
 
183
                                 khm_handle ident, 
 
184
                                 krb5_timestamp * pexpiration)
 
185
{
 
186
    krb5_principal principal = 0;
 
187
    char * princ_name = NULL;
 
188
    krb5_creds creds;
 
189
    krb5_error_code code;
 
190
    krb5_error_code cc_code;
 
191
    krb5_cc_cursor cur;
 
192
    krb5_timestamp now, expiration = 0;
 
193
 
 
194
    wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME];
 
195
    char    ident_name[KCDB_IDENT_MAXCCH_NAME];
 
196
    khm_size cb;
 
197
 
 
198
    khm_int32 rv = KHM_ERROR_NOT_FOUND;
 
199
 
 
200
    if (!ctx || !cc || !ident || !pexpiration)
 
201
        return KHM_ERROR_GENERAL;
 
202
 
 
203
    code = pkrb5_cc_get_principal(ctx, cc, &principal);
 
204
 
 
205
    if ( code )
 
206
        return KHM_ERROR_INVALID_PARAM;
 
207
 
 
208
    cb = sizeof(w_ident_name);
 
209
    kcdb_identity_get_name(ident, w_ident_name, &cb);
 
210
    UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name);
 
211
 
 
212
    code = pkrb5_unparse_name(ctx, principal, &princ_name);
 
213
 
 
214
    /* compare principal to ident. */
 
215
 
 
216
    if ( code || !princ_name ||
 
217
         strcmp(princ_name, ident_name) ) {
 
218
        if (princ_name)
 
219
            pkrb5_free_unparsed_name(ctx, princ_name);
 
220
        pkrb5_free_principal(ctx, principal);
 
221
        return KHM_ERROR_UNKNOWN;
 
222
    }
 
223
 
 
224
    pkrb5_free_unparsed_name(ctx, princ_name);
 
225
    pkrb5_free_principal(ctx, principal);
 
226
 
 
227
    code = pkrb5_timeofday(ctx, &now);
 
228
 
 
229
    if (code)
 
230
        return KHM_ERROR_UNKNOWN;
 
231
 
 
232
    cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
 
233
 
 
234
    while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
 
235
        krb5_data * c0 = krb5_princ_name(ctx, creds.server);
 
236
        krb5_data * c1  = krb5_princ_component(ctx, creds.server, 1);
 
237
        krb5_data * r = krb5_princ_realm(ctx, creds.server);
 
238
 
 
239
        if ( c0 && c1 && r && c1->length == r->length && 
 
240
             !strncmp(c1->data,r->data,r->length) &&
 
241
             !strncmp("krbtgt",c0->data,c0->length) ) {
 
242
 
 
243
            /* we have a TGT, check for the expiration time.
 
244
             * if it is valid and renewable, use the renew time 
 
245
             */
 
246
 
 
247
            if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
 
248
                creds.times.starttime < (now + TIMET_TOLERANCE) && 
 
249
                (creds.times.endtime + TIMET_TOLERANCE) > now) {
 
250
                expiration = creds.times.endtime;
 
251
 
 
252
                if ((creds.ticket_flags & TKT_FLG_RENEWABLE) && 
 
253
                    (creds.times.renew_till > creds.times.endtime)) {
 
254
                    expiration = creds.times.renew_till;
 
255
                }
 
256
            }
 
257
        }
 
258
    }
 
259
 
 
260
    if (cc_code == KRB5_CC_END) {
 
261
        cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
 
262
        rv = KHM_ERROR_SUCCESS;
 
263
        *pexpiration = expiration;
 
264
    }
 
265
 
 
266
    return rv;
 
267
}
 
268
 
 
269
khm_int32 KHMAPI
 
270
khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
 
271
                                  void * buffer, khm_size * pcbbuf)
 
272
{
 
273
    krb5_context        ctx = 0;
 
274
    krb5_ccache         cache = 0;
 
275
    krb5_error_code     code;
 
276
    apiCB *             cc_ctx = 0;
 
277
    struct _infoNC **   pNCi = NULL;
 
278
    int                 i;
 
279
    khm_int32           t;
 
280
    wchar_t *           ms = NULL;
 
281
    khm_size            cb;
 
282
    krb5_timestamp      expiration = 0;
 
283
    krb5_timestamp      best_match_expiration = 0;
 
284
    char                best_match_ccname[256] = "";
 
285
    khm_handle          csp_params = NULL;
 
286
    khm_handle          csp_plugins = NULL;
 
287
 
 
288
    if (!buffer || !pcbbuf)
 
289
    return KHM_ERROR_GENERAL;
 
290
 
 
291
    ctx = *pctx;
 
292
 
 
293
    if (!pcc_initialize ||
 
294
        !pcc_get_NC_info ||
 
295
        !pcc_free_NC_info ||
 
296
        !pcc_shutdown)
 
297
        goto _skip_cc_iter;
 
298
 
 
299
    code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
 
300
    if (code)
 
301
        goto _exit;
 
302
 
 
303
    code = pcc_get_NC_info(cc_ctx, &pNCi);
 
304
 
 
305
    if (code) 
 
306
        goto _exit;
 
307
 
 
308
    for(i=0; pNCi[i]; i++) {
 
309
        if (pNCi[i]->vers != CC_CRED_V5)
 
310
            continue;
 
311
 
 
312
        code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);
 
313
        if (code)
 
314
            continue;
 
315
 
 
316
        /* need a function to check the cache for the identity
 
317
         * and determine if it has valid tickets.  If it has 
 
318
         * the right identity and valid tickets, store the 
 
319
         * expiration time and the cache name.  If it has the
 
320
         * right identity but no valid tickets, store the ccache
 
321
         * name and an expiration time of zero.  if it does not
 
322
         * have the right identity don't save the name.
 
323
         * 
 
324
         * Keep searching to find the best cache available.
 
325
         */
 
326
 
 
327
        if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, 
 
328
                                                           ident, 
 
329
                                                           &expiration))) {
 
330
            if ( expiration > best_match_expiration ) {
 
331
                best_match_expiration = expiration;
 
332
                StringCbCopyA(best_match_ccname, 
 
333
                              sizeof(best_match_ccname),
 
334
                              "API:");
 
335
                StringCbCatA(best_match_ccname,
 
336
                             sizeof(best_match_ccname),
 
337
                             pNCi[i]->name);
 
338
                expiration = 0;
 
339
            }
 
340
        }
 
341
 
 
342
        if(ctx != NULL && cache != NULL)
 
343
            (*pkrb5_cc_close)(ctx, cache);
 
344
        cache = 0;
 
345
    }
 
346
 
 
347
 _skip_cc_iter:
 
348
 
 
349
    if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) {
 
350
        khc_open_space(csp_plugins, L"Krb5Cred\\Parameters",  0, &csp_params);
 
351
        khc_close_space(csp_plugins);
 
352
        csp_plugins = NULL;
 
353
    }
 
354
 
 
355
#ifdef DEBUG
 
356
    if (csp_params == NULL) {
 
357
        assert(FALSE);
 
358
    }
 
359
#endif
 
360
 
 
361
    if (csp_params &&
 
362
        KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
 
363
        code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
 
364
        if (code == 0 && cache) {
 
365
            if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, 
 
366
                                                               ident, 
 
367
                                                               &expiration))) {
 
368
                if ( expiration > best_match_expiration ) {
 
369
                    best_match_expiration = expiration;
 
370
                    StringCbCopyA(best_match_ccname, sizeof(best_match_ccname),
 
371
                                  "MSLSA:");
 
372
                    expiration = 0;
 
373
                }
 
374
            }
 
375
        }
 
376
 
 
377
        if (ctx != NULL && cache != NULL)
 
378
            (*pkrb5_cc_close)(ctx, cache);
 
379
 
 
380
        cache = 0;
 
381
    }
 
382
 
 
383
    if (csp_params &&
 
384
        khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
 
385
        == KHM_ERROR_TOO_LONG &&
 
386
        cb > sizeof(wchar_t) * 2) {
 
387
 
 
388
        wchar_t * t;
 
389
        char ccname[MAX_PATH + 6];
 
390
 
 
391
        ms = PMALLOC(cb);
 
392
 
 
393
#ifdef DEBUG
 
394
        assert(ms);
 
395
#endif
 
396
 
 
397
        khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
 
398
        for(t = ms; t && *t; t = multi_string_next(t)) {
 
399
            StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
 
400
                             "FILE:%S", t);
 
401
 
 
402
            code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
 
403
            if (code)
 
404
                continue;
 
405
 
 
406
            if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, 
 
407
                                                               ident, 
 
408
                                                               &expiration))) {
 
409
                if ( expiration > best_match_expiration ) {
 
410
                    best_match_expiration = expiration;
 
411
                    StringCbCopyA(best_match_ccname,
 
412
                                  sizeof(best_match_ccname),
 
413
                                  ccname);
 
414
                    expiration = 0;
 
415
                }
 
416
            }
 
417
 
 
418
            if (ctx != NULL && cache != NULL)
 
419
                (*pkrb5_cc_close)(ctx, cache);
 
420
            cache = 0;
 
421
        }
 
422
 
 
423
        PFREE(ms);
 
424
    }
 
425
 _exit:
 
426
    if (csp_params)
 
427
        khc_close_space(csp_params);
 
428
 
 
429
    if (pNCi)
 
430
        (*pcc_free_NC_info)(cc_ctx, &pNCi);
 
431
 
 
432
    if (cc_ctx)
 
433
        (*pcc_shutdown)(&cc_ctx);
 
434
 
 
435
    if (best_match_ccname[0]) {
 
436
        
 
437
        if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer, 
 
438
                                       *pcbbuf,
 
439
                                       best_match_ccname)) {
 
440
 
 
441
            *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t);
 
442
 
 
443
            return KHM_ERROR_SUCCESS;
 
444
        }
 
445
 
 
446
    }
 
447
 
 
448
    return KHM_ERROR_GENERAL;
 
449
}