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

« back to all changes in this revision

Viewing changes to src/kdc/kdc_authdata.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * kdc/kdc_authdata.c
 
3
 *
 
4
 * Copyright (C) 2007 Apple Inc.  All Rights Reserved.
 
5
 * Copyright (C) 2008 by the Massachusetts Institute of Technology.
 
6
 *
 
7
 * Export of this software from the United States of America may
 
8
 *   require a specific license from the United States Government.
 
9
 *   It is the responsibility of any person or organization contemplating
 
10
 *   export to obtain such a license before exporting.
 
11
 * 
 
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
13
 * distribute this software and its documentation for any purpose and
 
14
 * without fee is hereby granted, provided that the above copyright
 
15
 * notice appear in all copies and that both that copyright notice and
 
16
 * this permission notice appear in supporting documentation, and that
 
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
 
18
 * to distribution of the software without specific, written prior
 
19
 * permission.  Furthermore if you modify this software you must label
 
20
 * your software as modified software and not distribute it in such a
 
21
 * fashion that it might be confused with the original M.I.T. software.
 
22
 * M.I.T. makes no representations about the suitability of
 
23
 * this software for any purpose.  It is provided "as is" without express
 
24
 * or implied warranty.
 
25
 * 
 
26
 * AuthorizationData routines for the KDC.
 
27
 */
 
28
 
 
29
#include "k5-int.h"
 
30
#include "kdc_util.h"
 
31
#include "extern.h"
 
32
#include <stdio.h>
 
33
#include "adm_proto.h"
 
34
 
 
35
#include <syslog.h>
 
36
 
 
37
#include <assert.h>
 
38
#include "../include/krb5/authdata_plugin.h"
 
39
 
 
40
#if TARGET_OS_MAC
 
41
static const char *objdirs[] = { KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/authdata", NULL }; /* should be a list */
 
42
#else
 
43
static const char *objdirs[] = { LIBDIR "/krb5/plugins/authdata", NULL };
 
44
#endif
 
45
 
 
46
/* MIT Kerberos 1.6 (V0) authdata plugin callback */
 
47
typedef krb5_error_code (*authdata_proc_0)
 
48
    (krb5_context, krb5_db_entry *client,
 
49
     krb5_data *req_pkt,
 
50
     krb5_kdc_req *request,
 
51
     krb5_enc_tkt_part * enc_tkt_reply);
 
52
/* MIT Kerberos 1.7 (V1) authdata plugin callback */
 
53
typedef krb5_error_code (*authdata_proc_1)
 
54
    (krb5_context, unsigned int flags,
 
55
     krb5_db_entry *client, krb5_db_entry *server,
 
56
     krb5_db_entry *krbtgt,
 
57
     krb5_keyblock *client_key,
 
58
     krb5_keyblock *server_key,
 
59
     krb5_data *req_pkt,
 
60
     krb5_kdc_req *request,
 
61
     krb5_const_principal for_user_princ,
 
62
     krb5_enc_tkt_part *enc_tkt_request,
 
63
     krb5_enc_tkt_part *enc_tkt_reply);
 
64
typedef krb5_error_code (*init_proc)
 
65
    (krb5_context, void **);
 
66
typedef void (*fini_proc)
 
67
    (krb5_context, void *);
 
68
 
 
69
/* Internal authdata system for copying TGS-REQ authdata to ticket */
 
70
static krb5_error_code handle_request_authdata
 
71
    (krb5_context context,
 
72
     unsigned int flags,
 
73
     krb5_db_entry *client,
 
74
     krb5_db_entry *server,
 
75
     krb5_db_entry *krbtgt,
 
76
     krb5_keyblock *client_key,
 
77
     krb5_keyblock *server_key,
 
78
     krb5_data *req_pkt,
 
79
     krb5_kdc_req *request,
 
80
     krb5_const_principal for_user_princ,
 
81
     krb5_enc_tkt_part *enc_tkt_request,
 
82
     krb5_enc_tkt_part *enc_tkt_reply);
 
83
 
 
84
/* Internal authdata system for handling KDC-issued authdata */
 
85
static krb5_error_code handle_tgt_authdata
 
86
    (krb5_context context,
 
87
     unsigned int flags,
 
88
     krb5_db_entry *client,
 
89
     krb5_db_entry *server,
 
90
     krb5_db_entry *krbtgt,
 
91
     krb5_keyblock *client_key,
 
92
     krb5_keyblock *server_key,
 
93
     krb5_data *req_pkt,
 
94
     krb5_kdc_req *request,
 
95
     krb5_const_principal for_user_princ,
 
96
     krb5_enc_tkt_part *enc_tkt_request,
 
97
     krb5_enc_tkt_part *enc_tkt_reply);
 
98
 
 
99
typedef struct _krb5_authdata_systems {
 
100
    const char *name;
 
101
#define AUTHDATA_SYSTEM_UNKNOWN -1
 
102
#define AUTHDATA_SYSTEM_V0      0
 
103
#define AUTHDATA_SYSTEM_V1      1
 
104
    int         type;
 
105
#define AUTHDATA_FLAG_CRITICAL  0x1
 
106
    int         flags;
 
107
    void       *plugin_context;
 
108
    init_proc   init;
 
109
    fini_proc   fini;
 
110
    union {
 
111
        authdata_proc_1 v1;
 
112
        authdata_proc_0 v0;
 
113
    } handle_authdata;
 
114
} krb5_authdata_systems;
 
115
 
 
116
static krb5_authdata_systems static_authdata_systems[] = {
 
117
    { "tgs_req", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_request_authdata } },
 
118
    { "tgt", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_tgt_authdata } },
 
119
};
 
120
 
 
121
static krb5_authdata_systems *authdata_systems;
 
122
static int n_authdata_systems;
 
123
static struct plugin_dir_handle authdata_plugins;
 
124
 
 
125
/* Load both v0 and v1 authdata plugins */
 
126
krb5_error_code
 
127
load_authdata_plugins(krb5_context context)
 
128
{
 
129
    void **authdata_plugins_ftables_v0 = NULL;
 
130
    void **authdata_plugins_ftables_v1 = NULL;
 
131
    size_t module_count;
 
132
    size_t i, k;
 
133
    init_proc server_init_proc = NULL;
 
134
    krb5_error_code code;
 
135
 
 
136
    /* Attempt to load all of the authdata plugins we can find. */
 
137
    PLUGIN_DIR_INIT(&authdata_plugins);
 
138
    if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) {
 
139
        if (krb5int_open_plugin_dirs(objdirs, NULL,
 
140
                                     &authdata_plugins, &context->err) != 0) {
 
141
            return KRB5_PLUGIN_NO_HANDLE;
 
142
        }
 
143
    }
 
144
 
 
145
    /* Get the method tables provided by the loaded plugins. */
 
146
    authdata_plugins_ftables_v0 = NULL;
 
147
    authdata_plugins_ftables_v1 = NULL;
 
148
    n_authdata_systems = 0;
 
149
 
 
150
    if (krb5int_get_plugin_dir_data(&authdata_plugins,
 
151
                                    "authdata_server_1",
 
152
                                    &authdata_plugins_ftables_v1, &context->err) != 0 ||
 
153
        krb5int_get_plugin_dir_data(&authdata_plugins,
 
154
                                    "authdata_server_0",
 
155
                                    &authdata_plugins_ftables_v0, &context->err) != 0) {
 
156
        code = KRB5_PLUGIN_NO_HANDLE;
 
157
        goto cleanup;
 
158
    }
 
159
 
 
160
    /* Count the valid modules. */ 
 
161
    module_count = sizeof(static_authdata_systems)
 
162
        / sizeof(static_authdata_systems[0]);
 
163
 
 
164
    if (authdata_plugins_ftables_v1 != NULL) {
 
165
        struct krb5plugin_authdata_ftable_v1 *ftable;
 
166
 
 
167
        for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) {
 
168
            ftable = authdata_plugins_ftables_v1[i];
 
169
            if (ftable->authdata_proc != NULL)
 
170
                module_count++;
 
171
        }
 
172
    }
 
173
 
 
174
    if (authdata_plugins_ftables_v0 != NULL) {
 
175
        struct krb5plugin_authdata_ftable_v0 *ftable;
 
176
 
 
177
        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
 
178
            ftable = authdata_plugins_ftables_v0[i];
 
179
            if (ftable->authdata_proc != NULL)
 
180
                module_count++;
 
181
        }
 
182
    }
 
183
 
 
184
    /* Build the complete list of supported authdata options, and
 
185
     * leave room for a terminator entry. */
 
186
    authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems));
 
187
    if (authdata_systems == NULL) {
 
188
        code = ENOMEM;
 
189
        goto cleanup;
 
190
    }
 
191
 
 
192
    /* Add the locally-supplied mechanisms to the dynamic list first. */
 
193
    for (i = 0, k = 0;
 
194
         i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]);
 
195
         i++) {
 
196
        authdata_systems[k] = static_authdata_systems[i];
 
197
        /* Try to initialize the authdata system.  If it fails, we'll remove it
 
198
         * from the list of systems we'll be using. */
 
199
        server_init_proc = static_authdata_systems[i].init;
 
200
        if ((server_init_proc != NULL) &&
 
201
            ((*server_init_proc)(context, &authdata_systems[k].plugin_context) != 0)) {
 
202
            memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
 
203
            continue;
 
204
        }
 
205
        k++;
 
206
    }
 
207
 
 
208
    /* Add dynamically loaded V1 plugins */
 
209
    if (authdata_plugins_ftables_v1 != NULL) {
 
210
        struct krb5plugin_authdata_ftable_v1 *ftable;
 
211
 
 
212
        for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) {
 
213
            krb5_error_code initerr;
 
214
            void *pctx = NULL;
 
215
 
 
216
            ftable = authdata_plugins_ftables_v1[i];
 
217
            if ((ftable->authdata_proc == NULL)) {
 
218
                continue;
 
219
            }
 
220
            server_init_proc = ftable->init_proc;
 
221
            if ((server_init_proc != NULL) &&
 
222
                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
 
223
                const char *emsg;
 
224
                emsg = krb5_get_error_message(context, initerr);
 
225
                if (emsg) {
 
226
                    krb5_klog_syslog(LOG_ERR,
 
227
                                     "authdata %s failed to initialize: %s",
 
228
                                     ftable->name, emsg);
 
229
                    krb5_free_error_message(context, emsg);
 
230
                }
 
231
                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
 
232
        
 
233
                continue;
 
234
            }
 
235
    
 
236
            authdata_systems[k].name = ftable->name;
 
237
            authdata_systems[k].type = AUTHDATA_SYSTEM_V1;
 
238
            authdata_systems[k].init = server_init_proc;
 
239
            authdata_systems[k].fini = ftable->fini_proc;
 
240
            authdata_systems[k].handle_authdata.v1 = ftable->authdata_proc;
 
241
            authdata_systems[k].plugin_context = pctx;
 
242
            k++;
 
243
        }
 
244
    }
 
245
 
 
246
    /* Add dynamically loaded V0 plugins */
 
247
    if (authdata_plugins_ftables_v0 != NULL) {
 
248
        struct krb5plugin_authdata_ftable_v0 *ftable;
 
249
 
 
250
        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
 
251
            krb5_error_code initerr;
 
252
            void *pctx = NULL;
 
253
 
 
254
            ftable = authdata_plugins_ftables_v0[i];
 
255
            if ((ftable->authdata_proc == NULL)) {
 
256
                continue;
 
257
            }
 
258
            server_init_proc = ftable->init_proc;
 
259
            if ((server_init_proc != NULL) &&
 
260
                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
 
261
                const char *emsg;
 
262
                emsg = krb5_get_error_message(context, initerr);
 
263
                if (emsg) {
 
264
                    krb5_klog_syslog(LOG_ERR,
 
265
                                     "authdata %s failed to initialize: %s",
 
266
                                     ftable->name, emsg);
 
267
                    krb5_free_error_message(context, emsg);
 
268
                }
 
269
                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
 
270
        
 
271
                continue;
 
272
            }
 
273
    
 
274
            authdata_systems[k].name = ftable->name;
 
275
            authdata_systems[k].type = AUTHDATA_SYSTEM_V0;
 
276
            authdata_systems[k].init = server_init_proc;
 
277
            authdata_systems[k].fini = ftable->fini_proc;
 
278
            authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc;
 
279
            authdata_systems[k].plugin_context = pctx;
 
280
            k++;
 
281
        }
 
282
    }
 
283
 
 
284
    n_authdata_systems = k;
 
285
    /* Add the end-of-list marker. */
 
286
    authdata_systems[k].name = "[end]";
 
287
    authdata_systems[k].type = AUTHDATA_SYSTEM_UNKNOWN;
 
288
    code = 0;
 
289
 
 
290
cleanup:
 
291
    if (authdata_plugins_ftables_v1 != NULL)
 
292
        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v1);
 
293
    if (authdata_plugins_ftables_v0 != NULL)
 
294
        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0);
 
295
 
 
296
    return code;
 
297
}
 
298
 
 
299
krb5_error_code
 
300
unload_authdata_plugins(krb5_context context)
 
301
{
 
302
    int i;
 
303
    if (authdata_systems != NULL) {
 
304
        for (i = 0; i < n_authdata_systems; i++) {
 
305
            if (authdata_systems[i].fini != NULL) {
 
306
                (*authdata_systems[i].fini)(context,
 
307
                                            authdata_systems[i].plugin_context);
 
308
            }
 
309
            memset(&authdata_systems[i], 0, sizeof(authdata_systems[i]));
 
310
        }
 
311
        free(authdata_systems);
 
312
        authdata_systems = NULL;
 
313
        n_authdata_systems = 0;
 
314
        krb5int_close_plugin_dirs(&authdata_plugins);
 
315
    }
 
316
    return 0;
 
317
}
 
318
 
 
319
/* Merge authdata. If copy == 0, in_authdata is invalid on return */
 
320
static krb5_error_code
 
321
merge_authdata (krb5_context context,
 
322
                krb5_authdata **in_authdata,
 
323
                krb5_authdata ***out_authdata,
 
324
                krb5_boolean copy)
 
325
{
 
326
    size_t i, nadata = 0;
 
327
    krb5_authdata **authdata = *out_authdata;
 
328
 
 
329
    if (in_authdata == NULL || in_authdata[0] == NULL)
 
330
        return 0;
 
331
 
 
332
    if (authdata != NULL) {
 
333
        for (nadata = 0; authdata[nadata] != NULL; nadata++)
 
334
            ;
 
335
    }
 
336
 
 
337
    for (i = 0; in_authdata[i] != NULL; i++)
 
338
        ;
 
339
 
 
340
    if (authdata == NULL) {
 
341
        authdata = (krb5_authdata **)calloc(i + 1, sizeof(krb5_authdata *));
 
342
    } else {
 
343
        authdata = (krb5_authdata **)realloc(authdata,
 
344
            ((nadata + i + 1) * sizeof(krb5_authdata *)));
 
345
    }
 
346
    if (authdata == NULL)
 
347
        return ENOMEM;
 
348
 
 
349
    if (copy) {
 
350
        krb5_error_code code;
 
351
        krb5_authdata **tmp;
 
352
 
 
353
        code = krb5_copy_authdata(context, in_authdata, &tmp);
 
354
        if (code != 0)
 
355
            return code;
 
356
 
 
357
        in_authdata = tmp;
 
358
    }
 
359
 
 
360
    for (i = 0; in_authdata[i] != NULL; i++)
 
361
        authdata[nadata + i] = in_authdata[i];
 
362
 
 
363
    authdata[nadata + i] = NULL;
 
364
 
 
365
    free(in_authdata);
 
366
 
 
367
    *out_authdata = authdata;
 
368
 
 
369
    return 0;
 
370
}
 
371
 
 
372
/* Handle copying TGS-REQ authorization data into reply */
 
373
static krb5_error_code
 
374
handle_request_authdata (krb5_context context,
 
375
                         unsigned int flags,
 
376
                         krb5_db_entry *client,
 
377
                         krb5_db_entry *server,
 
378
                         krb5_db_entry *krbtgt,
 
379
                         krb5_keyblock *client_key,
 
380
                         krb5_keyblock *server_key,
 
381
                         krb5_data *req_pkt,
 
382
                         krb5_kdc_req *request,
 
383
                         krb5_const_principal for_user_princ,
 
384
                         krb5_enc_tkt_part *enc_tkt_request,
 
385
                         krb5_enc_tkt_part *enc_tkt_reply)
 
386
{
 
387
    krb5_error_code code;
 
388
    krb5_data scratch;
 
389
 
 
390
    if (request->msg_type != KRB5_TGS_REQ ||
 
391
        request->authorization_data.ciphertext.data == NULL)
 
392
        return 0;
 
393
 
 
394
    assert(enc_tkt_request != NULL);
 
395
 
 
396
    scratch.length = request->authorization_data.ciphertext.length;
 
397
    scratch.data = malloc(scratch.length);
 
398
    if (scratch.data == NULL)
 
399
        return ENOMEM;
 
400
 
 
401
    code = krb5_c_decrypt(context,
 
402
                          enc_tkt_request->session,
 
403
                          KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
 
404
                          0, &request->authorization_data,
 
405
                          &scratch);
 
406
    if (code != 0)
 
407
        code = krb5_c_decrypt(context,
 
408
                              client_key,
 
409
                              KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY,
 
410
                              0, &request->authorization_data,
 
411
                              &scratch);
 
412
 
 
413
    if (code != 0) {
 
414
        free(scratch.data);
 
415
        return code;
 
416
    }
 
417
 
 
418
    /* scratch now has the authorization data, so we decode it, and make
 
419
     * it available to subsequent authdata plugins */
 
420
    code = decode_krb5_authdata(&scratch, &request->unenc_authdata);
 
421
    if (code != 0) {
 
422
        free(scratch.data);
 
423
        return code;
 
424
    }
 
425
 
 
426
    free(scratch.data);
 
427
 
 
428
    code = merge_authdata(context, request->unenc_authdata,
 
429
                          &enc_tkt_reply->authorization_data, TRUE /* copy */);
 
430
 
 
431
    return code;
 
432
}
 
433
 
 
434
/* Handle backend-managed authorization data */
 
435
static krb5_error_code
 
436
handle_tgt_authdata (krb5_context context,
 
437
                     unsigned int flags,
 
438
                     krb5_db_entry *client,
 
439
                     krb5_db_entry *server,
 
440
                     krb5_db_entry *krbtgt,
 
441
                     krb5_keyblock *client_key,
 
442
                     krb5_keyblock *server_key,
 
443
                     krb5_data *req_pkt,
 
444
                     krb5_kdc_req *request,
 
445
                     krb5_const_principal for_user_princ,
 
446
                     krb5_enc_tkt_part *enc_tkt_request,
 
447
                     krb5_enc_tkt_part *enc_tkt_reply)
 
448
{
 
449
    krb5_error_code code;
 
450
    krb5_authdata **db_authdata = NULL;
 
451
    krb5_db_entry ad_entry;
 
452
    int ad_nprincs = 0;
 
453
    krb5_boolean tgs_req = (request->msg_type == KRB5_TGS_REQ);
 
454
    krb5_const_principal actual_client;
 
455
 
 
456
    /*
 
457
     * Check whether KDC issued authorization data should be included.
 
458
     * A server can explicitly disable the inclusion of authorization
 
459
     * data by setting the KRB5_KDB_NO_AUTH_DATA_REQUIRED flag on its
 
460
     * principal entry. Otherwise authorization data will be included
 
461
     * if it was present in the TGT, the client is from another realm
 
462
     * or protocol transition/constrained delegation was used, or, in
 
463
     * the AS-REQ case, if the pre-auth data indicated the PAC should
 
464
     * be present.
 
465
     *
 
466
     * We permit sign_authorization_data() to return a krb5_db_entry
 
467
     * representing the principal associated with the authorization
 
468
     * data, in case that principal is not local to our realm and we
 
469
     * need to perform additional checks (such as disabling delegation
 
470
     * for cross-realm protocol transition below).
 
471
     */
 
472
    if (tgs_req) {
 
473
        assert(enc_tkt_request != NULL);
 
474
 
 
475
        if (isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED))
 
476
            return 0;
 
477
 
 
478
        if (enc_tkt_request->authorization_data == NULL &&
 
479
            !isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM | KRB5_KDB_FLAGS_S4U))
 
480
            return 0;
 
481
 
 
482
        assert(enc_tkt_reply->times.authtime == enc_tkt_request->times.authtime);
 
483
    } else {
 
484
        if (!isflagset(flags, KRB5_KDB_FLAG_INCLUDE_PAC))
 
485
            return 0;
 
486
    }
 
487
 
 
488
    /*
 
489
     * We have this special case for protocol transition, because for
 
490
     * cross-realm protocol transition the ticket reply client will
 
491
     * not be changed until the final hop.
 
492
     */
 
493
    if (isflagset(flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION))
 
494
        actual_client = for_user_princ;
 
495
    else
 
496
        actual_client = enc_tkt_reply->client;
 
497
 
 
498
    /*
 
499
     * If the backend does not implement the sign authdata method, then
 
500
     * just copy the TGT authorization data into the reply, except for
 
501
     * the constrained delegation case (which requires special handling
 
502
     * because it will promote untrusted auth data to KDC issued auth
 
503
     * data; this requires backend-specific code)
 
504
     *
 
505
     * Presently this interface does not support using request auth data
 
506
     * to influence (eg. possibly restrict) the reply auth data.
 
507
     */
 
508
    code = sign_db_authdata(context,
 
509
                            flags,
 
510
                            actual_client,
 
511
                            client,
 
512
                            server,
 
513
                            krbtgt,
 
514
                            client_key,
 
515
                            server_key, /* U2U or server key */
 
516
                            enc_tkt_reply->times.authtime,
 
517
                            tgs_req ? enc_tkt_request->authorization_data : NULL,
 
518
                            &db_authdata,
 
519
                            &ad_entry,
 
520
                            &ad_nprincs);
 
521
    if (code == KRB5_KDB_DBTYPE_NOSUP) {
 
522
        assert(ad_nprincs == 0);
 
523
        assert(db_authdata == NULL);
 
524
 
 
525
        if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION))
 
526
            return KRB5KDC_ERR_POLICY;
 
527
 
 
528
        if (tgs_req)
 
529
            return merge_authdata(context, enc_tkt_request->authorization_data,
 
530
                                  &enc_tkt_reply->authorization_data, TRUE);
 
531
        else
 
532
            return 0;
 
533
    }
 
534
 
 
535
    if (ad_nprincs != 0) {
 
536
        if (isflagset(flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) &&
 
537
            isflagset(ad_entry.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))
 
538
            clear(enc_tkt_reply->flags, TKT_FLG_FORWARDABLE);
 
539
 
 
540
        krb5_db_free_principal(context, &ad_entry, ad_nprincs);
 
541
 
 
542
        if (ad_nprincs != 1) {
 
543
            if (db_authdata != NULL)
 
544
                krb5_free_authdata(context, db_authdata);
 
545
            return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
 
546
        }
 
547
    }
 
548
 
 
549
    if (db_authdata != NULL) {
 
550
        code = merge_authdata(context, db_authdata,
 
551
                              &enc_tkt_reply->authorization_data,
 
552
                              FALSE);
 
553
        if (code != 0)
 
554
            krb5_free_authdata(context, db_authdata);
 
555
    }
 
556
 
 
557
    return code;
 
558
}
 
559
 
 
560
krb5_error_code
 
561
handle_authdata (krb5_context context,
 
562
                 unsigned int flags,
 
563
                 krb5_db_entry *client,
 
564
                 krb5_db_entry *server,
 
565
                 krb5_db_entry *krbtgt,
 
566
                 krb5_keyblock *client_key,
 
567
                 krb5_keyblock *server_key,
 
568
                 krb5_data *req_pkt,
 
569
                 krb5_kdc_req *request,
 
570
                 krb5_const_principal for_user_princ,
 
571
                 krb5_enc_tkt_part *enc_tkt_request,
 
572
                 krb5_enc_tkt_part *enc_tkt_reply)
 
573
{
 
574
    krb5_error_code code = 0;
 
575
    int i;
 
576
 
 
577
    assert(enc_tkt_reply->authorization_data == NULL);
 
578
    for (i = 0; i < n_authdata_systems; i++) {
 
579
        const krb5_authdata_systems *asys = &authdata_systems[i];
 
580
 
 
581
        switch (asys->type) {
 
582
        case AUTHDATA_SYSTEM_V0:
 
583
            /* V0 was only in AS-REQ code path */
 
584
            if (request->msg_type != KRB5_AS_REQ)
 
585
                continue;
 
586
 
 
587
            code = (*asys->handle_authdata.v0)(context, client, req_pkt,
 
588
                                               request, enc_tkt_reply);
 
589
            break;
 
590
        case AUTHDATA_SYSTEM_V1:
 
591
            code = (*asys->handle_authdata.v1)(context, flags,
 
592
                                              client, server, krbtgt,
 
593
                                              client_key, server_key,
 
594
                                              req_pkt, request, for_user_princ,
 
595
                                              enc_tkt_request,
 
596
                                              enc_tkt_reply);
 
597
            break;
 
598
        default:
 
599
            code = 0;
 
600
            break;
 
601
        }
 
602
        if (code != 0) {
 
603
            const char *emsg;
 
604
 
 
605
            emsg = krb5_get_error_message (context, code);
 
606
            krb5_klog_syslog (LOG_INFO,
 
607
                              "authdata (%s) handling failure: %s",
 
608
                              asys->name, emsg);
 
609
            krb5_free_error_message (context, emsg);
 
610
 
 
611
            if (asys->flags & AUTHDATA_FLAG_CRITICAL)
 
612
                break;
 
613
        }
 
614
    }
 
615
 
 
616
    return code;
 
617
}
 
618