Line data Source code
1 : /*
2 : * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "kdc_locl.h"
35 :
36 : /*
37 : * return the realm of a krbtgt-ticket or NULL
38 : */
39 :
40 : static Realm
41 79385 : get_krbtgt_realm(const PrincipalName *p)
42 : {
43 81563 : if(p->name_string.len == 2
44 79691 : && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
45 65125 : return p->name_string.val[1];
46 : else
47 16099 : return NULL;
48 : }
49 :
50 : /*
51 : * The KDC might add a signed path to the ticket authorization data
52 : * field. This is to avoid server impersonating clients and the
53 : * request constrained delegation.
54 : *
55 : * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
56 : * entry of type KRB5SignedPath.
57 : */
58 :
59 : static krb5_error_code
60 39896 : find_KRB5SignedPath(krb5_context context,
61 : const AuthorizationData *ad,
62 : krb5_data *data)
63 : {
64 : AuthorizationData child;
65 : krb5_error_code ret;
66 : int pos;
67 :
68 39896 : if (ad == NULL || ad->len == 0)
69 0 : return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
70 :
71 39896 : pos = ad->len - 1;
72 :
73 39896 : if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
74 0 : return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
75 :
76 39896 : ret = decode_AuthorizationData(ad->val[pos].ad_data.data,
77 38807 : ad->val[pos].ad_data.length,
78 : &child,
79 : NULL);
80 39896 : if (ret) {
81 0 : krb5_set_error_message(context, ret, "Failed to decode "
82 : "IF_RELEVANT with %d", ret);
83 0 : return ret;
84 : }
85 :
86 39896 : if (child.len != 1) {
87 0 : free_AuthorizationData(&child);
88 0 : return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
89 : }
90 :
91 39896 : if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) {
92 297 : free_AuthorizationData(&child);
93 297 : return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
94 : }
95 :
96 39599 : if (data)
97 39599 : ret = der_copy_octet_string(&child.val[0].ad_data, data);
98 39599 : free_AuthorizationData(&child);
99 39599 : return ret;
100 : }
101 :
102 : krb5_error_code
103 64870 : _kdc_add_KRB5SignedPath(krb5_context context,
104 : krb5_kdc_configuration *config,
105 : hdb_entry_ex *krbtgt,
106 : krb5_enctype enctype,
107 : krb5_principal client,
108 : krb5_const_principal server,
109 : krb5_principals principals,
110 : EncTicketPart *tkt)
111 : {
112 : krb5_error_code ret;
113 : KRB5SignedPath sp;
114 : krb5_data data;
115 64870 : krb5_crypto crypto = NULL;
116 64870 : size_t size = 0;
117 :
118 64870 : if (server && principals) {
119 0 : ret = add_Principals(principals, server);
120 0 : if (ret)
121 0 : return ret;
122 : }
123 :
124 : {
125 : KRB5SignedPathData spd;
126 :
127 64870 : spd.client = client;
128 64870 : spd.authtime = tkt->authtime;
129 64870 : spd.delegated = principals;
130 64870 : spd.method_data = NULL;
131 :
132 64870 : ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
133 : &spd, &size, ret);
134 64870 : if (ret)
135 0 : return ret;
136 64870 : if (data.length != size)
137 0 : krb5_abortx(context, "internal asn.1 encoder error");
138 : }
139 :
140 : {
141 : Key *key;
142 64870 : ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key);
143 64870 : if (ret == 0)
144 64870 : ret = krb5_crypto_init(context, &key->key, 0, &crypto);
145 64870 : if (ret) {
146 0 : free(data.data);
147 0 : return ret;
148 : }
149 : }
150 :
151 : /*
152 : * Fill in KRB5SignedPath
153 : */
154 :
155 64870 : sp.etype = enctype;
156 64870 : sp.delegated = principals;
157 64870 : sp.method_data = NULL;
158 :
159 64870 : ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
160 : data.data, data.length, &sp.cksum);
161 64870 : krb5_crypto_destroy(context, crypto);
162 64870 : free(data.data);
163 64870 : if (ret)
164 0 : return ret;
165 :
166 64870 : ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
167 64870 : free_Checksum(&sp.cksum);
168 64870 : if (ret)
169 0 : return ret;
170 64870 : if (data.length != size)
171 0 : krb5_abortx(context, "internal asn.1 encoder error");
172 :
173 :
174 : /*
175 : * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
176 : * authorization data field.
177 : */
178 :
179 64870 : ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
180 : KRB5_AUTHDATA_SIGNTICKET, &data);
181 64870 : krb5_data_free(&data);
182 :
183 64870 : return ret;
184 : }
185 :
186 : static krb5_error_code
187 39896 : check_KRB5SignedPath(krb5_context context,
188 : krb5_kdc_configuration *config,
189 : hdb_entry_ex *krbtgt,
190 : krb5_principal cp,
191 : EncTicketPart *tkt,
192 : krb5_principals *delegated,
193 : int *signedpath)
194 : {
195 : krb5_error_code ret;
196 : krb5_data data;
197 39896 : krb5_crypto crypto = NULL;
198 :
199 39896 : if (delegated)
200 39878 : *delegated = NULL;
201 :
202 39896 : ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
203 39896 : if (ret == 0) {
204 : KRB5SignedPathData spd;
205 : KRB5SignedPath sp;
206 39599 : size_t size = 0;
207 :
208 39599 : ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
209 39599 : krb5_data_free(&data);
210 39599 : if (ret)
211 2 : return ret;
212 :
213 39599 : spd.client = cp;
214 39599 : spd.authtime = tkt->authtime;
215 39599 : spd.delegated = sp.delegated;
216 39599 : spd.method_data = sp.method_data;
217 :
218 39599 : ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
219 : &spd, &size, ret);
220 39599 : if (ret) {
221 0 : free_KRB5SignedPath(&sp);
222 0 : return ret;
223 : }
224 39599 : if (data.length != size)
225 0 : krb5_abortx(context, "internal asn.1 encoder error");
226 :
227 : {
228 : Key *key;
229 39599 : ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
230 39599 : if (ret == 0)
231 39599 : ret = krb5_crypto_init(context, &key->key, 0, &crypto);
232 39599 : if (ret) {
233 0 : free(data.data);
234 0 : free_KRB5SignedPath(&sp);
235 0 : return ret;
236 : }
237 : }
238 39599 : ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
239 : data.data, data.length,
240 : &sp.cksum);
241 39599 : krb5_crypto_destroy(context, crypto);
242 39599 : free(data.data);
243 39599 : if (ret) {
244 2 : free_KRB5SignedPath(&sp);
245 2 : kdc_log(context, config, 5,
246 : "KRB5SignedPath not signed correctly, not marking as signed");
247 2 : return 0;
248 : }
249 :
250 39597 : if (delegated && sp.delegated) {
251 :
252 0 : *delegated = malloc(sizeof(*sp.delegated));
253 0 : if (*delegated == NULL) {
254 0 : free_KRB5SignedPath(&sp);
255 0 : return ENOMEM;
256 : }
257 :
258 0 : ret = copy_Principals(*delegated, sp.delegated);
259 0 : if (ret) {
260 0 : free_KRB5SignedPath(&sp);
261 0 : free(*delegated);
262 0 : *delegated = NULL;
263 0 : return ret;
264 : }
265 : }
266 39597 : free_KRB5SignedPath(&sp);
267 :
268 39597 : *signedpath = 1;
269 : }
270 :
271 38805 : return 0;
272 : }
273 :
274 : /*
275 : *
276 : */
277 :
278 : static krb5_error_code
279 39896 : check_PAC(krb5_context context,
280 : krb5_kdc_configuration *config,
281 : const krb5_principal client_principal,
282 : const krb5_principal delegated_proxy_principal,
283 : hdb_entry_ex *client,
284 : hdb_entry_ex *server,
285 : hdb_entry_ex *krbtgt,
286 : const EncryptionKey *server_check_key,
287 : const EncryptionKey *server_sign_key,
288 : const EncryptionKey *krbtgt_sign_key,
289 : EncTicketPart *tkt,
290 : krb5_data *rspac,
291 : int *signedpath)
292 : {
293 39896 : AuthorizationData *ad = tkt->authorization_data;
294 : unsigned i, j;
295 : krb5_error_code ret;
296 :
297 39896 : if (ad == NULL || ad->len == 0)
298 0 : return 0;
299 :
300 38839 : for (i = 0; i < ad->len; i++) {
301 : AuthorizationData child;
302 :
303 39928 : if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
304 0 : continue;
305 :
306 39928 : ret = decode_AuthorizationData(ad->val[i].ad_data.data,
307 38839 : ad->val[i].ad_data.length,
308 : &child,
309 : NULL);
310 39928 : if (ret) {
311 0 : krb5_set_error_message(context, ret, "Failed to decode "
312 : "IF_RELEVANT with %d", ret);
313 39896 : return ret;
314 : }
315 38871 : for (j = 0; j < child.len; j++) {
316 :
317 39928 : if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
318 39896 : int signed_pac = 0;
319 : krb5_pac pac;
320 :
321 : /* Found PAC */
322 79792 : ret = krb5_pac_parse(context,
323 39896 : child.val[j].ad_data.data,
324 38807 : child.val[j].ad_data.length,
325 : &pac);
326 39896 : free_AuthorizationData(&child);
327 39896 : if (ret)
328 0 : return ret;
329 :
330 39896 : ret = krb5_pac_verify(context, pac, tkt->authtime,
331 : client_principal,
332 : server_check_key, NULL);
333 39896 : if (ret) {
334 0 : krb5_pac_free(context, pac);
335 0 : return ret;
336 : }
337 :
338 39896 : ret = _kdc_pac_verify(context, client_principal,
339 : delegated_proxy_principal,
340 : client, server, krbtgt, &pac, &signed_pac);
341 39896 : if (ret) {
342 0 : krb5_pac_free(context, pac);
343 0 : return ret;
344 : }
345 :
346 : /*
347 : * Only re-sign PAC if we could verify it with the PAC
348 : * function. The no-verify case happens when we get in
349 : * a PAC from cross realm from a Windows domain and
350 : * that there is no PAC verification function.
351 : */
352 39896 : if (signed_pac) {
353 39896 : *signedpath = 1;
354 39896 : ret = _krb5_pac_sign(context, pac, tkt->authtime,
355 : client_principal,
356 : server_sign_key, krbtgt_sign_key, rspac);
357 : }
358 39896 : krb5_pac_free(context, pac);
359 :
360 38807 : return ret;
361 : }
362 : }
363 32 : free_AuthorizationData(&child);
364 : }
365 0 : return 0;
366 : }
367 :
368 : /*
369 : *
370 : */
371 :
372 : static krb5_error_code
373 39871 : check_tgs_flags(krb5_context context,
374 : krb5_kdc_configuration *config,
375 : KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
376 : {
377 39871 : KDCOptions f = b->kdc_options;
378 :
379 39871 : if(f.validate){
380 0 : if(!tgt->flags.invalid || tgt->starttime == NULL){
381 0 : kdc_log(context, config, 0,
382 : "Bad request to validate ticket");
383 0 : return KRB5KDC_ERR_BADOPTION;
384 : }
385 0 : if(*tgt->starttime > kdc_time){
386 0 : kdc_log(context, config, 0,
387 : "Early request to validate ticket");
388 0 : return KRB5KRB_AP_ERR_TKT_NYV;
389 : }
390 : /* XXX tkt = tgt */
391 0 : et->flags.invalid = 0;
392 39871 : }else if(tgt->flags.invalid){
393 0 : kdc_log(context, config, 0,
394 : "Ticket-granting ticket has INVALID flag set");
395 0 : return KRB5KRB_AP_ERR_TKT_INVALID;
396 : }
397 :
398 39871 : if(f.forwardable){
399 19479 : if(!tgt->flags.forwardable){
400 186 : kdc_log(context, config, 0,
401 : "Bad request for forwardable ticket");
402 186 : return KRB5KDC_ERR_BADOPTION;
403 : }
404 19293 : et->flags.forwardable = 1;
405 : }
406 39685 : if(f.forwarded){
407 19229 : if(!tgt->flags.forwardable){
408 0 : kdc_log(context, config, 0,
409 : "Request to forward non-forwardable ticket");
410 0 : return KRB5KDC_ERR_BADOPTION;
411 : }
412 19229 : et->flags.forwarded = 1;
413 19229 : et->caddr = b->addresses;
414 : }
415 39685 : if(tgt->flags.forwarded)
416 299 : et->flags.forwarded = 1;
417 :
418 39685 : if(f.proxiable){
419 0 : if(!tgt->flags.proxiable){
420 0 : kdc_log(context, config, 0,
421 : "Bad request for proxiable ticket");
422 0 : return KRB5KDC_ERR_BADOPTION;
423 : }
424 0 : et->flags.proxiable = 1;
425 : }
426 39685 : if(f.proxy){
427 0 : if(!tgt->flags.proxiable){
428 0 : kdc_log(context, config, 0,
429 : "Request to proxy non-proxiable ticket");
430 0 : return KRB5KDC_ERR_BADOPTION;
431 : }
432 0 : et->flags.proxy = 1;
433 0 : et->caddr = b->addresses;
434 : }
435 39685 : if(tgt->flags.proxy)
436 0 : et->flags.proxy = 1;
437 :
438 39685 : if(f.allow_postdate){
439 0 : if(!tgt->flags.may_postdate){
440 0 : kdc_log(context, config, 0,
441 : "Bad request for post-datable ticket");
442 0 : return KRB5KDC_ERR_BADOPTION;
443 : }
444 0 : et->flags.may_postdate = 1;
445 : }
446 39685 : if(f.postdated){
447 0 : if(!tgt->flags.may_postdate){
448 0 : kdc_log(context, config, 0,
449 : "Bad request for postdated ticket");
450 0 : return KRB5KDC_ERR_BADOPTION;
451 : }
452 0 : if(b->from)
453 0 : *et->starttime = *b->from;
454 0 : et->flags.postdated = 1;
455 0 : et->flags.invalid = 1;
456 39685 : }else if(b->from && *b->from > kdc_time + context->max_skew){
457 0 : kdc_log(context, config, 0, "Ticket cannot be postdated");
458 0 : return KRB5KDC_ERR_CANNOT_POSTDATE;
459 : }
460 :
461 39685 : if(f.renewable){
462 42 : if(!tgt->flags.renewable || tgt->renew_till == NULL){
463 12 : kdc_log(context, config, 0,
464 : "Bad request for renewable ticket");
465 12 : return KRB5KDC_ERR_BADOPTION;
466 : }
467 30 : et->flags.renewable = 1;
468 30 : ALLOC(et->renew_till);
469 30 : _kdc_fix_time(&b->rtime);
470 30 : *et->renew_till = *b->rtime;
471 : }
472 39673 : if(f.renew){
473 : time_t old_life;
474 30 : if(!tgt->flags.renewable || tgt->renew_till == NULL){
475 0 : kdc_log(context, config, 0,
476 : "Request to renew non-renewable ticket");
477 0 : return KRB5KDC_ERR_BADOPTION;
478 : }
479 30 : old_life = tgt->endtime;
480 30 : if(tgt->starttime)
481 0 : old_life -= *tgt->starttime;
482 : else
483 30 : old_life -= tgt->authtime;
484 30 : et->endtime = *et->starttime + old_life;
485 30 : if (et->renew_till != NULL)
486 30 : et->endtime = min(*et->renew_till, et->endtime);
487 : }
488 :
489 : #if 0
490 : /* checks for excess flags */
491 : if(f.request_anonymous && !config->allow_anonymous){
492 : kdc_log(context, config, 0,
493 : "Request for anonymous ticket");
494 : return KRB5KDC_ERR_BADOPTION;
495 : }
496 : #endif
497 38584 : return 0;
498 : }
499 :
500 : /*
501 : * Determine if constrained delegation is allowed from this client to this server
502 : */
503 :
504 : static krb5_error_code
505 18 : check_constrained_delegation(krb5_context context,
506 : krb5_kdc_configuration *config,
507 : HDB *clientdb,
508 : hdb_entry_ex *client,
509 : hdb_entry_ex *server,
510 : krb5_const_principal target)
511 : {
512 : const HDB_Ext_Constrained_delegation_acl *acl;
513 : krb5_error_code ret;
514 : size_t i;
515 :
516 : /*
517 : * constrained_delegation (S4U2Proxy) only works within
518 : * the same realm. We use the already canonicalized version
519 : * of the principals here, while "target" is the principal
520 : * provided by the client.
521 : */
522 18 : if(!krb5_realm_compare(context, client->entry.principal, server->entry.principal)) {
523 0 : ret = KRB5KDC_ERR_BADOPTION;
524 0 : kdc_log(context, config, 0,
525 : "Bad request for constrained delegation");
526 0 : return ret;
527 : }
528 :
529 18 : if (clientdb->hdb_check_constrained_delegation) {
530 18 : ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target);
531 18 : if (ret == 0)
532 18 : return 0;
533 : } else {
534 : /* if client delegates to itself, that ok */
535 0 : if (krb5_principal_compare(context, client->entry.principal, server->entry.principal) == TRUE)
536 0 : return 0;
537 :
538 0 : ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
539 0 : if (ret) {
540 0 : krb5_clear_error_message(context);
541 0 : return ret;
542 : }
543 :
544 0 : if (acl) {
545 0 : for (i = 0; i < acl->len; i++) {
546 0 : if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE)
547 0 : return 0;
548 : }
549 : }
550 0 : ret = KRB5KDC_ERR_BADOPTION;
551 : }
552 0 : kdc_log(context, config, 0,
553 : "Bad request for constrained delegation");
554 0 : return ret;
555 : }
556 :
557 : /*
558 : * Determine if s4u2self is allowed from this client to this server
559 : *
560 : * For example, regardless of the principal being impersonated, if the
561 : * 'client' and 'server' are the same, then it's safe.
562 : */
563 :
564 : static krb5_error_code
565 622 : check_s4u2self(krb5_context context,
566 : krb5_kdc_configuration *config,
567 : HDB *clientdb,
568 : hdb_entry_ex *client,
569 : krb5_const_principal server)
570 : {
571 : krb5_error_code ret;
572 :
573 : /* if client does a s4u2self to itself, that ok */
574 622 : if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
575 309 : return 0;
576 :
577 313 : if (clientdb->hdb_check_s4u2self) {
578 313 : ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server);
579 313 : if (ret == 0)
580 313 : return 0;
581 : } else {
582 0 : ret = KRB5KDC_ERR_BADOPTION;
583 : }
584 0 : return ret;
585 : }
586 :
587 : /*
588 : *
589 : */
590 :
591 : static krb5_error_code
592 18 : verify_flags (krb5_context context,
593 : krb5_kdc_configuration *config,
594 : const EncTicketPart *et,
595 : const char *pstr)
596 : {
597 18 : if(et->endtime < kdc_time){
598 0 : kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
599 0 : return KRB5KRB_AP_ERR_TKT_EXPIRED;
600 : }
601 18 : if(et->flags.invalid){
602 0 : kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
603 0 : return KRB5KRB_AP_ERR_TKT_NYV;
604 : }
605 18 : return 0;
606 : }
607 :
608 : /*
609 : *
610 : */
611 :
612 : static krb5_error_code
613 39673 : fix_transited_encoding(krb5_context context,
614 : krb5_kdc_configuration *config,
615 : krb5_boolean check_policy,
616 : const TransitedEncoding *tr,
617 : EncTicketPart *et,
618 : const char *client_realm,
619 : const char *server_realm,
620 : const char *tgt_realm)
621 : {
622 39673 : krb5_error_code ret = 0;
623 : char **realms, **tmp;
624 : unsigned int num_realms;
625 : size_t i;
626 :
627 39673 : switch (tr->tr_type) {
628 38584 : case DOMAIN_X500_COMPRESS:
629 38584 : break;
630 0 : case 0:
631 : /*
632 : * Allow empty content of type 0 because that is was Microsoft
633 : * generates in their TGT.
634 : */
635 0 : if (tr->contents.length == 0)
636 0 : break;
637 0 : kdc_log(context, config, 0,
638 : "Transited type 0 with non empty content");
639 0 : return KRB5KDC_ERR_TRTYPE_NOSUPP;
640 0 : default:
641 0 : kdc_log(context, config, 0,
642 : "Unknown transited type: %u", tr->tr_type);
643 0 : return KRB5KDC_ERR_TRTYPE_NOSUPP;
644 : }
645 :
646 38584 : ret = krb5_domain_x500_decode(context,
647 : tr->contents,
648 : &realms,
649 : &num_realms,
650 : client_realm,
651 : server_realm);
652 39673 : if(ret){
653 0 : krb5_warn(context, ret,
654 : "Decoding transited encoding");
655 0 : return ret;
656 : }
657 39673 : if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
658 : /* not us, so add the previous realm to transited set */
659 0 : if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
660 0 : ret = ERANGE;
661 0 : goto free_realms;
662 : }
663 0 : tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
664 0 : if(tmp == NULL){
665 0 : ret = ENOMEM;
666 0 : goto free_realms;
667 : }
668 0 : realms = tmp;
669 0 : realms[num_realms] = strdup(tgt_realm);
670 0 : if(realms[num_realms] == NULL){
671 0 : ret = ENOMEM;
672 0 : goto free_realms;
673 : }
674 0 : num_realms++;
675 : }
676 39673 : if(num_realms == 0) {
677 39673 : if(strcmp(client_realm, server_realm))
678 57 : kdc_log(context, config, 0,
679 : "cross-realm %s -> %s", client_realm, server_realm);
680 : } else {
681 0 : size_t l = 0;
682 : char *rs;
683 0 : for(i = 0; i < num_realms; i++)
684 0 : l += strlen(realms[i]) + 2;
685 0 : rs = malloc(l);
686 0 : if(rs != NULL) {
687 0 : *rs = '\0';
688 0 : for(i = 0; i < num_realms; i++) {
689 0 : if(i > 0)
690 0 : strlcat(rs, ", ", l);
691 0 : strlcat(rs, realms[i], l);
692 : }
693 0 : kdc_log(context, config, 0,
694 : "cross-realm %s -> %s via [%s]",
695 : client_realm, server_realm, rs);
696 0 : free(rs);
697 : }
698 : }
699 39673 : if(check_policy) {
700 39673 : ret = krb5_check_transited(context, client_realm,
701 : server_realm,
702 : realms, num_realms, NULL);
703 39673 : if(ret) {
704 0 : krb5_warn(context, ret, "cross-realm %s -> %s",
705 : client_realm, server_realm);
706 0 : goto free_realms;
707 : }
708 39673 : et->flags.transited_policy_checked = 1;
709 : }
710 39673 : et->transited.tr_type = DOMAIN_X500_COMPRESS;
711 39673 : ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
712 39673 : if(ret)
713 0 : krb5_warn(context, ret, "Encoding transited encoding");
714 79346 : free_realms:
715 39673 : for(i = 0; i < num_realms; i++)
716 0 : free(realms[i]);
717 39673 : free(realms);
718 39673 : return ret;
719 : }
720 :
721 :
722 : static krb5_error_code
723 39871 : tgs_make_reply(krb5_context context,
724 : krb5_kdc_configuration *config,
725 : KDC_REQ_BODY *b,
726 : krb5_const_principal tgt_name,
727 : const EncTicketPart *tgt,
728 : const krb5_keyblock *replykey,
729 : int rk_is_subkey,
730 : const EncryptionKey *serverkey,
731 : const krb5_keyblock *sessionkey,
732 : krb5_kvno kvno,
733 : AuthorizationData *auth_data,
734 : hdb_entry_ex *server,
735 : krb5_principal server_principal,
736 : const char *server_name,
737 : hdb_entry_ex *client,
738 : krb5_principal client_principal,
739 : hdb_entry_ex *krbtgt,
740 : krb5_enctype krbtgt_etype,
741 : krb5_principals spp,
742 : const krb5_data *rspac,
743 : const METHOD_DATA *enc_pa_data,
744 : const char **e_text,
745 : krb5_data *reply)
746 : {
747 : KDC_REP rep;
748 : EncKDCRepPart ek;
749 : EncTicketPart et;
750 39871 : KDCOptions f = b->kdc_options;
751 : krb5_error_code ret;
752 39871 : int is_weak = 0;
753 :
754 39871 : memset(&rep, 0, sizeof(rep));
755 39871 : memset(&et, 0, sizeof(et));
756 39871 : memset(&ek, 0, sizeof(ek));
757 :
758 39871 : rep.pvno = 5;
759 39871 : rep.msg_type = krb_tgs_rep;
760 :
761 39871 : et.authtime = tgt->authtime;
762 39871 : _kdc_fix_time(&b->till);
763 39871 : et.endtime = min(tgt->endtime, *b->till);
764 39871 : ALLOC(et.starttime);
765 39871 : *et.starttime = kdc_time;
766 :
767 39871 : ret = check_tgs_flags(context, config, b, tgt, &et);
768 39871 : if(ret)
769 198 : goto out;
770 :
771 : /* We should check the transited encoding if:
772 : 1) the request doesn't ask not to be checked
773 : 2) globally enforcing a check
774 : 3) principal requires checking
775 : 4) we allow non-check per-principal, but principal isn't marked as allowing this
776 : 5) we don't globally allow this
777 : */
778 :
779 : #define GLOBAL_FORCE_TRANSITED_CHECK \
780 : (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
781 : #define GLOBAL_ALLOW_PER_PRINCIPAL \
782 : (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
783 : #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
784 : (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
785 :
786 : /* these will consult the database in future release */
787 : #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
788 : #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
789 :
790 119019 : ret = fix_transited_encoding(context, config,
791 39673 : !f.disable_transited_check ||
792 0 : GLOBAL_FORCE_TRANSITED_CHECK ||
793 : PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
794 : !((GLOBAL_ALLOW_PER_PRINCIPAL &&
795 : PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
796 0 : GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
797 : &tgt->transited, &et,
798 : krb5_principal_get_realm(context, client_principal),
799 39673 : krb5_principal_get_realm(context, server->entry.principal),
800 39673 : krb5_principal_get_realm(context, krbtgt->entry.principal));
801 39673 : if(ret)
802 0 : goto out;
803 :
804 39673 : copy_Realm(&server_principal->realm, &rep.ticket.realm);
805 39673 : _krb5_principal2principalname(&rep.ticket.sname, server_principal);
806 39673 : copy_Realm(&tgt_name->realm, &rep.crealm);
807 : /*
808 : if (f.request_anonymous)
809 : _kdc_make_anonymous_principalname (&rep.cname);
810 : else */
811 :
812 39673 : copy_PrincipalName(&tgt_name->name, &rep.cname);
813 39673 : rep.ticket.tkt_vno = 5;
814 :
815 39673 : ek.caddr = et.caddr;
816 39673 : if(et.caddr == NULL)
817 39673 : et.caddr = tgt->caddr;
818 :
819 : {
820 : time_t life;
821 39673 : life = et.endtime - *et.starttime;
822 39673 : if(client && client->entry.max_life)
823 39616 : life = min(life, *client->entry.max_life);
824 39673 : if(server->entry.max_life)
825 38823 : life = min(life, *server->entry.max_life);
826 39673 : et.endtime = *et.starttime + life;
827 : }
828 39673 : if(f.renewable_ok && tgt->flags.renewable &&
829 0 : et.renew_till == NULL && et.endtime < *b->till &&
830 0 : tgt->renew_till != NULL)
831 : {
832 0 : et.flags.renewable = 1;
833 0 : ALLOC(et.renew_till);
834 0 : *et.renew_till = *b->till;
835 : }
836 39673 : if(et.renew_till){
837 : time_t renew;
838 30 : renew = *et.renew_till - et.authtime;
839 30 : if(client && client->entry.max_renew)
840 30 : renew = min(renew, *client->entry.max_renew);
841 30 : if(server->entry.max_renew)
842 30 : renew = min(renew, *server->entry.max_renew);
843 30 : *et.renew_till = et.authtime + renew;
844 : }
845 :
846 39673 : if(et.renew_till){
847 30 : *et.renew_till = min(*et.renew_till, *tgt->renew_till);
848 30 : *et.starttime = min(*et.starttime, *et.renew_till);
849 30 : et.endtime = min(et.endtime, *et.renew_till);
850 : }
851 :
852 39673 : *et.starttime = min(*et.starttime, et.endtime);
853 :
854 39673 : if(*et.starttime == et.endtime){
855 0 : ret = KRB5KDC_ERR_NEVER_VALID;
856 0 : goto out;
857 : }
858 39673 : if(et.renew_till && et.endtime == *et.renew_till){
859 0 : free(et.renew_till);
860 0 : et.renew_till = NULL;
861 0 : et.flags.renewable = 0;
862 : }
863 :
864 39673 : et.flags.pre_authent = tgt->flags.pre_authent;
865 39673 : et.flags.hw_authent = tgt->flags.hw_authent;
866 39673 : et.flags.anonymous = tgt->flags.anonymous;
867 39673 : et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
868 :
869 : /* See MS-KILE 3.3.5.1 */
870 39673 : if (!server->entry.flags.forwardable)
871 1 : et.flags.forwardable = 0;
872 39673 : if (!server->entry.flags.proxiable)
873 851 : et.flags.proxiable = 0;
874 :
875 39673 : if(rspac->length) {
876 : /*
877 : * No not need to filter out the any PAC from the
878 : * auth_data since it's signed by the KDC.
879 : */
880 39673 : ret = _kdc_tkt_add_if_relevant_ad(context, &et,
881 : KRB5_AUTHDATA_WIN2K_PAC, rspac);
882 39673 : if (ret)
883 0 : goto out;
884 : }
885 :
886 39673 : if (auth_data) {
887 0 : unsigned int i = 0;
888 :
889 : /* XXX check authdata */
890 :
891 0 : if (et.authorization_data == NULL) {
892 0 : et.authorization_data = calloc(1, sizeof(*et.authorization_data));
893 0 : if (et.authorization_data == NULL) {
894 0 : ret = ENOMEM;
895 0 : krb5_set_error_message(context, ret, "malloc: out of memory");
896 0 : goto out;
897 : }
898 : }
899 0 : for(i = 0; i < auth_data->len ; i++) {
900 0 : ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
901 0 : if (ret) {
902 0 : krb5_set_error_message(context, ret, "malloc: out of memory");
903 0 : goto out;
904 : }
905 : }
906 :
907 : /* Filter out type KRB5SignedPath */
908 0 : ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
909 0 : if (ret == 0) {
910 0 : if (et.authorization_data->len == 1) {
911 0 : free_AuthorizationData(et.authorization_data);
912 0 : free(et.authorization_data);
913 0 : et.authorization_data = NULL;
914 : } else {
915 0 : AuthorizationData *ad = et.authorization_data;
916 0 : free_AuthorizationDataElement(&ad->val[ad->len - 1]);
917 0 : ad->len--;
918 : }
919 : }
920 : }
921 :
922 39673 : ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
923 39673 : if (ret)
924 0 : goto out;
925 39673 : et.crealm = tgt_name->realm;
926 39673 : et.cname = tgt_name->name;
927 :
928 39673 : ek.key = et.key;
929 : /* MIT must have at least one last_req */
930 39673 : ek.last_req.len = 1;
931 39673 : ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
932 39673 : if (ek.last_req.val == NULL) {
933 0 : ret = ENOMEM;
934 0 : goto out;
935 : }
936 39673 : ek.nonce = b->nonce;
937 39673 : ek.flags = et.flags;
938 39673 : ek.authtime = et.authtime;
939 39673 : ek.starttime = et.starttime;
940 39673 : ek.endtime = et.endtime;
941 39673 : ek.renew_till = et.renew_till;
942 39673 : ek.srealm = rep.ticket.realm;
943 39673 : ek.sname = rep.ticket.sname;
944 :
945 39673 : _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
946 : et.endtime, et.renew_till);
947 :
948 : /* Don't sign cross realm tickets, they can't be checked anyway */
949 : {
950 40423 : char *r = get_krbtgt_realm(&ek.sname);
951 :
952 39334 : if (r == NULL || strcmp(r, ek.srealm) == 0) {
953 38527 : ret = _kdc_add_KRB5SignedPath(context,
954 : config,
955 : krbtgt,
956 : krbtgt_etype,
957 : client_principal,
958 : NULL,
959 : spp,
960 : &et);
961 38527 : if (ret)
962 0 : goto out;
963 : }
964 : }
965 :
966 39673 : if (enc_pa_data->len) {
967 302 : rep.padata = calloc(1, sizeof(*rep.padata));
968 302 : if (rep.padata == NULL) {
969 0 : ret = ENOMEM;
970 0 : goto out;
971 : }
972 302 : ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
973 302 : if (ret)
974 0 : goto out;
975 : }
976 :
977 39673 : if (krb5_enctype_valid(context, et.key.keytype) != 0
978 0 : && _kdc_is_weak_exception(server->entry.principal, et.key.keytype))
979 : {
980 0 : krb5_enctype_enable(context, et.key.keytype);
981 0 : is_weak = 1;
982 : }
983 :
984 :
985 : /* It is somewhat unclear where the etype in the following
986 : encryption should come from. What we have is a session
987 : key in the passed tgt, and a list of preferred etypes
988 : *for the new ticket*. Should we pick the best possible
989 : etype, given the keytype in the tgt, or should we look
990 : at the etype list here as well? What if the tgt
991 : session key is DES3 and we want a ticket with a (say)
992 : CAST session key. Should the DES3 etype be added to the
993 : etype list, even if we don't want a session key with
994 : DES3? */
995 39673 : ret = _kdc_encode_reply(context, config,
996 39673 : &rep, &et, &ek, et.key.keytype,
997 : kvno,
998 : serverkey, 0, replykey, rk_is_subkey,
999 : e_text, reply);
1000 39673 : if (is_weak)
1001 0 : krb5_enctype_disable(context, et.key.keytype);
1002 :
1003 78455 : out:
1004 39871 : free_TGS_REP(&rep);
1005 39871 : free_TransitedEncoding(&et.transited);
1006 39871 : if(et.starttime)
1007 39871 : free(et.starttime);
1008 39871 : if(et.renew_till)
1009 30 : free(et.renew_till);
1010 39871 : if(et.authorization_data) {
1011 39673 : free_AuthorizationData(et.authorization_data);
1012 39673 : free(et.authorization_data);
1013 : }
1014 39871 : free_LastReq(&ek.last_req);
1015 40960 : memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1016 39871 : free_EncryptionKey(&et.key);
1017 39871 : return ret;
1018 : }
1019 :
1020 : static krb5_error_code
1021 40652 : tgs_check_authenticator(krb5_context context,
1022 : krb5_kdc_configuration *config,
1023 : krb5_auth_context ac,
1024 : KDC_REQ_BODY *b,
1025 : const char **e_text,
1026 : krb5_keyblock *key)
1027 : {
1028 : krb5_authenticator auth;
1029 40652 : size_t len = 0;
1030 : unsigned char *buf;
1031 : size_t buf_size;
1032 : krb5_error_code ret;
1033 : krb5_crypto crypto;
1034 :
1035 40652 : krb5_auth_con_getauthenticator(context, ac, &auth);
1036 40652 : if(auth->cksum == NULL){
1037 0 : kdc_log(context, config, 0, "No authenticator in request");
1038 0 : ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1039 0 : goto out;
1040 : }
1041 : /*
1042 : * according to RFC1510 it doesn't need to be keyed,
1043 : * but according to the latest draft it needs to.
1044 : */
1045 40652 : if (
1046 : #if 0
1047 : !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1048 : ||
1049 : #endif
1050 40652 : !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1051 0 : kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1052 0 : auth->cksum->cksumtype);
1053 0 : ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1054 0 : goto out;
1055 : }
1056 :
1057 : /* XXX should not re-encode this */
1058 40652 : ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1059 40652 : if(ret){
1060 0 : const char *msg = krb5_get_error_message(context, ret);
1061 0 : kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
1062 0 : krb5_free_error_message(context, msg);
1063 0 : goto out;
1064 : }
1065 40652 : if(buf_size != len) {
1066 0 : free(buf);
1067 0 : kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1068 0 : *e_text = "KDC internal error";
1069 0 : ret = KRB5KRB_ERR_GENERIC;
1070 0 : goto out;
1071 : }
1072 40652 : ret = krb5_crypto_init(context, key, 0, &crypto);
1073 40652 : if (ret) {
1074 0 : const char *msg = krb5_get_error_message(context, ret);
1075 0 : free(buf);
1076 0 : kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1077 0 : krb5_free_error_message(context, msg);
1078 0 : goto out;
1079 : }
1080 40652 : ret = krb5_verify_checksum(context,
1081 : crypto,
1082 : KRB5_KU_TGS_REQ_AUTH_CKSUM,
1083 : buf,
1084 : len,
1085 40652 : auth->cksum);
1086 40652 : free(buf);
1087 40652 : krb5_crypto_destroy(context, crypto);
1088 40652 : if(ret){
1089 2 : const char *msg = krb5_get_error_message(context, ret);
1090 2 : kdc_log(context, config, 0,
1091 : "Failed to verify authenticator checksum: %s", msg);
1092 2 : krb5_free_error_message(context, msg);
1093 : }
1094 81302 : out:
1095 40652 : free_Authenticator(auth);
1096 40652 : free(auth);
1097 40652 : return ret;
1098 : }
1099 :
1100 : /*
1101 : *
1102 : */
1103 :
1104 : static const char *
1105 0 : find_rpath(krb5_context context, Realm crealm, Realm srealm)
1106 : {
1107 0 : const char *new_realm = krb5_config_get_string(context,
1108 : NULL,
1109 : "capaths",
1110 : crealm,
1111 : srealm,
1112 : NULL);
1113 0 : return new_realm;
1114 : }
1115 :
1116 :
1117 : static krb5_boolean
1118 0 : need_referral(krb5_context context, krb5_kdc_configuration *config,
1119 : const KDCOptions * const options, krb5_principal server,
1120 : krb5_realm **realms)
1121 : {
1122 : const char *name;
1123 :
1124 0 : if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
1125 0 : return FALSE;
1126 :
1127 0 : if (server->name.name_string.len == 1)
1128 0 : name = server->name.name_string.val[0];
1129 0 : else if (server->name.name_string.len == 3) {
1130 : /*
1131 : This is used to give referrals for the
1132 : E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
1133 : SPN form, which is used for inter-domain communication in AD
1134 : */
1135 0 : name = server->name.name_string.val[2];
1136 0 : kdc_log(context, config, 0, "Giving 3 part referral for %s", name);
1137 0 : *realms = malloc(sizeof(char *)*2);
1138 0 : if (*realms == NULL) {
1139 0 : krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1140 0 : return FALSE;
1141 : }
1142 0 : (*realms)[0] = strdup(name);
1143 0 : (*realms)[1] = NULL;
1144 0 : return TRUE;
1145 0 : } else if (server->name.name_string.len > 1)
1146 0 : name = server->name.name_string.val[1];
1147 : else
1148 0 : return FALSE;
1149 :
1150 0 : kdc_log(context, config, 0, "Searching referral for %s", name);
1151 :
1152 0 : return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
1153 : }
1154 :
1155 : static krb5_error_code
1156 41890 : tgs_parse_request(krb5_context context,
1157 : krb5_kdc_configuration *config,
1158 : KDC_REQ_BODY *b,
1159 : const PA_DATA *tgs_req,
1160 : hdb_entry_ex **krbtgt,
1161 : krb5_enctype *krbtgt_etype,
1162 : krb5_ticket **ticket,
1163 : const char **e_text,
1164 : const char *from,
1165 : const struct sockaddr *from_addr,
1166 : time_t **csec,
1167 : int **cusec,
1168 : AuthorizationData **auth_data,
1169 : krb5_keyblock **replykey,
1170 : int *rk_is_subkey)
1171 : {
1172 : static char failed[] = "<unparse_name failed>";
1173 : krb5_ap_req ap_req;
1174 : krb5_error_code ret;
1175 : krb5_principal princ;
1176 41890 : krb5_auth_context ac = NULL;
1177 : krb5_flags ap_req_options;
1178 : krb5_flags verify_ap_req_flags;
1179 : krb5_crypto crypto;
1180 : Key *tkey;
1181 41890 : krb5_keyblock *subkey = NULL;
1182 : unsigned usage;
1183 41890 : krb5uint32 kvno = 0;
1184 41890 : krb5uint32 *kvno_ptr = NULL;
1185 :
1186 41890 : *auth_data = NULL;
1187 41890 : *csec = NULL;
1188 41890 : *cusec = NULL;
1189 41890 : *replykey = NULL;
1190 :
1191 41890 : memset(&ap_req, 0, sizeof(ap_req));
1192 41890 : ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1193 41890 : if(ret){
1194 0 : const char *msg = krb5_get_error_message(context, ret);
1195 0 : kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
1196 0 : krb5_free_error_message(context, msg);
1197 0 : goto out;
1198 : }
1199 :
1200 42979 : if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1201 : /* XXX check for ticket.sname == req.sname */
1202 2 : kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1203 2 : ret = KRB5KDC_ERR_POLICY; /* ? */
1204 2 : goto out;
1205 : }
1206 :
1207 41888 : _krb5_principalname2krb5_principal(context,
1208 : &princ,
1209 : ap_req.ticket.sname,
1210 : ap_req.ticket.realm);
1211 :
1212 41888 : if (ap_req.ticket.enc_part.kvno) {
1213 41831 : kvno = *ap_req.ticket.enc_part.kvno;
1214 41831 : kvno_ptr = &kvno;
1215 : }
1216 41888 : ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, kvno_ptr,
1217 : NULL, krbtgt);
1218 :
1219 41888 : if(ret == HDB_ERR_NOT_FOUND_HERE) {
1220 : char *p;
1221 1232 : ret = krb5_unparse_name(context, princ, &p);
1222 1232 : if (ret != 0)
1223 0 : p = failed;
1224 1232 : krb5_free_principal(context, princ);
1225 1232 : kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p);
1226 1232 : if (ret == 0)
1227 1232 : free(p);
1228 1232 : ret = HDB_ERR_NOT_FOUND_HERE;
1229 1232 : goto out;
1230 40656 : } else if(ret){
1231 0 : const char *msg = krb5_get_error_message(context, ret);
1232 : char *p;
1233 0 : ret = krb5_unparse_name(context, princ, &p);
1234 0 : if (ret != 0)
1235 0 : p = failed;
1236 0 : krb5_free_principal(context, princ);
1237 0 : kdc_log(context, config, 0,
1238 : "Ticket-granting ticket not found in database: %s", msg);
1239 0 : krb5_free_error_message(context, msg);
1240 0 : if (ret == 0)
1241 0 : free(p);
1242 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1243 0 : goto out;
1244 : }
1245 :
1246 81255 : if(ap_req.ticket.enc_part.kvno &&
1247 40599 : *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
1248 : char *p;
1249 :
1250 0 : ret = krb5_unparse_name (context, princ, &p);
1251 0 : krb5_free_principal(context, princ);
1252 0 : if (ret != 0)
1253 0 : p = failed;
1254 0 : kdc_log(context, config, 0,
1255 : "Ticket kvno = %d, DB kvno = %d (%s)",
1256 0 : *ap_req.ticket.enc_part.kvno,
1257 0 : (*krbtgt)->entry.kvno,
1258 : p);
1259 0 : if (ret == 0)
1260 0 : free (p);
1261 0 : ret = KRB5KRB_AP_ERR_BADKEYVER;
1262 0 : goto out;
1263 : }
1264 :
1265 40656 : *krbtgt_etype = ap_req.ticket.enc_part.etype;
1266 :
1267 40656 : ret = hdb_enctype2key(context, &(*krbtgt)->entry,
1268 : ap_req.ticket.enc_part.etype, &tkey);
1269 40656 : if(ret){
1270 0 : char *str = NULL, *p = NULL;
1271 :
1272 0 : krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1273 0 : krb5_unparse_name(context, princ, &p);
1274 0 : kdc_log(context, config, 0,
1275 : "No server key with enctype %s found for %s",
1276 0 : str ? str : "<unknown enctype>",
1277 0 : p ? p : "<unparse_name failed>");
1278 0 : free(str);
1279 0 : free(p);
1280 0 : ret = KRB5KRB_AP_ERR_BADKEYVER;
1281 0 : goto out;
1282 : }
1283 :
1284 40656 : if (b->kdc_options.validate)
1285 0 : verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1286 : else
1287 40656 : verify_ap_req_flags = 0;
1288 :
1289 40656 : ret = krb5_verify_ap_req2(context,
1290 : &ac,
1291 : &ap_req,
1292 : princ,
1293 40656 : &tkey->key,
1294 : verify_ap_req_flags,
1295 : &ap_req_options,
1296 : ticket,
1297 : KRB5_KU_TGS_REQ_AUTH);
1298 :
1299 40656 : krb5_free_principal(context, princ);
1300 40656 : if(ret) {
1301 4 : const char *msg = krb5_get_error_message(context, ret);
1302 4 : kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
1303 4 : krb5_free_error_message(context, msg);
1304 4 : goto out;
1305 : }
1306 :
1307 : {
1308 : krb5_authenticator auth;
1309 :
1310 40652 : ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1311 40652 : if (ret == 0) {
1312 40652 : *csec = malloc(sizeof(**csec));
1313 40652 : if (*csec == NULL) {
1314 0 : krb5_free_authenticator(context, &auth);
1315 0 : kdc_log(context, config, 0, "malloc failed");
1316 0 : goto out;
1317 : }
1318 40652 : **csec = auth->ctime;
1319 40652 : *cusec = malloc(sizeof(**cusec));
1320 40652 : if (*cusec == NULL) {
1321 0 : krb5_free_authenticator(context, &auth);
1322 0 : kdc_log(context, config, 0, "malloc failed");
1323 0 : goto out;
1324 : }
1325 40652 : **cusec = auth->cusec;
1326 40652 : krb5_free_authenticator(context, &auth);
1327 : }
1328 : }
1329 :
1330 40652 : ret = tgs_check_authenticator(context, config,
1331 40652 : ac, b, e_text, &(*ticket)->ticket.key);
1332 40652 : if (ret) {
1333 2 : krb5_auth_con_free(context, ac);
1334 2 : goto out;
1335 : }
1336 :
1337 40650 : usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1338 40650 : *rk_is_subkey = 1;
1339 :
1340 40650 : ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
1341 40650 : if(ret){
1342 0 : const char *msg = krb5_get_error_message(context, ret);
1343 0 : krb5_auth_con_free(context, ac);
1344 0 : kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
1345 0 : krb5_free_error_message(context, msg);
1346 0 : goto out;
1347 : }
1348 40650 : if(subkey == NULL){
1349 2 : usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1350 2 : *rk_is_subkey = 0;
1351 :
1352 2 : ret = krb5_auth_con_getkey(context, ac, &subkey);
1353 2 : if(ret) {
1354 0 : const char *msg = krb5_get_error_message(context, ret);
1355 0 : krb5_auth_con_free(context, ac);
1356 0 : kdc_log(context, config, 0, "Failed to get session key: %s", msg);
1357 0 : krb5_free_error_message(context, msg);
1358 0 : goto out;
1359 : }
1360 : }
1361 40650 : if(subkey == NULL){
1362 0 : krb5_auth_con_free(context, ac);
1363 0 : kdc_log(context, config, 0,
1364 : "Failed to get key for enc-authorization-data");
1365 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1366 0 : goto out;
1367 : }
1368 :
1369 40650 : *replykey = subkey;
1370 :
1371 40650 : if (b->enc_authorization_data) {
1372 : krb5_data ad;
1373 :
1374 0 : ret = krb5_crypto_init(context, subkey, 0, &crypto);
1375 0 : if (ret) {
1376 0 : const char *msg = krb5_get_error_message(context, ret);
1377 0 : krb5_auth_con_free(context, ac);
1378 0 : kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1379 0 : krb5_free_error_message(context, msg);
1380 0 : goto out;
1381 : }
1382 0 : ret = krb5_decrypt_EncryptedData (context,
1383 : crypto,
1384 : usage,
1385 0 : b->enc_authorization_data,
1386 : &ad);
1387 0 : krb5_crypto_destroy(context, crypto);
1388 0 : if(ret){
1389 0 : krb5_auth_con_free(context, ac);
1390 0 : kdc_log(context, config, 0,
1391 : "Failed to decrypt enc-authorization-data");
1392 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1393 0 : goto out;
1394 : }
1395 0 : ALLOC(*auth_data);
1396 0 : if (*auth_data == NULL) {
1397 0 : krb5_auth_con_free(context, ac);
1398 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1399 0 : goto out;
1400 : }
1401 0 : ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
1402 0 : if(ret){
1403 0 : krb5_auth_con_free(context, ac);
1404 0 : free(*auth_data);
1405 0 : *auth_data = NULL;
1406 0 : kdc_log(context, config, 0, "Failed to decode authorization data");
1407 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1408 0 : goto out;
1409 : }
1410 : }
1411 :
1412 40650 : krb5_auth_con_free(context, ac);
1413 :
1414 41890 : out:
1415 41890 : free_AP_REQ(&ap_req);
1416 :
1417 41890 : return ret;
1418 : }
1419 :
1420 : static krb5_error_code
1421 302 : build_server_referral(krb5_context context,
1422 : krb5_kdc_configuration *config,
1423 : krb5_crypto session,
1424 : krb5_const_realm referred_realm,
1425 : const PrincipalName *true_principal_name,
1426 : const PrincipalName *requested_principal,
1427 : krb5_data *outdata)
1428 : {
1429 : PA_ServerReferralData ref;
1430 : krb5_error_code ret;
1431 : EncryptedData ed;
1432 : krb5_data data;
1433 302 : size_t size = 0;
1434 :
1435 302 : memset(&ref, 0, sizeof(ref));
1436 :
1437 302 : if (referred_realm) {
1438 302 : ALLOC(ref.referred_realm);
1439 302 : if (ref.referred_realm == NULL)
1440 0 : goto eout;
1441 302 : *ref.referred_realm = strdup(referred_realm);
1442 302 : if (*ref.referred_realm == NULL)
1443 0 : goto eout;
1444 : }
1445 302 : if (true_principal_name) {
1446 0 : ALLOC(ref.true_principal_name);
1447 0 : if (ref.true_principal_name == NULL)
1448 0 : goto eout;
1449 0 : ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1450 0 : if (ret)
1451 0 : goto eout;
1452 : }
1453 302 : if (requested_principal) {
1454 302 : ALLOC(ref.requested_principal_name);
1455 302 : if (ref.requested_principal_name == NULL)
1456 0 : goto eout;
1457 302 : ret = copy_PrincipalName(requested_principal,
1458 : ref.requested_principal_name);
1459 302 : if (ret)
1460 0 : goto eout;
1461 : }
1462 :
1463 302 : ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1464 : data.data, data.length,
1465 : &ref, &size, ret);
1466 302 : free_PA_ServerReferralData(&ref);
1467 302 : if (ret)
1468 0 : return ret;
1469 302 : if (data.length != size)
1470 0 : krb5_abortx(context, "internal asn.1 encoder error");
1471 :
1472 302 : ret = krb5_encrypt_EncryptedData(context, session,
1473 : KRB5_KU_PA_SERVER_REFERRAL,
1474 : data.data, data.length,
1475 : 0 /* kvno */, &ed);
1476 302 : free(data.data);
1477 302 : if (ret)
1478 0 : return ret;
1479 :
1480 302 : ASN1_MALLOC_ENCODE(EncryptedData,
1481 : outdata->data, outdata->length,
1482 : &ed, &size, ret);
1483 302 : free_EncryptedData(&ed);
1484 302 : if (ret)
1485 0 : return ret;
1486 302 : if (outdata->length != size)
1487 0 : krb5_abortx(context, "internal asn.1 encoder error");
1488 :
1489 302 : return 0;
1490 0 : eout:
1491 0 : free_PA_ServerReferralData(&ref);
1492 0 : krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1493 0 : return ENOMEM;
1494 : }
1495 :
1496 : static krb5_error_code
1497 40650 : tgs_build_reply(krb5_context context,
1498 : krb5_kdc_configuration *config,
1499 : KDC_REQ *req,
1500 : KDC_REQ_BODY *b,
1501 : hdb_entry_ex *krbtgt,
1502 : krb5_enctype krbtgt_etype,
1503 : const krb5_keyblock *replykey,
1504 : int rk_is_subkey,
1505 : krb5_ticket *ticket,
1506 : krb5_data *reply,
1507 : const char *from,
1508 : const char **e_text,
1509 : AuthorizationData **auth_data,
1510 : const struct sockaddr *from_addr)
1511 : {
1512 : krb5_error_code ret;
1513 40650 : krb5_principal cp = NULL, sp = NULL, tp = NULL, dp = NULL;
1514 40650 : krb5_principal krbtgt_principal = NULL;
1515 40650 : char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL;
1516 40650 : hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
1517 : HDB *clientdb, *s4u2self_impersonated_clientdb;
1518 40650 : krb5_realm ref_realm = NULL;
1519 40650 : EncTicketPart *tgt = &ticket->ticket;
1520 40650 : krb5_principals spp = NULL;
1521 : const EncryptionKey *ekey;
1522 : krb5_keyblock sessionkey;
1523 : krb5_kvno kvno;
1524 : krb5_data rspac;
1525 :
1526 40650 : hdb_entry_ex *krbtgt_out = NULL;
1527 :
1528 : METHOD_DATA enc_pa_data;
1529 :
1530 : PrincipalName *s;
1531 : Realm r;
1532 40650 : int nloop = 0;
1533 : EncTicketPart adtkt;
1534 : char opt_str[128];
1535 40650 : int signedpath = 0;
1536 :
1537 : Key *tkey_check;
1538 : Key *tkey_sign;
1539 40650 : int flags = HDB_F_FOR_TGS_REQ;
1540 :
1541 40650 : memset(&sessionkey, 0, sizeof(sessionkey));
1542 40650 : memset(&adtkt, 0, sizeof(adtkt));
1543 40650 : krb5_data_zero(&rspac);
1544 40650 : memset(&enc_pa_data, 0, sizeof(enc_pa_data));
1545 :
1546 40650 : s = b->sname;
1547 40650 : r = b->realm;
1548 :
1549 40650 : if (b->kdc_options.canonicalize)
1550 19576 : flags |= HDB_F_CANON;
1551 :
1552 40650 : if(b->kdc_options.enc_tkt_in_skey){
1553 : Ticket *t;
1554 : hdb_entry_ex *uu;
1555 : krb5_principal p;
1556 : Key *uukey;
1557 0 : krb5uint32 second_kvno = 0;
1558 0 : krb5uint32 *kvno_ptr = NULL;
1559 :
1560 0 : if(b->additional_tickets == NULL ||
1561 0 : b->additional_tickets->len == 0){
1562 0 : ret = KRB5KDC_ERR_BADOPTION; /* ? */
1563 0 : kdc_log(context, config, 0,
1564 : "No second ticket present in request");
1565 0 : goto out;
1566 : }
1567 0 : t = &b->additional_tickets->val[0];
1568 0 : if(!get_krbtgt_realm(&t->sname)){
1569 0 : kdc_log(context, config, 0,
1570 : "Additional ticket is not a ticket-granting ticket");
1571 0 : ret = KRB5KDC_ERR_POLICY;
1572 0 : goto out;
1573 : }
1574 0 : _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1575 0 : if(t->enc_part.kvno){
1576 0 : second_kvno = *t->enc_part.kvno;
1577 0 : kvno_ptr = &second_kvno;
1578 : }
1579 0 : ret = _kdc_db_fetch(context, config, p,
1580 : HDB_F_GET_KRBTGT, kvno_ptr,
1581 : NULL, &uu);
1582 0 : krb5_free_principal(context, p);
1583 0 : if(ret){
1584 0 : if (ret == HDB_ERR_NOENTRY)
1585 0 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1586 0 : goto out;
1587 : }
1588 0 : ret = hdb_enctype2key(context, &uu->entry,
1589 : t->enc_part.etype, &uukey);
1590 0 : if(ret){
1591 0 : _kdc_free_ent(context, uu);
1592 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1593 0 : goto out;
1594 : }
1595 0 : ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1596 0 : _kdc_free_ent(context, uu);
1597 0 : if(ret)
1598 0 : goto out;
1599 :
1600 0 : ret = verify_flags(context, config, &adtkt, spn);
1601 0 : if (ret)
1602 0 : goto out;
1603 :
1604 0 : s = &adtkt.cname;
1605 0 : r = adtkt.crealm;
1606 40650 : } else if (s == NULL) {
1607 3 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1608 3 : krb5_set_error_message(context, ret, "No server in request");
1609 3 : goto out;
1610 : }
1611 :
1612 40647 : _krb5_principalname2krb5_principal(context, &sp, *s, r);
1613 40647 : ret = krb5_unparse_name(context, sp, &spn);
1614 40647 : if (ret)
1615 0 : goto out;
1616 40647 : _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
1617 40647 : ret = krb5_unparse_name(context, cp, &cpn);
1618 40647 : if (ret)
1619 0 : goto out;
1620 40647 : unparse_flags (KDCOptions2int(b->kdc_options),
1621 : asn1_KDCOptions_units(),
1622 : opt_str, sizeof(opt_str));
1623 40647 : if(*opt_str)
1624 39046 : kdc_log(context, config, 0,
1625 : "TGS-REQ %s from %s for %s [%s]",
1626 : cpn, from, spn, opt_str);
1627 : else
1628 1601 : kdc_log(context, config, 0,
1629 : "TGS-REQ %s from %s for %s", cpn, from, spn);
1630 :
1631 : /*
1632 : * Fetch server
1633 : */
1634 :
1635 39558 : server_lookup:
1636 40949 : ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags,
1637 : NULL, NULL, &server);
1638 :
1639 40949 : if(ret == HDB_ERR_NOT_FOUND_HERE) {
1640 47 : kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
1641 47 : goto out;
1642 40902 : } else if (ret == HDB_ERR_WRONG_REALM) {
1643 302 : if (ref_realm)
1644 0 : free(ref_realm);
1645 302 : ref_realm = strdup(server->entry.principal->realm);
1646 302 : if (ref_realm == NULL) {
1647 0 : ret = ENOMEM;
1648 0 : goto out;
1649 : }
1650 :
1651 302 : kdc_log(context, config, 5,
1652 : "Returning a referral to realm %s for "
1653 : "server %s.",
1654 : ref_realm, spn);
1655 302 : krb5_free_principal(context, sp);
1656 302 : sp = NULL;
1657 302 : free(spn);
1658 302 : spn = NULL;
1659 302 : ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1660 : ref_realm, NULL);
1661 302 : if (ret)
1662 0 : goto out;
1663 302 : ret = krb5_unparse_name(context, sp, &spn);
1664 302 : if (ret)
1665 0 : goto out;
1666 :
1667 302 : goto server_lookup;
1668 40600 : } else if(ret){
1669 : const char *new_rlm, *msg;
1670 : Realm req_rlm;
1671 : krb5_realm *realms;
1672 :
1673 722 : if (!config->autodetect_referrals) {
1674 : /* noop */
1675 0 : } else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1676 0 : if(nloop++ < 2) {
1677 0 : new_rlm = find_rpath(context, tgt->crealm, req_rlm);
1678 0 : if(new_rlm) {
1679 0 : kdc_log(context, config, 5, "krbtgt for realm %s "
1680 : "not found, trying %s",
1681 : req_rlm, new_rlm);
1682 0 : krb5_free_principal(context, sp);
1683 0 : free(spn);
1684 0 : krb5_make_principal(context, &sp, r,
1685 : KRB5_TGS_NAME, new_rlm, NULL);
1686 0 : ret = krb5_unparse_name(context, sp, &spn);
1687 0 : if (ret)
1688 722 : goto out;
1689 :
1690 0 : if (ref_realm)
1691 0 : free(ref_realm);
1692 0 : ref_realm = strdup(new_rlm);
1693 0 : goto server_lookup;
1694 : }
1695 : }
1696 0 : } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
1697 0 : if (strcmp(realms[0], sp->realm) != 0) {
1698 0 : kdc_log(context, config, 5,
1699 : "Returning a referral to realm %s for "
1700 : "server %s that was not found",
1701 : realms[0], spn);
1702 0 : krb5_free_principal(context, sp);
1703 0 : free(spn);
1704 0 : krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1705 : realms[0], NULL);
1706 0 : ret = krb5_unparse_name(context, sp, &spn);
1707 0 : if (ret)
1708 0 : goto out;
1709 :
1710 0 : if (ref_realm)
1711 0 : free(ref_realm);
1712 0 : ref_realm = strdup(realms[0]);
1713 :
1714 0 : krb5_free_host_realm(context, realms);
1715 0 : goto server_lookup;
1716 : }
1717 0 : krb5_free_host_realm(context, realms);
1718 : }
1719 722 : msg = krb5_get_error_message(context, ret);
1720 722 : kdc_log(context, config, 0,
1721 : "Server not found in database: %s: %s", spn, msg);
1722 722 : krb5_free_error_message(context, msg);
1723 722 : if (ret == HDB_ERR_NOENTRY)
1724 722 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1725 722 : goto out;
1726 : }
1727 :
1728 : /*
1729 : * Select enctype, return key and kvno.
1730 : */
1731 :
1732 : {
1733 : krb5_enctype etype;
1734 :
1735 39878 : if(b->kdc_options.enc_tkt_in_skey) {
1736 : size_t i;
1737 0 : ekey = &adtkt.key;
1738 0 : for(i = 0; i < b->etype.len; i++)
1739 0 : if (b->etype.val[i] == adtkt.key.keytype)
1740 0 : break;
1741 0 : if(i == b->etype.len) {
1742 0 : kdc_log(context, config, 0,
1743 : "Addition ticket have not matching etypes");
1744 0 : krb5_clear_error_message(context);
1745 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1746 0 : goto out;
1747 : }
1748 0 : etype = b->etype.val[i];
1749 0 : kvno = 0;
1750 : } else {
1751 : Key *skey;
1752 :
1753 79756 : ret = _kdc_find_etype(context,
1754 : config->tgs_use_strongest_session_key, FALSE,
1755 39878 : server, b->etype.val, b->etype.len, NULL,
1756 : &skey);
1757 39878 : if(ret) {
1758 0 : kdc_log(context, config, 0,
1759 : "Server (%s) has no support for etypes", spn);
1760 0 : goto out;
1761 : }
1762 39878 : ekey = &skey->key;
1763 39878 : etype = skey->key.keytype;
1764 39878 : kvno = server->entry.kvno;
1765 : }
1766 :
1767 39878 : ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1768 39878 : if (ret)
1769 0 : goto out;
1770 : }
1771 :
1772 : /*
1773 : * Check that service is in the same realm as the krbtgt. If it's
1774 : * not the same, it's someone that is using a uni-directional trust
1775 : * backward.
1776 : */
1777 :
1778 : /*
1779 : * Validate authoriation data
1780 : */
1781 :
1782 39878 : ret = hdb_enctype2key(context, &krbtgt->entry,
1783 : krbtgt_etype, &tkey_check);
1784 39878 : if(ret) {
1785 0 : kdc_log(context, config, 0,
1786 : "Failed to find key for krbtgt PAC check");
1787 0 : goto out;
1788 : }
1789 :
1790 : /* Now refetch the primary krbtgt, and get the current kvno (the
1791 : * sign check may have been on an old kvno, and the server may
1792 : * have been an incoming trust) */
1793 79756 : ret = krb5_make_principal(context, &krbtgt_principal,
1794 : krb5_principal_get_comp_string(context,
1795 39878 : krbtgt->entry.principal,
1796 : 1),
1797 : KRB5_TGS_NAME,
1798 : krb5_principal_get_comp_string(context,
1799 39878 : krbtgt->entry.principal,
1800 : 1), NULL);
1801 39878 : if(ret) {
1802 0 : kdc_log(context, config, 0,
1803 : "Failed to generate krbtgt principal");
1804 0 : goto out;
1805 : }
1806 :
1807 39878 : ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
1808 39878 : krb5_free_principal(context, krbtgt_principal);
1809 39878 : if (ret) {
1810 : krb5_error_code ret2;
1811 : char *ktpn, *ktpn2;
1812 0 : ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn);
1813 0 : ret2 = krb5_unparse_name(context, krbtgt_principal, &ktpn2);
1814 0 : kdc_log(context, config, 0,
1815 : "Request with wrong krbtgt: %s, %s not found in our database",
1816 : (ret == 0) ? ktpn : "<unknown>", (ret2 == 0) ? ktpn2 : "<unknown>");
1817 0 : if(ret == 0)
1818 0 : free(ktpn);
1819 0 : if(ret2 == 0)
1820 0 : free(ktpn2);
1821 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1822 0 : goto out;
1823 : }
1824 :
1825 : /* The first realm is the realm of the service, the second is
1826 : * krbtgt/<this>/@REALM component of the krbtgt DN the request was
1827 : * encrypted to. The redirection via the krbtgt_out entry allows
1828 : * the DB to possibly correct the case of the realm (Samba4 does
1829 : * this) before the strcmp() */
1830 39878 : if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
1831 39878 : krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
1832 : char *ktpn;
1833 0 : ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn);
1834 0 : kdc_log(context, config, 0,
1835 : "Request with wrong krbtgt: %s",
1836 : (ret == 0) ? ktpn : "<unknown>");
1837 0 : if(ret == 0)
1838 0 : free(ktpn);
1839 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1840 : }
1841 :
1842 39878 : ret = hdb_enctype2key(context, &krbtgt_out->entry,
1843 : krbtgt_etype, &tkey_sign);
1844 39878 : if(ret) {
1845 0 : kdc_log(context, config, 0,
1846 : "Failed to find key for krbtgt PAC signature");
1847 0 : goto out;
1848 : }
1849 :
1850 39878 : ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags,
1851 : NULL, &clientdb, &client);
1852 39878 : if(ret == HDB_ERR_NOT_FOUND_HERE) {
1853 : /* This is OK, we are just trying to find out if they have
1854 : * been disabled or deleted in the meantime, missing secrets
1855 : * is OK */
1856 39878 : } else if(ret){
1857 : const char *krbtgt_realm, *msg;
1858 :
1859 : /*
1860 : * If the client belongs to the same realm as our krbtgt, it
1861 : * should exist in the local database.
1862 : *
1863 : */
1864 :
1865 57 : krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal);
1866 :
1867 57 : if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1868 0 : if (ret == HDB_ERR_NOENTRY)
1869 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1870 0 : kdc_log(context, config, 1, "Client no longer in database: %s",
1871 : cpn);
1872 0 : goto out;
1873 : }
1874 :
1875 57 : msg = krb5_get_error_message(context, ret);
1876 57 : kdc_log(context, config, 1, "Client not found in database: %s", msg);
1877 57 : krb5_free_error_message(context, msg);
1878 : }
1879 :
1880 39878 : ret = check_PAC(context, config, cp, NULL,
1881 : client, server, krbtgt,
1882 39878 : &tkey_check->key,
1883 39878 : ekey, &tkey_sign->key,
1884 : tgt, &rspac, &signedpath);
1885 39878 : if (ret) {
1886 0 : const char *msg = krb5_get_error_message(context, ret);
1887 0 : kdc_log(context, config, 0,
1888 : "Verify PAC failed for %s (%s) from %s with %s",
1889 : spn, cpn, from, msg);
1890 0 : krb5_free_error_message(context, msg);
1891 0 : goto out;
1892 : }
1893 :
1894 : /* also check the krbtgt for signature */
1895 39878 : ret = check_KRB5SignedPath(context,
1896 : config,
1897 : krbtgt,
1898 : cp,
1899 : tgt,
1900 : &spp,
1901 : &signedpath);
1902 39878 : if (ret) {
1903 0 : const char *msg = krb5_get_error_message(context, ret);
1904 0 : kdc_log(context, config, 0,
1905 : "KRB5SignedPath check failed for %s (%s) from %s with %s",
1906 : spn, cpn, from, msg);
1907 0 : krb5_free_error_message(context, msg);
1908 0 : goto out;
1909 : }
1910 :
1911 : /*
1912 : * Process request
1913 : */
1914 :
1915 : /* by default the tgt principal matches the client principal */
1916 39878 : tp = cp;
1917 39878 : tpn = cpn;
1918 :
1919 39878 : if (client) {
1920 : const PA_DATA *sdata;
1921 39821 : int i = 0;
1922 :
1923 39821 : sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
1924 39821 : if (sdata) {
1925 : krb5_crypto crypto;
1926 : krb5_data datack;
1927 : PA_S4U2Self self;
1928 : const char *str;
1929 :
1930 625 : ret = decode_PA_S4U2Self(sdata->padata_value.data,
1931 : sdata->padata_value.length,
1932 : &self, NULL);
1933 625 : if (ret) {
1934 0 : kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
1935 0 : goto out;
1936 : }
1937 :
1938 625 : if (!krb5_checksum_is_keyed(context, self.cksum.cksumtype)) {
1939 1 : free_PA_S4U2Self(&self);
1940 1 : kdc_log(context, config, 0, "Reject PA-S4U2Self with unkeyed checksum");
1941 1 : ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1942 1 : goto out;
1943 : }
1944 :
1945 624 : ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
1946 624 : if (ret)
1947 0 : goto out;
1948 :
1949 624 : ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1950 624 : if (ret) {
1951 0 : const char *msg = krb5_get_error_message(context, ret);
1952 0 : free_PA_S4U2Self(&self);
1953 0 : krb5_data_free(&datack);
1954 0 : kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1955 0 : krb5_free_error_message(context, msg);
1956 0 : goto out;
1957 : }
1958 :
1959 : /* Allow HMAC_MD5 checksum with any key type */
1960 624 : if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
1961 : unsigned char csdata[16];
1962 : Checksum cs;
1963 :
1964 117 : cs.checksum.length = sizeof(csdata);
1965 117 : cs.checksum.data = &csdata;
1966 :
1967 234 : ret = _krb5_HMAC_MD5_checksum(context, &crypto->key,
1968 117 : datack.data, datack.length,
1969 : KRB5_KU_OTHER_CKSUM, &cs);
1970 234 : if (ret == 0 &&
1971 117 : krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0)
1972 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1973 : }
1974 : else {
1975 507 : ret = krb5_verify_checksum(context,
1976 : crypto,
1977 : KRB5_KU_OTHER_CKSUM,
1978 : datack.data,
1979 : datack.length,
1980 : &self.cksum);
1981 : }
1982 624 : krb5_data_free(&datack);
1983 624 : krb5_crypto_destroy(context, crypto);
1984 624 : if (ret) {
1985 2 : const char *msg = krb5_get_error_message(context, ret);
1986 2 : free_PA_S4U2Self(&self);
1987 2 : kdc_log(context, config, 0,
1988 : "krb5_verify_checksum failed for S4U2Self: %s", msg);
1989 2 : krb5_free_error_message(context, msg);
1990 2 : goto out;
1991 : }
1992 :
1993 622 : ret = _krb5_principalname2krb5_principal(context,
1994 : &tp,
1995 : self.name,
1996 : self.realm);
1997 622 : free_PA_S4U2Self(&self);
1998 622 : if (ret)
1999 0 : goto out;
2000 :
2001 622 : ret = krb5_unparse_name(context, tp, &tpn);
2002 622 : if (ret)
2003 0 : goto out;
2004 :
2005 622 : ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags,
2006 : NULL, &s4u2self_impersonated_clientdb,
2007 : &s4u2self_impersonated_client);
2008 622 : if (ret) {
2009 : const char *msg;
2010 :
2011 : /*
2012 : * If the client belongs to the same realm as our krbtgt, it
2013 : * should exist in the local database.
2014 : *
2015 : */
2016 :
2017 0 : if (ret == HDB_ERR_NOENTRY)
2018 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2019 0 : msg = krb5_get_error_message(context, ret);
2020 0 : kdc_log(context, config, 1,
2021 : "S2U4Self principal to impersonate %s not found in database: %s",
2022 : tpn, msg);
2023 0 : krb5_free_error_message(context, msg);
2024 0 : goto out;
2025 : }
2026 :
2027 : /* Ignore pw_end attributes (as Windows does),
2028 : * since S4U2Self is not password authentication. */
2029 622 : free(s4u2self_impersonated_client->entry.pw_end);
2030 622 : s4u2self_impersonated_client->entry.pw_end = NULL;
2031 :
2032 622 : ret = kdc_check_flags(context, config, s4u2self_impersonated_client, tpn,
2033 : NULL, NULL, FALSE);
2034 622 : if (ret)
2035 0 : goto out;
2036 :
2037 : /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
2038 622 : if(rspac.data) {
2039 622 : krb5_pac p = NULL;
2040 622 : krb5_data_free(&rspac);
2041 622 : ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p);
2042 622 : if (ret) {
2043 0 : kdc_log(context, config, 0, "PAC generation failed for -- %s",
2044 : tpn);
2045 0 : goto out;
2046 : }
2047 622 : if (p != NULL) {
2048 622 : ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
2049 622 : s4u2self_impersonated_client->entry.principal,
2050 622 : ekey, &tkey_sign->key,
2051 : &rspac);
2052 622 : krb5_pac_free(context, p);
2053 622 : if (ret) {
2054 0 : kdc_log(context, config, 0, "PAC signing failed for -- %s",
2055 : tpn);
2056 0 : goto out;
2057 : }
2058 : }
2059 : }
2060 :
2061 : /*
2062 : * Check that service doing the impersonating is
2063 : * requesting a ticket to it-self.
2064 : */
2065 622 : ret = check_s4u2self(context, config, clientdb, client, sp);
2066 622 : if (ret) {
2067 0 : kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
2068 : "to impersonate to service "
2069 : "(tried for user %s to service %s)",
2070 : cpn, tpn, spn);
2071 0 : goto out;
2072 : }
2073 :
2074 : /*
2075 : * If the service isn't trusted for authentication to
2076 : * delegation or if the impersonate client is disallowed
2077 : * forwardable, remove the forwardable flag.
2078 : */
2079 :
2080 743 : if (client->entry.flags.trusted_for_delegation &&
2081 121 : s4u2self_impersonated_client->entry.flags.forwardable) {
2082 120 : str = "[forwardable]";
2083 : } else {
2084 502 : b->kdc_options.forwardable = 0;
2085 502 : str = "";
2086 : }
2087 622 : kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
2088 : "service %s %s", cpn, tpn, spn, str);
2089 : }
2090 : }
2091 :
2092 : /*
2093 : * Constrained delegation
2094 : */
2095 :
2096 39875 : if (client != NULL
2097 39818 : && b->additional_tickets != NULL
2098 22 : && b->additional_tickets->len != 0
2099 22 : && b->kdc_options.enc_tkt_in_skey == 0)
2100 : {
2101 22 : int ad_signedpath = 0;
2102 : Key *clientkey;
2103 : Ticket *t;
2104 :
2105 : /*
2106 : * Require that the KDC have issued the service's krbtgt (not
2107 : * self-issued ticket with kimpersonate(1).
2108 : */
2109 22 : if (!signedpath) {
2110 0 : ret = KRB5KDC_ERR_BADOPTION;
2111 0 : kdc_log(context, config, 0,
2112 : "Constrained delegation done on service ticket %s/%s",
2113 : cpn, spn);
2114 0 : goto out;
2115 : }
2116 :
2117 22 : t = &b->additional_tickets->val[0];
2118 :
2119 22 : ret = hdb_enctype2key(context, &client->entry,
2120 : t->enc_part.etype, &clientkey);
2121 22 : if(ret){
2122 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2123 0 : goto out;
2124 : }
2125 :
2126 22 : ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
2127 22 : if (ret) {
2128 0 : kdc_log(context, config, 0,
2129 : "failed to decrypt ticket for "
2130 : "constrained delegation from %s to %s ", cpn, spn);
2131 0 : goto out;
2132 : }
2133 :
2134 22 : ret = _krb5_principalname2krb5_principal(context,
2135 : &tp,
2136 : adtkt.cname,
2137 : adtkt.crealm);
2138 22 : if (ret)
2139 0 : goto out;
2140 :
2141 22 : ret = krb5_unparse_name(context, tp, &tpn);
2142 22 : if (ret)
2143 0 : goto out;
2144 :
2145 22 : ret = _krb5_principalname2krb5_principal(context,
2146 : &dp,
2147 : t->sname,
2148 : t->realm);
2149 22 : if (ret)
2150 0 : goto out;
2151 :
2152 22 : ret = krb5_unparse_name(context, dp, &dpn);
2153 22 : if (ret)
2154 0 : goto out;
2155 :
2156 : /* check that ticket is valid */
2157 22 : if (adtkt.flags.forwardable == 0) {
2158 4 : kdc_log(context, config, 0,
2159 : "Missing forwardable flag on ticket for "
2160 : "constrained delegation from %s (%s) as %s to %s ",
2161 : cpn, dpn, tpn, spn);
2162 4 : ret = KRB5KDC_ERR_BADOPTION;
2163 4 : goto out;
2164 : }
2165 :
2166 18 : ret = check_constrained_delegation(context, config, clientdb,
2167 : client, server, sp);
2168 18 : if (ret) {
2169 0 : kdc_log(context, config, 0,
2170 : "constrained delegation from %s (%s) as %s to %s not allowed",
2171 : cpn, dpn, tpn, spn);
2172 0 : goto out;
2173 : }
2174 :
2175 18 : ret = verify_flags(context, config, &adtkt, tpn);
2176 18 : if (ret) {
2177 0 : goto out;
2178 : }
2179 :
2180 18 : krb5_data_free(&rspac);
2181 :
2182 : /*
2183 : * generate the PAC for the user.
2184 : *
2185 : * TODO: pass in t->sname and t->realm and build
2186 : * a S4U_DELEGATION_INFO blob to the PAC.
2187 : */
2188 18 : ret = check_PAC(context, config, tp, dp,
2189 : client, server, krbtgt,
2190 18 : &clientkey->key,
2191 18 : ekey, &tkey_sign->key,
2192 : &adtkt, &rspac, &ad_signedpath);
2193 18 : if (ret) {
2194 0 : const char *msg = krb5_get_error_message(context, ret);
2195 0 : kdc_log(context, config, 0,
2196 : "Verify delegated PAC failed to %s for client"
2197 : "%s (%s) as %s from %s with %s",
2198 : spn, cpn, dpn, tpn, from, msg);
2199 0 : krb5_free_error_message(context, msg);
2200 0 : goto out;
2201 : }
2202 :
2203 : /*
2204 : * Check that the KDC issued the user's ticket.
2205 : */
2206 18 : ret = check_KRB5SignedPath(context,
2207 : config,
2208 : krbtgt,
2209 : cp,
2210 : &adtkt,
2211 : NULL,
2212 : &ad_signedpath);
2213 18 : if (ret) {
2214 0 : const char *msg = krb5_get_error_message(context, ret);
2215 0 : kdc_log(context, config, 0,
2216 : "KRB5SignedPath check from service %s failed "
2217 : "for delegation to %s for client %s (%s)"
2218 : "from %s failed with %s",
2219 : spn, tpn, dpn, cpn, from, msg);
2220 0 : krb5_free_error_message(context, msg);
2221 0 : goto out;
2222 : }
2223 :
2224 18 : if (!ad_signedpath) {
2225 0 : ret = KRB5KDC_ERR_BADOPTION;
2226 0 : kdc_log(context, config, 0,
2227 : "Ticket not signed with PAC nor SignedPath service %s failed "
2228 : "for delegation to %s for client %s (%s)"
2229 : "from %s",
2230 : spn, tpn, dpn, cpn, from);
2231 0 : goto out;
2232 : }
2233 :
2234 18 : kdc_log(context, config, 0, "constrained delegation for %s "
2235 : "from %s (%s) to %s", tpn, cpn, dpn, spn);
2236 : }
2237 :
2238 : /*
2239 : * Check flags
2240 : */
2241 :
2242 39871 : ret = kdc_check_flags(context, config,
2243 : client, cpn,
2244 : server, spn,
2245 : FALSE);
2246 39871 : if(ret)
2247 0 : goto out;
2248 :
2249 39901 : if((b->kdc_options.validate || b->kdc_options.renew) &&
2250 30 : !krb5_principal_compare(context,
2251 30 : krbtgt->entry.principal,
2252 30 : server->entry.principal)){
2253 0 : kdc_log(context, config, 0, "Inconsistent request.");
2254 0 : ret = KRB5KDC_ERR_SERVER_NOMATCH;
2255 0 : goto out;
2256 : }
2257 :
2258 : /* check for valid set of addresses */
2259 39871 : if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
2260 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2261 0 : kdc_log(context, config, 0, "Request from wrong address");
2262 0 : goto out;
2263 : }
2264 :
2265 : /*
2266 : * If this is an referral, add server referral data to the
2267 : * auth_data reply .
2268 : */
2269 39871 : if (ref_realm) {
2270 : PA_DATA pa;
2271 : krb5_crypto crypto;
2272 :
2273 302 : kdc_log(context, config, 0,
2274 : "Adding server referral to %s", ref_realm);
2275 :
2276 302 : ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
2277 302 : if (ret)
2278 0 : goto out;
2279 :
2280 302 : ret = build_server_referral(context, config, crypto, ref_realm,
2281 : NULL, s, &pa.padata_value);
2282 302 : krb5_crypto_destroy(context, crypto);
2283 302 : if (ret) {
2284 0 : kdc_log(context, config, 0,
2285 : "Failed building server referral");
2286 0 : goto out;
2287 : }
2288 302 : pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
2289 :
2290 302 : ret = add_METHOD_DATA(&enc_pa_data, &pa);
2291 302 : krb5_data_free(&pa.padata_value);
2292 302 : if (ret) {
2293 0 : kdc_log(context, config, 0,
2294 : "Add server referral METHOD-DATA failed");
2295 0 : goto out;
2296 : }
2297 : }
2298 :
2299 : /*
2300 : *
2301 : */
2302 :
2303 79742 : ret = tgs_make_reply(context,
2304 : config,
2305 : b,
2306 : tp,
2307 : tgt,
2308 : replykey,
2309 : rk_is_subkey,
2310 : ekey,
2311 : &sessionkey,
2312 : kvno,
2313 : *auth_data,
2314 : server,
2315 39871 : server->entry.principal,
2316 : spn,
2317 : client,
2318 : cp,
2319 : krbtgt_out,
2320 : krbtgt_etype,
2321 : spp,
2322 : &rspac,
2323 : &enc_pa_data,
2324 : e_text,
2325 : reply);
2326 :
2327 40650 : out:
2328 40650 : if (tpn != cpn)
2329 1413 : free(tpn);
2330 40650 : free(spn);
2331 40650 : free(cpn);
2332 40650 : if (dpn)
2333 22 : free(dpn);
2334 :
2335 40650 : krb5_data_free(&rspac);
2336 40650 : krb5_free_keyblock_contents(context, &sessionkey);
2337 40650 : if(krbtgt_out)
2338 39878 : _kdc_free_ent(context, krbtgt_out);
2339 40650 : if(server)
2340 39878 : _kdc_free_ent(context, server);
2341 40650 : if(client)
2342 39821 : _kdc_free_ent(context, client);
2343 40650 : if(s4u2self_impersonated_client)
2344 622 : _kdc_free_ent(context, s4u2self_impersonated_client);
2345 :
2346 40650 : if (tp && tp != cp)
2347 644 : krb5_free_principal(context, tp);
2348 40650 : if (cp)
2349 40647 : krb5_free_principal(context, cp);
2350 40650 : if (dp)
2351 22 : krb5_free_principal(context, dp);
2352 40650 : if (sp)
2353 40647 : krb5_free_principal(context, sp);
2354 40650 : if (ref_realm)
2355 302 : free(ref_realm);
2356 40650 : free_METHOD_DATA(&enc_pa_data);
2357 :
2358 40650 : free_EncTicketPart(&adtkt);
2359 :
2360 40650 : return ret;
2361 : }
2362 :
2363 : /*
2364 : *
2365 : */
2366 :
2367 : krb5_error_code
2368 41890 : _kdc_tgs_rep(krb5_context context,
2369 : krb5_kdc_configuration *config,
2370 : KDC_REQ *req,
2371 : krb5_data *data,
2372 : const char *from,
2373 : struct sockaddr *from_addr,
2374 : int datagram_reply)
2375 : {
2376 41890 : AuthorizationData *auth_data = NULL;
2377 : krb5_error_code ret;
2378 41890 : int i = 0;
2379 : const PA_DATA *tgs_req;
2380 :
2381 41890 : hdb_entry_ex *krbtgt = NULL;
2382 41890 : krb5_ticket *ticket = NULL;
2383 41890 : const char *e_text = NULL;
2384 41890 : krb5_enctype krbtgt_etype = ETYPE_NULL;
2385 :
2386 41890 : krb5_keyblock *replykey = NULL;
2387 41890 : int rk_is_subkey = 0;
2388 41890 : time_t *csec = NULL;
2389 41890 : int *cusec = NULL;
2390 :
2391 41890 : if(req->padata == NULL){
2392 0 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2393 0 : kdc_log(context, config, 0,
2394 : "TGS-REQ from %s without PA-DATA", from);
2395 0 : goto out;
2396 : }
2397 :
2398 41890 : tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2399 :
2400 41890 : if(tgs_req == NULL){
2401 0 : ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2402 :
2403 0 : kdc_log(context, config, 0,
2404 : "TGS-REQ from %s without PA-TGS-REQ", from);
2405 0 : goto out;
2406 : }
2407 41890 : ret = tgs_parse_request(context, config,
2408 : &req->req_body, tgs_req,
2409 : &krbtgt,
2410 : &krbtgt_etype,
2411 : &ticket,
2412 : &e_text,
2413 : from, from_addr,
2414 : &csec, &cusec,
2415 : &auth_data,
2416 : &replykey,
2417 : &rk_is_subkey);
2418 41890 : if (ret == HDB_ERR_NOT_FOUND_HERE) {
2419 : /* kdc_log() is called in tgs_parse_request() */
2420 1232 : goto out;
2421 : }
2422 40658 : if (ret) {
2423 8 : kdc_log(context, config, 0,
2424 : "Failed parsing TGS-REQ from %s", from);
2425 8 : goto out;
2426 : }
2427 :
2428 40650 : ret = tgs_build_reply(context,
2429 : config,
2430 : req,
2431 : &req->req_body,
2432 : krbtgt,
2433 : krbtgt_etype,
2434 : replykey,
2435 : rk_is_subkey,
2436 : ticket,
2437 : data,
2438 : from,
2439 : &e_text,
2440 : &auth_data,
2441 : from_addr);
2442 40650 : if (ret) {
2443 977 : kdc_log(context, config, 0,
2444 : "Failed building TGS-REP to %s", from);
2445 977 : goto out;
2446 : }
2447 :
2448 : /* */
2449 39706 : if (datagram_reply && data->length > config->max_datagram_reply_length) {
2450 0 : krb5_data_free(data);
2451 0 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2452 0 : e_text = "Reply packet too large";
2453 : }
2454 :
2455 81563 : out:
2456 41890 : if (replykey)
2457 40650 : krb5_free_keyblock(context, replykey);
2458 41890 : if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
2459 938 : krb5_mk_error(context,
2460 : ret,
2461 : NULL,
2462 : NULL,
2463 : NULL,
2464 : NULL,
2465 : csec,
2466 : cusec,
2467 : data);
2468 938 : ret = 0;
2469 : }
2470 41890 : free(csec);
2471 41890 : free(cusec);
2472 41890 : if (ticket)
2473 40652 : krb5_free_ticket(context, ticket);
2474 41890 : if(krbtgt)
2475 40656 : _kdc_free_ent(context, krbtgt);
2476 :
2477 41890 : if (auth_data) {
2478 0 : free_AuthorizationData(auth_data);
2479 0 : free(auth_data);
2480 : }
2481 :
2482 41890 : return ret;
2483 : }
|