99
98
return min(entry->expiration, entry->pw_expiration);
104
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
105
const krb5_fulladdr *from, krb5_data **response)
107
krb5_db_entry *client = NULL, *server = NULL;
101
struct as_req_state {
102
loop_respond_fn respond;
105
krb5_enc_tkt_part enc_tkt_reply;
109
106
krb5_enc_kdc_rep_part reply_encpart;
110
107
krb5_ticket ticket_reply;
111
krb5_enc_tkt_part enc_tkt_reply;
112
krb5_error_code errcode;
113
krb5_timestamp kdc_time, authtime = 0;
108
krb5_keyblock server_keyblock;
109
krb5_keyblock client_keyblock;
110
krb5_db_entry *client;
111
krb5_db_entry *server;
112
krb5_kdc_req *request;
113
struct krb5_kdcpreauth_rock_st rock;
115
krb5_pa_data **e_data;
116
krb5_boolean typed_e_data;
118
krb5_timestamp kdc_time;
119
krb5_timestamp authtime;
114
120
krb5_keyblock session_key;
116
krb5_key_data *server_key, *client_key;
117
krb5_keyblock server_keyblock, client_keyblock;
118
krb5_enctype useenctype;
121
unsigned int c_flags;
123
struct kdc_request_state *rstate;
126
const krb5_fulladdr *from;
128
krb5_error_code preauth_err;
132
finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
134
krb5_key_data *server_key;
135
krb5_key_data *client_key;
136
krb5_keyblock *as_encrypting_key = NULL;
137
krb5_data *response = NULL;
138
const char *emsg = 0;
141
krb5_enctype useenctype;
142
loop_respond_fn oldrespond;
146
oldrespond = state->respond;
152
if ((errcode = validate_forwardable(state->request, *state->client,
153
*state->server, state->kdc_time,
155
errcode += ERROR_TABLE_BASE_krb5;
159
state->ticket_reply.enc_part2 = &state->enc_tkt_reply;
162
* Find the server key
164
if ((errcode = krb5_dbe_find_enctype(kdc_context, state->server,
165
-1, /* ignore keytype */
166
-1, /* Ignore salttype */
167
0, /* Get highest kvno */
169
state->status = "FINDING_SERVER_KEY";
174
* Convert server->key into a real key
175
* (it may be encrypted in the database)
177
* server_keyblock is later used to generate auth data signatures
179
if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
181
&state->server_keyblock,
183
state->status = "DECRYPT_SERVER_KEY";
188
* Find the appropriate client key. We search in the order specified
189
* by request keytype list.
192
for (i = 0; i < state->request->nktypes; i++) {
193
useenctype = state->request->ktype[i];
194
if (!krb5_c_valid_enctype(useenctype))
197
if (!krb5_dbe_find_enctype(kdc_context, state->client,
198
useenctype, -1, 0, &client_key))
202
/* Cannot find an appropriate key */
203
state->status = "CANT_FIND_CLIENT_KEY";
204
errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
207
state->rock.client_key = client_key;
209
/* convert client.key_data into a real key */
210
if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
212
&state->client_keyblock,
214
state->status = "DECRYPT_CLIENT_KEY";
217
state->client_keyblock.enctype = useenctype;
219
/* Start assembling the response */
220
state->reply.msg_type = KRB5_AS_REP;
221
state->reply.client = state->enc_tkt_reply.client; /* post canonization */
222
state->reply.ticket = &state->ticket_reply;
223
state->reply_encpart.session = &state->session_key;
224
if ((errcode = fetch_last_req_info(state->client,
225
&state->reply_encpart.last_req))) {
226
state->status = "FETCH_LAST_REQ";
229
state->reply_encpart.nonce = state->request->nonce;
230
state->reply_encpart.key_exp = get_key_exp(state->client);
231
state->reply_encpart.flags = state->enc_tkt_reply.flags;
232
state->reply_encpart.server = state->ticket_reply.server;
234
/* copy the time fields EXCEPT for authtime; it's location
237
state->reply_encpart.times = state->enc_tkt_reply.times;
238
state->reply_encpart.times.authtime = state->authtime = state->kdc_time;
240
state->reply_encpart.caddrs = state->enc_tkt_reply.caddrs;
241
state->reply_encpart.enc_padata = NULL;
243
/* Fetch the padata info to be returned (do this before
244
* authdata to handle possible replacement of reply key
246
errcode = return_padata(kdc_context, &state->rock, state->req_pkt,
247
state->request, &state->reply,
248
&state->client_keyblock, &state->pa_context);
250
state->status = "KDC_RETURN_PADATA";
255
asReqDebug("process_as_req reply realm %s name %s\n",
256
reply.client->realm.data, reply.client->data->data);
257
#endif /* APPLE_PKINIT */
261
errcode = handle_authdata(kdc_context,
266
&state->client_keyblock,
267
&state->server_keyblock,
268
&state->server_keyblock,
271
NULL, /* for_user_princ */
272
NULL, /* enc_tkt_request */
273
&state->enc_tkt_reply);
275
krb5_klog_syslog(LOG_INFO, _("AS_REQ : handle_authdata (%d)"),
277
state->status = "HANDLE_AUTHDATA";
281
errcode = krb5_encrypt_tkt_part(kdc_context, &state->server_keyblock,
282
&state->ticket_reply);
284
state->status = "ENCRYPTING_TICKET";
287
state->ticket_reply.enc_part.kvno = server_key->key_data_kvno;
288
errcode = kdc_fast_response_handle_padata(state->rstate,
291
state->client_keyblock.enctype);
293
state->status = "fast response handling";
297
/* now encode/encrypt the response */
299
state->reply.enc_part.enctype = state->client_keyblock.enctype;
301
errcode = kdc_fast_handle_reply_key(state->rstate, &state->client_keyblock,
304
state->status = "generating reply key";
307
errcode = return_enc_padata(kdc_context, state->req_pkt, state->request,
308
as_encrypting_key, state->server,
309
&state->reply_encpart, FALSE);
311
state->status = "KDC_RETURN_ENC_PADATA";
315
errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP,
316
&state->reply_encpart, 0,
318
&state->reply, &response);
319
state->reply.enc_part.kvno = client_key->key_data_kvno;
321
state->status = "ENCODE_KDC_REP";
325
/* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
326
can use them in raw form if needed. But, we don't... */
327
memset(state->reply.enc_part.ciphertext.data, 0,
328
state->reply.enc_part.ciphertext.length);
329
free(state->reply.enc_part.ciphertext.data);
331
log_as_req(state->from, state->request, &state->reply,
332
state->client, state->cname, state->server,
333
state->sname, state->authtime, 0, 0, 0);
338
assert (state->status != 0);
339
free_padata_context(kdc_context, state->pa_context);
340
if (as_encrypting_key)
341
krb5_free_keyblock(kdc_context, as_encrypting_key);
343
emsg = krb5_get_error_message(kdc_context, errcode);
346
log_as_req(state->from, state->request, &state->reply, state->client,
347
state->cname, state->server, state->sname, state->authtime,
348
state->status, errcode, emsg);
352
if (state->status == 0) {
353
state->status = emsg;
355
if (errcode != KRB5KDC_ERR_DISCARD) {
356
errcode -= ERROR_TABLE_BASE_krb5;
357
if (errcode < 0 || errcode > 128)
358
errcode = KRB_ERR_GENERIC;
360
errcode = prepare_error_as(state->rstate, state->request,
361
errcode, state->e_data,
363
((state->client != NULL) ?
364
state->client->princ : NULL),
365
&response, state->status);
371
krb5_free_error_message(kdc_context, emsg);
372
if (state->enc_tkt_reply.authorization_data != NULL)
373
krb5_free_authdata(kdc_context,
374
state->enc_tkt_reply.authorization_data);
375
if (state->server_keyblock.contents != NULL)
376
krb5_free_keyblock_contents(kdc_context, &state->server_keyblock);
377
if (state->client_keyblock.contents != NULL)
378
krb5_free_keyblock_contents(kdc_context, &state->client_keyblock);
379
if (state->reply.padata != NULL)
380
krb5_free_pa_data(kdc_context, state->reply.padata);
381
if (state->reply_encpart.enc_padata)
382
krb5_free_pa_data(kdc_context, state->reply_encpart.enc_padata);
384
if (state->cname != NULL)
386
if (state->sname != NULL)
388
krb5_db_free_principal(kdc_context, state->client);
389
krb5_db_free_principal(kdc_context, state->server);
390
if (state->session_key.contents != NULL)
391
krb5_free_keyblock_contents(kdc_context, &state->session_key);
392
if (state->ticket_reply.enc_part.ciphertext.data != NULL) {
393
memset(state->ticket_reply.enc_part.ciphertext.data , 0,
394
state->ticket_reply.enc_part.ciphertext.length);
395
free(state->ticket_reply.enc_part.ciphertext.data);
398
krb5_free_pa_data(kdc_context, state->e_data);
399
kdc_free_rstate(state->rstate);
400
krb5_free_kdc_req(kdc_context, state->request);
401
assert(did_log != 0);
404
(*oldrespond)(oldarg, errcode, response);
408
finish_missing_required_preauth(void *arg)
410
struct as_req_state *state = (struct as_req_state *)arg;
412
finish_process_as_req(state, state->preauth_err);
416
finish_preauth(void *arg, krb5_error_code code)
418
struct as_req_state *state = arg;
419
krb5_error_code real_code = code;
423
code = KRB5KRB_ERR_GENERIC;
424
state->status = "PREAUTH_FAILED";
425
if (real_code == KRB5KDC_ERR_PREAUTH_FAILED) {
426
state->preauth_err = code;
427
get_preauth_hint_list(state->request, &state->rock, &state->e_data,
428
finish_missing_required_preauth, state);
433
* Final check before handing out ticket: If the client requires
434
* preauthentication, verify that the proper kind of
435
* preauthentication was carried out.
437
state->status = missing_required_preauth(state->client, state->server,
438
&state->enc_tkt_reply);
440
state->preauth_err = KRB5KDC_ERR_PREAUTH_REQUIRED;
441
get_preauth_hint_list(state->request, &state->rock, &state->e_data,
442
finish_missing_required_preauth, state);
447
finish_process_as_req(state, code);
452
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
453
const krb5_fulladdr *from, loop_respond_fn respond, void *arg)
455
krb5_error_code errcode;
121
456
krb5_timestamp rtime;
122
char *cname = 0, *sname = 0;
123
unsigned int c_flags = 0, s_flags = 0;
457
unsigned int s_flags = 0;
124
458
krb5_principal_data client_princ;
125
void *pa_context = NULL;
127
const char *emsg = 0;
128
struct kdc_request_state *state = NULL;
129
459
krb5_data encoded_req_body;
130
krb5_keyblock *as_encrypting_key = NULL;
460
krb5_enctype useenctype;
461
struct as_req_state *state;
463
state = malloc(sizeof(*state));
465
(*respond)(arg, ENOMEM, NULL);
468
state->session_key.contents = 0;
469
state->enc_tkt_reply.authorization_data = NULL;
470
state->reply.padata = 0;
471
memset(&state->reply, 0, sizeof(state->reply));
472
state->respond = respond;
474
state->ticket_reply.enc_part.ciphertext.data = 0;
475
state->server_keyblock.contents = NULL;
476
state->client_keyblock.contents = NULL;
477
state->reply_encpart.enc_padata = 0;
478
state->client = NULL;
479
state->server = NULL;
480
state->request = request;
481
state->e_data = NULL;
482
state->typed_e_data = FALSE;
485
state->req_pkt = req_pkt;
486
state->rstate = NULL;
489
state->pa_context = NULL;
491
memset(&state->rock, 0, sizeof(state->rock));
134
494
asReqDebug("process_as_req top realm %s name %s\n",
135
495
request->client->realm.data, request->client->data->data);
136
496
#endif /* APPLE_PKINIT */
138
ticket_reply.enc_part.ciphertext.data = 0;
140
server_keyblock.contents = NULL;
141
client_keyblock.contents = NULL;
143
reply_encpart.enc_padata = 0;
144
memset(&reply, 0, sizeof(reply));
146
session_key.contents = 0;
147
enc_tkt_reply.authorization_data = NULL;
149
if (request->msg_type != KRB5_AS_REQ) {
150
status = "msg_type mismatch";
498
if (state->request->msg_type != KRB5_AS_REQ) {
499
state->status = "msg_type mismatch";
151
500
errcode = KRB5_BADMSGTYPE;
154
errcode = kdc_make_rstate(&state);
503
errcode = kdc_make_rstate(&state->rstate);
155
504
if (errcode != 0) {
156
status = "constructing state";
505
state->status = "constructing state";
159
508
if (fetch_asn1_field((unsigned char *) req_pkt->data,
160
509
1, 4, &encoded_req_body) != 0) {
161
510
errcode = ASN1_BAD_ID;
162
status = "Finding req_body";
511
state->status = "Finding req_body";
165
errcode = kdc_find_fast(&request, &encoded_req_body,
166
NULL /*TGS key*/, NULL, state);
514
errcode = kdc_find_fast(&state->request, &encoded_req_body,
515
NULL /*TGS key*/, NULL, state->rstate);
168
status = "error decoding FAST";
517
state->status = "error decoding FAST";
171
request->kdc_state = state;
172
if (!request->client) {
173
status = "NULL_CLIENT";
520
state->rock.request = state->request;
521
state->rock.rstate = state->rstate;
522
if (!state->request->client) {
523
state->status = "NULL_CLIENT";
174
524
errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
177
if ((errcode = krb5_unparse_name(kdc_context, request->client, &cname))) {
178
status = "UNPARSING_CLIENT";
527
if ((errcode = krb5_unparse_name(kdc_context,
528
state->request->client,
530
state->status = "UNPARSING_CLIENT";
182
if (!request->server) {
183
status = "NULL_SERVER";
533
limit_string(state->cname);
534
if (!state->request->server) {
535
state->status = "NULL_SERVER";
184
536
errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
187
if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) {
188
status = "UNPARSING_SERVER";
539
if ((errcode = krb5_unparse_name(kdc_context,
540
state->request->server,
542
state->status = "UNPARSING_SERVER";
545
limit_string(state->sname);
194
548
* We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint
195
549
* to the backend to return naming information in lieu
196
550
* of cross realm TGS entries.
198
setflag(c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY);
552
setflag(state->c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY);
200
554
* Note that according to the referrals draft we should
201
555
* always canonicalize enterprise principal names.
203
if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) ||
204
krb5_princ_type(kdc_context,
205
request->client) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
206
setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE);
207
setflag(c_flags, KRB5_KDB_FLAG_ALIAS_OK);
209
if (include_pac_p(kdc_context, request)) {
210
setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
212
errcode = krb5_db_get_principal(kdc_context, request->client,
557
if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) ||
558
state->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
559
setflag(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE);
560
setflag(state->c_flags, KRB5_KDB_FLAG_ALIAS_OK);
562
if (include_pac_p(kdc_context, state->request)) {
563
setflag(state->c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
565
errcode = krb5_db_get_principal(kdc_context, state->request->client,
566
state->c_flags, &state->client);
214
567
if (errcode == KRB5_KDB_NOENTRY) {
215
status = "CLIENT_NOT_FOUND";
568
state->status = "CLIENT_NOT_FOUND";
216
569
if (vague_errors)
217
570
errcode = KRB5KRB_ERR_GENERIC;
219
572
errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
221
574
} else if (errcode) {
222
status = "LOOKING_UP_CLIENT";
575
state->status = "LOOKING_UP_CLIENT";
578
state->rock.client = state->client;
227
581
* If the backend returned a principal that is not in the local
228
582
* realm, then we need to refer the client to that realm.
230
if (!is_local_principal(client->princ)) {
584
if (!is_local_principal(state->client->princ)) {
231
585
/* Entry is a referral to another realm */
586
state->status = "REFERRAL";
233
587
errcode = KRB5KDC_ERR_WRONG_REALM;
319
674
* realms may refuse to issue renewable tickets
322
if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE))
323
setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
325
if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE))
326
setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
328
if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
329
setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
331
enc_tkt_reply.session = &session_key;
332
if (isflagset(c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
333
client_princ = *(client->princ);
677
if (isflagset(state->request->kdc_options, KDC_OPT_FORWARDABLE))
678
setflag(state->enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
680
if (isflagset(state->request->kdc_options, KDC_OPT_PROXIABLE))
681
setflag(state->enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
683
if (isflagset(state->request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
684
setflag(state->enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
686
state->enc_tkt_reply.session = &state->session_key;
687
if (isflagset(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
688
client_princ = *(state->client->princ);
335
client_princ = *(request->client);
690
client_princ = *(state->request->client);
336
691
/* The realm is always canonicalized */
337
client_princ.realm = *(krb5_princ_realm(context, client->princ));
692
client_princ.realm = state->client->princ->realm;
339
enc_tkt_reply.client = &client_princ;
340
enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
341
enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */
694
state->enc_tkt_reply.client = &client_princ;
695
state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
696
state->enc_tkt_reply.transited.tr_contents = empty_string;
343
if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
344
setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
345
setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
346
enc_tkt_reply.times.starttime = request->from;
698
if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) {
699
setflag(state->enc_tkt_reply.flags, TKT_FLG_POSTDATED);
700
setflag(state->enc_tkt_reply.flags, TKT_FLG_INVALID);
701
state->enc_tkt_reply.times.starttime = state->request->from;
348
enc_tkt_reply.times.starttime = kdc_time;
350
kdc_get_ticket_endtime(kdc_context,
351
enc_tkt_reply.times.starttime,
356
&enc_tkt_reply.times.endtime);
358
if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
359
!isflagset(client->attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
360
(enc_tkt_reply.times.endtime < request->till)) {
703
state->enc_tkt_reply.times.starttime = state->kdc_time;
705
kdc_get_ticket_endtime(kdc_context, state->enc_tkt_reply.times.starttime,
706
kdc_infinity, state->request->till, state->client,
707
state->server, &state->enc_tkt_reply.times.endtime);
709
if (isflagset(state->request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
710
!isflagset(state->client->attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
711
(state->enc_tkt_reply.times.endtime < state->request->till)) {
362
713
/* we set the RENEWABLE option for later processing */
364
setflag(request->kdc_options, KDC_OPT_RENEWABLE);
365
request->rtime = request->till;
715
setflag(state->request->kdc_options, KDC_OPT_RENEWABLE);
716
state->request->rtime = state->request->till;
367
rtime = (request->rtime == 0) ? kdc_infinity : request->rtime;
718
rtime = (state->request->rtime == 0) ? kdc_infinity :
719
state->request->rtime;
369
if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) {
721
if (isflagset(state->request->kdc_options, KDC_OPT_RENEWABLE)) {
371
723
* XXX Should we squelch the output renew_till to be no
372
724
* earlier than the endtime of the ticket?
374
setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
375
enc_tkt_reply.times.renew_till =
376
min(rtime, enc_tkt_reply.times.starttime +
377
min(client->max_renewable_life,
378
min(server->max_renewable_life,
726
setflag(state->enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
727
state->enc_tkt_reply.times.renew_till =
728
min(rtime, state->enc_tkt_reply.times.starttime +
729
min(state->client->max_renewable_life,
730
min(state->server->max_renewable_life,
379
731
max_renewable_life_for_realm)));
381
enc_tkt_reply.times.renew_till = 0; /* XXX */
733
state->enc_tkt_reply.times.renew_till = 0; /* XXX */
384
736
* starttime is optional, and treated as authtime if not present.
385
737
* so we can nuke it if it matches
387
if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
388
enc_tkt_reply.times.starttime = 0;
739
if (state->enc_tkt_reply.times.starttime ==
740
state->enc_tkt_reply.times.authtime)
741
state->enc_tkt_reply.times.starttime = 0;
390
enc_tkt_reply.caddrs = request->addresses;
391
enc_tkt_reply.authorization_data = 0;
743
state->enc_tkt_reply.caddrs = state->request->addresses;
744
state->enc_tkt_reply.authorization_data = 0;
393
746
/* If anonymous requests are being used, adjust the realm of the client
395
if (isflagset(request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) {
396
if (!krb5_principal_compare_any_realm(kdc_context, request->client,
748
if (isflagset(state->request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) {
749
if (!krb5_principal_compare_any_realm(kdc_context,
750
state->request->client,
397
751
krb5_anonymous_principal())) {
398
752
errcode = KRB5KDC_ERR_BADOPTION;
399
status = "Anonymous requested but anonymous principal not used.";
753
state->status = "Anonymous requested but anonymous "
754
"principal not used.";
402
setflag(enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
403
krb5_free_principal(kdc_context, request->client);
757
setflag(state->enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
758
krb5_free_principal(kdc_context, state->request->client);
404
759
errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
760
&state->request->client);
407
status = "Copying anonymous principal";
762
state->status = "Copying anonymous principal";
410
enc_tkt_reply.client = request->client;
411
setflag(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH);
765
state->enc_tkt_reply.client = state->request->client;
766
setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH);
414
770
* Check the preauthentication if it is there.
416
if (request->padata) {
417
errcode = check_padata(kdc_context, client, req_pkt, request,
418
&enc_tkt_reply, &pa_context, &e_data);
420
if (errcode == KRB5KDC_ERR_PREAUTH_FAILED)
421
get_preauth_hint_list(request, client, server, &e_data);
423
status = "PREAUTH_FAILED";
425
errcode = KRB5KRB_ERR_GENERIC;
431
* Final check before handing out ticket: If the client requires
432
* preauthentication, verify that the proper kind of
433
* preauthentication was carried out.
435
status = missing_required_preauth(client, server, &enc_tkt_reply);
437
errcode = KRB5KDC_ERR_PREAUTH_REQUIRED;
438
get_preauth_hint_list(request, client, server, &e_data);
442
if ((errcode = validate_forwardable(request, *client, *server,
443
kdc_time, &status))) {
444
errcode += ERROR_TABLE_BASE_krb5;
448
ticket_reply.enc_part2 = &enc_tkt_reply;
451
* Find the server key
453
if ((errcode = krb5_dbe_find_enctype(kdc_context, server,
454
-1, /* ignore keytype */
455
-1, /* Ignore salttype */
456
0, /* Get highest kvno */
458
status = "FINDING_SERVER_KEY";
463
* Convert server->key into a real key
464
* (it may be encrypted in the database)
466
* server_keyblock is later used to generate auth data signatures
468
if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
469
server_key, &server_keyblock,
471
status = "DECRYPT_SERVER_KEY";
476
* Find the appropriate client key. We search in the order specified
477
* by request keytype list.
479
client_key = (krb5_key_data *) NULL;
480
for (i = 0; i < request->nktypes; i++) {
481
useenctype = request->ktype[i];
482
if (!krb5_c_valid_enctype(useenctype))
485
if (!krb5_dbe_find_enctype(kdc_context, client, useenctype, -1,
490
/* Cannot find an appropriate key */
491
status = "CANT_FIND_CLIENT_KEY";
492
errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
496
/* convert client.key_data into a real key */
497
if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
498
client_key, &client_keyblock,
500
status = "DECRYPT_CLIENT_KEY";
503
client_keyblock.enctype = useenctype;
505
/* Start assembling the response */
506
reply.msg_type = KRB5_AS_REP;
507
reply.client = enc_tkt_reply.client; /* post canonicalization */
508
reply.ticket = &ticket_reply;
509
reply_encpart.session = &session_key;
510
if ((errcode = fetch_last_req_info(client, &reply_encpart.last_req))) {
511
status = "FETCH_LAST_REQ";
514
reply_encpart.nonce = request->nonce;
515
reply_encpart.key_exp = get_key_exp(client);
516
reply_encpart.flags = enc_tkt_reply.flags;
517
reply_encpart.server = ticket_reply.server;
519
/* copy the time fields EXCEPT for authtime; it's location
522
reply_encpart.times = enc_tkt_reply.times;
523
reply_encpart.times.authtime = authtime = kdc_time;
525
reply_encpart.caddrs = enc_tkt_reply.caddrs;
526
reply_encpart.enc_padata = NULL;
528
/* Fetch the padata info to be returned (do this before
529
* authdata to handle possible replacement of reply key
531
errcode = return_padata(kdc_context, client, req_pkt, request,
532
&reply, client_key, &client_keyblock, &pa_context);
534
status = "KDC_RETURN_PADATA";
539
asReqDebug("process_as_req reply realm %s name %s\n",
540
reply.client->realm.data, reply.client->data->data);
541
#endif /* APPLE_PKINIT */
545
errcode = handle_authdata(kdc_context,
555
NULL, /* for_user_princ */
556
NULL, /* enc_tkt_request */
559
krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode);
560
status = "HANDLE_AUTHDATA";
564
errcode = krb5_encrypt_tkt_part(kdc_context, &server_keyblock,
567
status = "ENCRYPTING_TICKET";
570
ticket_reply.enc_part.kvno = server_key->key_data_kvno;
571
errcode = kdc_fast_response_handle_padata(state, request, &reply,
572
client_keyblock.enctype);
574
status = "fast response handling";
578
/* now encode/encrypt the response */
580
reply.enc_part.enctype = client_keyblock.enctype;
582
errcode = kdc_fast_handle_reply_key(state, &client_keyblock,
585
status = "generating reply key";
588
errcode = return_enc_padata(kdc_context, req_pkt, request,
589
as_encrypting_key, server, &reply_encpart,
592
status = "KDC_RETURN_ENC_PADATA";
596
errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart,
597
0, as_encrypting_key, &reply, response);
598
reply.enc_part.kvno = client_key->key_data_kvno;
600
status = "ENCODE_KDC_REP";
604
/* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
605
can use them in raw form if needed. But, we don't... */
606
memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
607
free(reply.enc_part.ciphertext.data);
609
log_as_req(from, request, &reply, client, cname, server, sname,
772
if (state->request->padata) {
773
check_padata(kdc_context, &state->rock, state->req_pkt,
774
state->request, &state->enc_tkt_reply, &state->pa_context,
775
&state->e_data, &state->typed_e_data, finish_preauth,
778
finish_preauth(state, 0);
616
assert (status != 0);
621
free_padata_context(kdc_context, &pa_context);
622
if (as_encrypting_key)
623
krb5_free_keyblock(kdc_context, as_encrypting_key);
625
emsg = krb5_get_error_message(kdc_context, errcode);
628
log_as_req(from, request, &reply, client, cname, server, sname,
629
authtime, status, errcode, emsg);
636
if (errcode == KRB5KDC_ERR_DISCARD)
638
errcode -= ERROR_TABLE_BASE_krb5;
639
if (errcode < 0 || errcode > 128)
640
errcode = KRB_ERR_GENERIC;
642
errcode = prepare_error_as(state, request, errcode, &e_data,
643
(client != NULL) ? client->princ : NULL,
649
krb5_free_error_message(kdc_context, emsg);
650
if (enc_tkt_reply.authorization_data != NULL)
651
krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data);
652
if (server_keyblock.contents != NULL)
653
krb5_free_keyblock_contents(kdc_context, &server_keyblock);
654
if (client_keyblock.contents != NULL)
655
krb5_free_keyblock_contents(kdc_context, &client_keyblock);
656
if (reply.padata != NULL)
657
krb5_free_pa_data(kdc_context, reply.padata);
658
if (reply_encpart.enc_padata)
659
krb5_free_pa_data(kdc_context, reply_encpart.enc_padata);
665
krb5_db_free_principal(kdc_context, client);
666
krb5_db_free_principal(kdc_context, server);
667
if (session_key.contents != NULL)
668
krb5_free_keyblock_contents(kdc_context, &session_key);
669
if (ticket_reply.enc_part.ciphertext.data != NULL) {
670
memset(ticket_reply.enc_part.ciphertext.data , 0,
671
ticket_reply.enc_part.ciphertext.length);
672
free(ticket_reply.enc_part.ciphertext.data);
675
krb5_free_data_contents(kdc_context, &e_data);
676
kdc_free_rstate(state);
677
request->kdc_state = NULL;
678
krb5_free_kdc_req(kdc_context, request);
679
assert(did_log != 0);
782
finish_process_as_req(state, errcode);
684
785
static krb5_error_code
685
786
prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
686
int error, krb5_data *e_data,
787
int error, krb5_pa_data **e_data, krb5_boolean typed_e_data,
687
788
krb5_principal canon_client, krb5_data **response,
688
789
const char *status)
690
791
krb5_error errpkt;
691
792
krb5_error_code retval;
693
krb5_pa_data **pa = NULL;
694
krb5_typed_data **td = NULL;
793
krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
697
795
errpkt.ctime = request->nonce;
698
796
errpkt.cusec = 0;
700
if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime,
798
retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
703
801
errpkt.error = error;
704
802
errpkt.server = request->server;
706
if (error == KRB5KDC_ERR_WRONG_REALM)
707
errpkt.client = canon_client;
709
errpkt.client = request->client;
710
errpkt.text.length = strlen(status);
711
if (!(errpkt.text.data = strdup(status)))
714
if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) {
715
free(errpkt.text.data);
718
if (e_data != NULL&& e_data->data != NULL) {
719
errpkt.e_data = *e_data;
721
errpkt.e_data.length = 0;
722
errpkt.e_data.data = NULL;
724
/*We need to try and produce a padata sequence for FAST*/
725
retval = decode_krb5_padata_sequence(e_data, &pa);
727
retval = decode_krb5_typed_data(e_data, &td);
729
for (size =0; td[size]; size++);
730
pa = calloc(size+1, sizeof(*pa));
734
for (size = 0; td[size]; size++) {
735
krb5_pa_data *pad = malloc(sizeof(krb5_pa_data ));
740
pad->pa_type = td[size]->type;
741
pad->contents = td[size]->data;
742
pad->length = td[size]->length;
744
td[size]->data = NULL;
745
td[size]->length = 0;
747
krb5_free_typed_data(kdc_context, td);
750
retval = kdc_fast_handle_error(kdc_context, rstate,
751
request, pa, &errpkt);
753
retval = krb5_mk_error(kdc_context, &errpkt, scratch);
755
free(errpkt.text.data);
760
krb5_free_pa_data(kdc_context, pa);
803
errpkt.client = (error == KRB5KDC_ERR_WRONG_REALM) ? canon_client :
805
errpkt.text = string2data((char *)status);
807
if (e_data != NULL) {
809
retval = encode_krb5_typed_data((const krb5_typed_data **)e_data,
812
retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
815
errpkt.e_data = *e_data_asn1;
817
errpkt.e_data = empty_data();
819
retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
820
&errpkt, &fast_edata);
823
if (fast_edata != NULL)
824
errpkt.e_data = *fast_edata;
826
scratch = k5alloc(sizeof(*scratch), &retval);
829
retval = krb5_mk_error(kdc_context, &errpkt, scratch);
837
krb5_free_data(kdc_context, fast_edata);
838
krb5_free_data(kdc_context, e_data_asn1);