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 0 : get_krbtgt_realm(const PrincipalName *p)
42 : {
43 0 : if(p->name_string.len == 2
44 0 : && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
45 0 : return p->name_string.val[1];
46 : else
47 0 : return NULL;
48 : }
49 :
50 : /*
51 : * return TRUE if client was a synthetic principal, as indicated by
52 : * authorization data
53 : */
54 : krb5_boolean
55 50386 : _kdc_synthetic_princ_used_p(krb5_context context, krb5_ticket *ticket)
56 : {
57 1658 : krb5_data synthetic_princ_used;
58 1658 : krb5_error_code ret;
59 :
60 50386 : ret = krb5_ticket_get_authorization_data_type(context, ticket,
61 : KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
62 : &synthetic_princ_used);
63 50386 : if (ret == ENOENT)
64 50386 : ret = krb5_ticket_get_authorization_data_type(context, ticket,
65 : KRB5_AUTHDATA_INITIAL_VERIFIED_CAS,
66 : &synthetic_princ_used);
67 :
68 50386 : if (ret == 0)
69 16 : krb5_data_free(&synthetic_princ_used);
70 :
71 50386 : return ret == 0;
72 : }
73 :
74 : /*
75 : *
76 : */
77 :
78 : krb5_error_code
79 50630 : _kdc_check_pac(astgs_request_t r,
80 : const krb5_principal client_principal,
81 : hdb_entry *delegated_proxy,
82 : hdb_entry *client,
83 : hdb_entry *server,
84 : hdb_entry *krbtgt,
85 : hdb_entry *ticket_server,
86 : const EncryptionKey *server_check_key,
87 : const EncryptionKey *krbtgt_check_key,
88 : EncTicketPart *tkt,
89 : krb5_boolean *kdc_issued,
90 : krb5_pac *ppac,
91 : krb5_principal *pac_canon_name,
92 : uint64_t *pac_attributes)
93 : {
94 50630 : krb5_context context = r->context;
95 50630 : krb5_kdc_configuration *config = r->config;
96 50630 : krb5_pac pac = NULL;
97 1658 : krb5_error_code ret;
98 1658 : krb5_boolean signedticket;
99 :
100 50630 : *kdc_issued = FALSE;
101 50630 : *ppac = NULL;
102 50630 : if (pac_canon_name)
103 49806 : *pac_canon_name = NULL;
104 50630 : if (pac_attributes)
105 49806 : *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
106 :
107 50630 : ret = _krb5_kdc_pac_ticket_parse(context, tkt, &signedticket, &pac);
108 50630 : if (ret)
109 0 : return ret;
110 :
111 50630 : if (pac == NULL) {
112 33 : if (config->require_pac)
113 33 : ret = KRB5KDC_ERR_TGT_REVOKED;
114 33 : return ret;
115 : }
116 :
117 : /* Verify the server signature. */
118 50597 : ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal,
119 : server_check_key, NULL);
120 50597 : if (ret) {
121 36 : krb5_pac_free(context, pac);
122 36 : return ret;
123 : }
124 :
125 : /* Verify the KDC signatures. */
126 50561 : ret = _kdc_pac_verify(r,
127 : client_principal, delegated_proxy,
128 : client, server, krbtgt, tkt, pac);
129 50561 : if (ret == 0) {
130 50433 : if (pac_canon_name) {
131 49637 : ret = _krb5_pac_get_canon_principal(context, pac, pac_canon_name);
132 49637 : if (ret && ret != ENOENT) {
133 0 : krb5_pac_free(context, pac);
134 0 : return ret;
135 : }
136 : }
137 100070 : if (pac_attributes &&
138 49637 : _krb5_pac_get_attributes_info(context, pac, pac_attributes) != 0)
139 170 : *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
140 128 : } else if (ret == KRB5_PLUGIN_NO_HANDLE) {
141 : /*
142 : * We can't verify the KDC signatures if the ticket was issued by
143 : * another realm's KDC.
144 : */
145 0 : if (krb5_realm_compare(context, server->principal,
146 0 : ticket_server->principal)) {
147 0 : ret = krb5_pac_verify(context, pac, 0, NULL, NULL,
148 : krbtgt_check_key);
149 0 : if (ret) {
150 0 : krb5_pac_free(context, pac);
151 0 : return ret;
152 : }
153 : }
154 :
155 0 : if (pac_canon_name) {
156 0 : ret = _krb5_pac_get_canon_principal(context, pac, pac_canon_name);
157 0 : if (ret && ret != ENOENT) {
158 0 : krb5_pac_free(context, pac);
159 0 : return ret;
160 : }
161 : }
162 0 : if (pac_attributes &&
163 0 : _krb5_pac_get_attributes_info(context, pac, pac_attributes) != 0)
164 0 : *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
165 :
166 : /* Discard the PAC if the plugin didn't handle it */
167 0 : krb5_pac_free(context, pac);
168 0 : ret = krb5_pac_init(context, &pac);
169 0 : if (ret)
170 0 : return ret;
171 : } else {
172 128 : krb5_pac_free(context, pac);
173 128 : return ret;
174 : }
175 :
176 100702 : *kdc_issued = signedticket ||
177 50269 : krb5_principal_is_krbtgt(context,
178 50269 : ticket_server->principal);
179 50433 : *ppac = pac;
180 :
181 50433 : return 0;
182 : }
183 :
184 : static krb5_boolean
185 98596 : is_anon_tgs_request_p(const KDC_REQ_BODY *b,
186 : const EncTicketPart *tgt)
187 : {
188 98596 : KDCOptions f = b->kdc_options;
189 :
190 : /*
191 : * Versions of Heimdal from 1.0 to 7.6, inclusive, send both the
192 : * request-anonymous and cname-in-addl-tkt flags for constrained
193 : * delegation requests. A true anonymous TGS request will only
194 : * have the request-anonymous flag set. (A corollary of this is
195 : * that it is not possible to support anonymous constrained
196 : * delegation requests, although they would be of limited utility.)
197 : */
198 197192 : return tgt->flags.anonymous ||
199 98596 : (f.request_anonymous && !f.cname_in_addl_tkt && !b->additional_tickets);
200 : }
201 :
202 : /*
203 : *
204 : */
205 :
206 : static krb5_error_code
207 49299 : check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
208 : krb5_const_principal tgt_name,
209 : const EncTicketPart *tgt, EncTicketPart *et)
210 : {
211 49299 : KDCOptions f = b->kdc_options;
212 :
213 49299 : if(f.validate){
214 12 : if (!tgt->flags.invalid || tgt->starttime == NULL) {
215 0 : kdc_audit_addreason((kdc_request_t)r,
216 : "Bad request to validate ticket");
217 0 : return KRB5KDC_ERR_BADOPTION;
218 : }
219 12 : if(*tgt->starttime > kdc_time){
220 0 : kdc_audit_addreason((kdc_request_t)r,
221 : "Early request to validate ticket");
222 0 : return KRB5KRB_AP_ERR_TKT_NYV;
223 : }
224 : /* XXX tkt = tgt */
225 12 : et->flags.invalid = 0;
226 49287 : } else if (tgt->flags.invalid) {
227 0 : kdc_audit_addreason((kdc_request_t)r,
228 : "Ticket-granting ticket has INVALID flag set");
229 0 : return KRB5KRB_AP_ERR_TKT_INVALID;
230 : }
231 :
232 49299 : if(f.forwardable){
233 36687 : if (!tgt->flags.forwardable) {
234 0 : kdc_audit_addreason((kdc_request_t)r,
235 : "Bad request for forwardable ticket");
236 0 : return KRB5KDC_ERR_BADOPTION;
237 : }
238 36687 : et->flags.forwardable = 1;
239 : }
240 49299 : if(f.forwarded){
241 23125 : if (!tgt->flags.forwardable) {
242 2 : kdc_audit_addreason((kdc_request_t)r,
243 : "Request to forward non-forwardable ticket");
244 2 : return KRB5KDC_ERR_BADOPTION;
245 : }
246 23123 : et->flags.forwarded = 1;
247 23123 : et->caddr = b->addresses;
248 : }
249 49297 : if(tgt->flags.forwarded)
250 299 : et->flags.forwarded = 1;
251 :
252 49297 : if(f.proxiable){
253 2 : if (!tgt->flags.proxiable) {
254 0 : kdc_audit_addreason((kdc_request_t)r,
255 : "Bad request for proxiable ticket");
256 0 : return KRB5KDC_ERR_BADOPTION;
257 : }
258 2 : et->flags.proxiable = 1;
259 : }
260 49297 : if(f.proxy){
261 0 : if (!tgt->flags.proxiable) {
262 0 : kdc_audit_addreason((kdc_request_t)r,
263 : "Request to proxy non-proxiable ticket");
264 0 : return KRB5KDC_ERR_BADOPTION;
265 : }
266 0 : et->flags.proxy = 1;
267 0 : et->caddr = b->addresses;
268 : }
269 49297 : if(tgt->flags.proxy)
270 0 : et->flags.proxy = 1;
271 :
272 49297 : if(f.allow_postdate){
273 0 : if (!tgt->flags.may_postdate) {
274 0 : kdc_audit_addreason((kdc_request_t)r,
275 : "Bad request for post-datable ticket");
276 0 : return KRB5KDC_ERR_BADOPTION;
277 : }
278 0 : et->flags.may_postdate = 1;
279 : }
280 49297 : if(f.postdated){
281 0 : if (!tgt->flags.may_postdate) {
282 0 : kdc_audit_addreason((kdc_request_t)r,
283 : "Bad request for postdated ticket");
284 0 : return KRB5KDC_ERR_BADOPTION;
285 : }
286 0 : if(b->from)
287 0 : *et->starttime = *b->from;
288 0 : et->flags.postdated = 1;
289 0 : et->flags.invalid = 1;
290 49297 : } else if (b->from && *b->from > kdc_time + r->context->max_skew) {
291 0 : kdc_audit_addreason((kdc_request_t)r,
292 : "Ticket cannot be postdated");
293 0 : return KRB5KDC_ERR_CANNOT_POSTDATE;
294 : }
295 :
296 49297 : if(f.renewable){
297 3180 : if (!tgt->flags.renewable || tgt->renew_till == NULL) {
298 0 : kdc_audit_addreason((kdc_request_t)r,
299 : "Bad request for renewable ticket");
300 0 : return KRB5KDC_ERR_BADOPTION;
301 : }
302 3180 : et->flags.renewable = 1;
303 3180 : ALLOC(et->renew_till);
304 3180 : _kdc_fix_time(&b->rtime);
305 3180 : *et->renew_till = *b->rtime;
306 : }
307 49297 : if(f.renew){
308 0 : time_t old_life;
309 48 : if (!tgt->flags.renewable || tgt->renew_till == NULL) {
310 0 : kdc_audit_addreason((kdc_request_t)r,
311 : "Request to renew non-renewable ticket");
312 0 : return KRB5KDC_ERR_BADOPTION;
313 : }
314 48 : old_life = tgt->endtime;
315 48 : if(tgt->starttime)
316 0 : old_life -= *tgt->starttime;
317 : else
318 48 : old_life -= tgt->authtime;
319 48 : et->endtime = *et->starttime + old_life;
320 48 : if (et->renew_till != NULL)
321 24 : et->endtime = min(*et->renew_till, et->endtime);
322 : }
323 :
324 : /*
325 : * RFC 8062 section 3 defines an anonymous ticket as one containing
326 : * the anonymous principal and the anonymous ticket flag.
327 : */
328 49297 : if (tgt->flags.anonymous &&
329 0 : !_kdc_is_anonymous(r->context, tgt_name)) {
330 0 : kdc_audit_addreason((kdc_request_t)r,
331 : "Anonymous ticket flag set without "
332 : "anonymous principal");
333 0 : return KRB5KDC_ERR_BADOPTION;
334 : }
335 :
336 : /*
337 : * RFC 8062 section 4.2 states that if the TGT is anonymous, the
338 : * anonymous KDC option SHOULD be set, but it is not required.
339 : * Treat an anonymous TGT as if the anonymous flag was set.
340 : */
341 50955 : if (is_anon_tgs_request_p(b, tgt))
342 0 : et->flags.anonymous = 1;
343 :
344 47639 : return 0;
345 : }
346 :
347 : /*
348 : * Determine if s4u2self is allowed from this client to this server
349 : *
350 : * also:
351 : *
352 : * Check that the client (user2user TGT, enc-tkt-in-skey) hosts the
353 : * service given by the client.
354 : *
355 : * For example, regardless of the principal being impersonated, if the
356 : * 'client' and 'server' (target) are the same, or server is an SPN
357 : * alias of client, then it's safe.
358 : */
359 :
360 : krb5_error_code
361 950 : _kdc_check_client_matches_target_service(krb5_context context,
362 : krb5_kdc_configuration *config,
363 : HDB *clientdb,
364 : hdb_entry *client,
365 : hdb_entry *target_server,
366 : krb5_const_principal target_server_principal)
367 : {
368 0 : krb5_error_code ret;
369 :
370 : /*
371 : * Always allow the plugin to check, this might be faster, allow a
372 : * policy or audit check and can look into the DB records
373 : * directly
374 : */
375 950 : if (clientdb->hdb_check_client_matches_target_service) {
376 950 : ret = clientdb->hdb_check_client_matches_target_service(context,
377 : clientdb,
378 : client,
379 : target_server);
380 950 : if (ret == 0)
381 944 : return 0;
382 0 : } else if (krb5_principal_compare(context,
383 0 : client->principal,
384 : target_server_principal) == TRUE) {
385 : /* if client does a s4u2self to itself, and there is no plugin, that is ok */
386 0 : return 0;
387 : } else {
388 0 : ret = KRB5KDC_ERR_BADOPTION;
389 : }
390 6 : return ret;
391 : }
392 :
393 : /*
394 : *
395 : */
396 :
397 : krb5_error_code
398 1054 : _kdc_verify_flags(krb5_context context,
399 : krb5_kdc_configuration *config,
400 : const EncTicketPart *et,
401 : const char *pstr)
402 : {
403 1054 : if(et->endtime < kdc_time){
404 0 : kdc_log(context, config, 4, "Ticket expired (%s)", pstr);
405 0 : return KRB5KRB_AP_ERR_TKT_EXPIRED;
406 : }
407 1054 : if(et->flags.invalid){
408 0 : kdc_log(context, config, 4, "Ticket not valid (%s)", pstr);
409 0 : return KRB5KRB_AP_ERR_TKT_NYV;
410 : }
411 1054 : return 0;
412 : }
413 :
414 : /*
415 : *
416 : */
417 :
418 : static krb5_error_code
419 49297 : fix_transited_encoding(krb5_context context,
420 : krb5_kdc_configuration *config,
421 : krb5_boolean check_policy,
422 : const TransitedEncoding *tr,
423 : EncTicketPart *et,
424 : const char *client_realm,
425 : const char *server_realm,
426 : const char *tgt_realm)
427 : {
428 49297 : krb5_error_code ret = 0;
429 1658 : char **realms, **tmp;
430 1658 : unsigned int num_realms;
431 1658 : size_t i;
432 :
433 49297 : switch (tr->tr_type) {
434 47639 : case domain_X500_Compress:
435 47639 : break;
436 0 : case 0:
437 : /*
438 : * Allow empty content of type 0 because that is was Microsoft
439 : * generates in their TGT.
440 : */
441 0 : if (tr->contents.length == 0)
442 0 : break;
443 0 : kdc_log(context, config, 4,
444 : "Transited type 0 with non empty content");
445 0 : return KRB5KDC_ERR_TRTYPE_NOSUPP;
446 0 : default:
447 0 : kdc_log(context, config, 4,
448 0 : "Unknown transited type: %u", tr->tr_type);
449 0 : return KRB5KDC_ERR_TRTYPE_NOSUPP;
450 : }
451 :
452 49297 : ret = krb5_domain_x500_decode(context,
453 : tr->contents,
454 : &realms,
455 : &num_realms,
456 : client_realm,
457 : server_realm);
458 49297 : if(ret){
459 0 : krb5_warn(context, ret,
460 : "Decoding transited encoding");
461 0 : return ret;
462 : }
463 :
464 : /*
465 : * If the realm of the presented tgt is neither the client nor the server
466 : * realm, it is a transit realm and must be added to transited set.
467 : */
468 49297 : if (strcmp(client_realm, tgt_realm) != 0 &&
469 8 : strcmp(server_realm, tgt_realm) != 0) {
470 0 : if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
471 0 : ret = ERANGE;
472 0 : goto free_realms;
473 : }
474 0 : tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
475 0 : if(tmp == NULL){
476 0 : ret = ENOMEM;
477 0 : goto free_realms;
478 : }
479 0 : realms = tmp;
480 0 : realms[num_realms] = strdup(tgt_realm);
481 0 : if(realms[num_realms] == NULL){
482 0 : ret = ENOMEM;
483 0 : goto free_realms;
484 : }
485 0 : num_realms++;
486 : }
487 49297 : if(num_realms == 0) {
488 49297 : if (strcmp(client_realm, server_realm) != 0)
489 59 : kdc_log(context, config, 4,
490 : "cross-realm %s -> %s", client_realm, server_realm);
491 : } else {
492 0 : size_t l = 0;
493 : char *rs;
494 0 : for(i = 0; i < num_realms; i++)
495 0 : l += strlen(realms[i]) + 2;
496 0 : rs = malloc(l);
497 0 : if(rs != NULL) {
498 0 : *rs = '\0';
499 0 : for(i = 0; i < num_realms; i++) {
500 0 : if(i > 0)
501 0 : strlcat(rs, ", ", l);
502 0 : strlcat(rs, realms[i], l);
503 : }
504 0 : kdc_log(context, config, 4,
505 : "cross-realm %s -> %s via [%s]",
506 : client_realm, server_realm, rs);
507 0 : free(rs);
508 : }
509 : }
510 49297 : if(check_policy) {
511 49297 : ret = krb5_check_transited(context, client_realm,
512 : server_realm,
513 : realms, num_realms, NULL);
514 49297 : if(ret) {
515 0 : krb5_warn(context, ret, "cross-realm %s -> %s",
516 : client_realm, server_realm);
517 0 : goto free_realms;
518 : }
519 49297 : et->flags.transited_policy_checked = 1;
520 : }
521 49297 : et->transited.tr_type = domain_X500_Compress;
522 49297 : ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
523 49297 : if(ret)
524 0 : krb5_warn(context, ret, "Encoding transited encoding");
525 49297 : free_realms:
526 49297 : for(i = 0; i < num_realms; i++)
527 0 : free(realms[i]);
528 49297 : free(realms);
529 49297 : return ret;
530 : }
531 :
532 :
533 : static krb5_error_code
534 49299 : tgs_make_reply(astgs_request_t r,
535 : const EncTicketPart *tgt,
536 : const EncryptionKey *serverkey,
537 : const EncryptionKey *krbtgtkey,
538 : const krb5_keyblock *sessionkey,
539 : krb5_kvno kvno,
540 : AuthorizationData *auth_data,
541 : const char *tgt_realm,
542 : uint16_t rodc_id,
543 : krb5_boolean add_ticket_sig)
544 : {
545 49299 : KDC_REQ_BODY *b = &r->req.req_body;
546 49299 : krb5_data *reply = r->reply;
547 49299 : KDC_REP *rep = &r->rep;
548 49299 : EncTicketPart *et = &r->et;
549 49299 : EncKDCRepPart *ek = &r->ek;
550 49299 : KDCOptions f = b->kdc_options;
551 1658 : krb5_error_code ret;
552 49299 : int is_weak = 0;
553 :
554 49299 : heim_assert(r->client_princ != NULL, "invalid client name passed to tgs_make_reply");
555 :
556 49299 : rep->pvno = 5;
557 49299 : rep->msg_type = krb_tgs_rep;
558 :
559 49299 : if (et->authtime == 0)
560 49159 : et->authtime = tgt->authtime;
561 49299 : _kdc_fix_time(&b->till);
562 49299 : et->endtime = min(tgt->endtime, *b->till);
563 49299 : ALLOC(et->starttime);
564 49299 : *et->starttime = kdc_time;
565 :
566 49299 : ret = check_tgs_flags(r, b, r->client_princ, tgt, et);
567 49299 : if(ret)
568 2 : goto out;
569 :
570 : /* We should check the transited encoding if:
571 : 1) the request doesn't ask not to be checked
572 : 2) globally enforcing a check
573 : 3) principal requires checking
574 : 4) we allow non-check per-principal, but principal isn't marked as allowing this
575 : 5) we don't globally allow this
576 : */
577 :
578 : #define GLOBAL_FORCE_TRANSITED_CHECK \
579 : (r->config->trpolicy == TRPOLICY_ALWAYS_CHECK)
580 : #define GLOBAL_ALLOW_PER_PRINCIPAL \
581 : (r->config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
582 : #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
583 : (r->config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
584 :
585 : /* these will consult the database in future release */
586 : #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
587 : #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
588 :
589 49297 : ret = fix_transited_encoding(r->context, r->config,
590 49297 : !f.disable_transited_check ||
591 0 : GLOBAL_FORCE_TRANSITED_CHECK ||
592 : PRINCIPAL_FORCE_TRANSITED_CHECK(r->server) ||
593 : !((GLOBAL_ALLOW_PER_PRINCIPAL &&
594 : PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(r->server)) ||
595 0 : GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
596 : &tgt->transited, et,
597 49297 : krb5_principal_get_realm(r->context, r->client_princ),
598 49297 : krb5_principal_get_realm(r->context, r->server->principal),
599 : tgt_realm);
600 :
601 : {
602 : /*
603 : * RFC 6806 notes that names MUST NOT be changed in the response to a
604 : * TGS request. Hence we ignore the setting of the canonicalize KDC
605 : * option. However, for legacy interoperability we do allow the backend
606 : * to override this by setting the force-canonicalize HDB flag in the
607 : * server entry.
608 : */
609 1658 : krb5_const_principal rsp;
610 :
611 49297 : if (r->server->flags.force_canonicalize)
612 47328 : rsp = r->server->principal;
613 : else
614 1969 : rsp = r->server_princ;
615 49297 : if (ret == 0)
616 49297 : ret = copy_Realm(&rsp->realm, &rep->ticket.realm);
617 49297 : if (ret == 0)
618 49297 : ret = _krb5_principal2principalname(&rep->ticket.sname, rsp);
619 : }
620 :
621 49297 : if (ret == 0)
622 49297 : ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
623 49297 : if (ret)
624 0 : goto out;
625 :
626 : /*
627 : * RFC 8062 states "if the ticket in the TGS request is an anonymous
628 : * one, the client and client realm are copied from that ticket". So
629 : * whilst the TGT flag check below is superfluous, it is included in
630 : * order to follow the specification to its letter.
631 : */
632 49297 : if (et->flags.anonymous && !tgt->flags.anonymous)
633 0 : _kdc_make_anonymous_principalname(&rep->cname);
634 : else
635 49297 : ret = copy_PrincipalName(&r->client_princ->name, &rep->cname);
636 49297 : if (ret)
637 0 : goto out;
638 49297 : rep->ticket.tkt_vno = 5;
639 :
640 49297 : ek->caddr = et->caddr;
641 :
642 : {
643 1658 : time_t life;
644 49297 : life = et->endtime - *et->starttime;
645 49297 : if(r->client && r->client->max_life)
646 49245 : life = min(life, *r->client->max_life);
647 49297 : if(r->server->max_life)
648 47328 : life = min(life, *r->server->max_life);
649 49297 : et->endtime = *et->starttime + life;
650 : }
651 49297 : if(f.renewable_ok && tgt->flags.renewable &&
652 0 : et->renew_till == NULL && et->endtime < *b->till &&
653 0 : tgt->renew_till != NULL)
654 : {
655 0 : et->flags.renewable = 1;
656 0 : ALLOC(et->renew_till);
657 0 : *et->renew_till = *b->till;
658 : }
659 49297 : if(et->renew_till){
660 0 : time_t renew;
661 3180 : renew = *et->renew_till - *et->starttime;
662 3180 : if(r->client && r->client->max_renew)
663 3145 : renew = min(renew, *r->client->max_renew);
664 3180 : if(r->server->max_renew)
665 3145 : renew = min(renew, *r->server->max_renew);
666 3180 : *et->renew_till = *et->starttime + renew;
667 : }
668 :
669 49297 : if(et->renew_till){
670 3180 : *et->renew_till = min(*et->renew_till, *tgt->renew_till);
671 3180 : *et->starttime = min(*et->starttime, *et->renew_till);
672 3180 : et->endtime = min(et->endtime, *et->renew_till);
673 : }
674 :
675 49297 : *et->starttime = min(*et->starttime, et->endtime);
676 :
677 49297 : if(*et->starttime == et->endtime){
678 0 : ret = KRB5KDC_ERR_NEVER_VALID;
679 0 : goto out;
680 : }
681 49297 : if(et->renew_till && et->endtime == *et->renew_till){
682 0 : free(et->renew_till);
683 0 : et->renew_till = NULL;
684 0 : et->flags.renewable = 0;
685 : }
686 :
687 49297 : et->flags.pre_authent = tgt->flags.pre_authent;
688 49297 : et->flags.hw_authent = tgt->flags.hw_authent;
689 49297 : et->flags.ok_as_delegate = r->server->flags.ok_as_delegate;
690 :
691 : /* See MS-KILE 3.3.5.1 */
692 49297 : if (!r->server->flags.forwardable)
693 1 : et->flags.forwardable = 0;
694 49297 : if (!r->server->flags.proxiable)
695 1970 : et->flags.proxiable = 0;
696 :
697 49297 : if (auth_data) {
698 5 : unsigned int i = 0;
699 :
700 : /* XXX check authdata */
701 :
702 5 : if (et->authorization_data == NULL) {
703 5 : et->authorization_data = calloc(1, sizeof(*et->authorization_data));
704 5 : if (et->authorization_data == NULL) {
705 0 : ret = ENOMEM;
706 0 : krb5_set_error_message(r->context, ret, "malloc: out of memory");
707 0 : goto out;
708 : }
709 : }
710 10 : for(i = 0; i < auth_data->len ; i++) {
711 5 : ret = add_AuthorizationData(et->authorization_data, &auth_data->val[i]);
712 5 : if (ret) {
713 0 : krb5_set_error_message(r->context, ret, "malloc: out of memory");
714 0 : goto out;
715 : }
716 : }
717 : }
718 :
719 49297 : ret = krb5_copy_keyblock_contents(r->context, sessionkey, &et->key);
720 49297 : if (ret)
721 0 : goto out;
722 49297 : et->crealm = rep->crealm;
723 49297 : et->cname = rep->cname;
724 :
725 49297 : ek->key = et->key;
726 : /* MIT must have at least one last_req */
727 49297 : ek->last_req.val = calloc(1, sizeof(*ek->last_req.val));
728 49297 : if (ek->last_req.val == NULL) {
729 0 : ret = ENOMEM;
730 0 : goto out;
731 : }
732 49297 : ek->last_req.len = 1; /* set after alloc to avoid null deref on cleanup */
733 49297 : ek->nonce = b->nonce;
734 49297 : ek->flags = et->flags;
735 49297 : ek->authtime = et->authtime;
736 49297 : ek->starttime = et->starttime;
737 49297 : ek->endtime = et->endtime;
738 49297 : ek->renew_till = et->renew_till;
739 49297 : ek->srealm = rep->ticket.realm;
740 49297 : ek->sname = rep->ticket.sname;
741 :
742 49297 : _kdc_log_timestamp(r, "TGS-REQ", et->authtime, et->starttime,
743 : et->endtime, et->renew_till);
744 :
745 49297 : if (krb5_enctype_valid(r->context, serverkey->keytype) != 0
746 0 : && _kdc_is_weak_exception(r->server->principal, serverkey->keytype))
747 : {
748 0 : krb5_enctype_enable(r->context, serverkey->keytype);
749 0 : is_weak = 1;
750 : }
751 :
752 49297 : if (r->canon_client_princ) {
753 1658 : char *cpn;
754 :
755 49297 : (void) krb5_unparse_name(r->context, r->canon_client_princ, &cpn);
756 49297 : kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
757 49297 : cpn ? cpn : "<unknown>");
758 49297 : krb5_xfree(cpn);
759 : }
760 :
761 : /*
762 : * For anonymous tickets, we should filter out positive authorization data
763 : * that could reveal the client's identity, and return a policy error for
764 : * restrictive authorization data. Policy for unknown authorization types
765 : * is implementation dependent.
766 : */
767 49297 : if (r->pac && !et->flags.anonymous) {
768 49286 : kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
769 49286 : r->pac_attributes);
770 :
771 : /*
772 : * PACs are included when issuing TGTs, if there is no PAC_ATTRIBUTES
773 : * buffer (legacy behavior) or if the attributes buffer indicates the
774 : * AS client requested one.
775 : */
776 49286 : if (_kdc_include_pac_p(r)) {
777 1658 : krb5_boolean is_tgs =
778 49286 : krb5_principal_is_krbtgt(r->context, r->server->principal);
779 :
780 49286 : ret = _krb5_kdc_pac_sign_ticket(r->context, r->pac, r->client_princ, serverkey,
781 49286 : krbtgtkey, rodc_id, NULL, r->canon_client_princ,
782 : add_ticket_sig, add_ticket_sig, et,
783 : is_tgs ? &r->pac_attributes : NULL);
784 49286 : if (ret)
785 0 : goto out;
786 : }
787 : }
788 :
789 49297 : ret = _kdc_finalize_reply(r);
790 49297 : if (ret)
791 0 : goto out;
792 :
793 : /* It is somewhat unclear where the etype in the following
794 : encryption should come from. What we have is a session
795 : key in the passed tgt, and a list of preferred etypes
796 : *for the new ticket*. Should we pick the best possible
797 : etype, given the keytype in the tgt, or should we look
798 : at the etype list here as well? What if the tgt
799 : session key is DES3 and we want a ticket with a (say)
800 : CAST session key. Should the DES3 etype be added to the
801 : etype list, even if we don't want a session key with
802 : DES3? */
803 50955 : ret = _kdc_encode_reply(r->context, r->config, r, b->nonce,
804 49297 : serverkey->keytype, kvno,
805 49297 : serverkey, 0, r->rk_is_subkey, reply);
806 49297 : if (is_weak)
807 0 : krb5_enctype_disable(r->context, serverkey->keytype);
808 :
809 49297 : _log_astgs_req(r, serverkey->keytype);
810 :
811 49299 : out:
812 49299 : return ret;
813 : }
814 :
815 : static krb5_error_code
816 51162 : tgs_check_authenticator(krb5_context context,
817 : krb5_kdc_configuration *config,
818 : krb5_auth_context ac,
819 : KDC_REQ_BODY *b,
820 : krb5_keyblock *key)
821 : {
822 1658 : krb5_authenticator auth;
823 1658 : krb5_error_code ret;
824 1658 : krb5_crypto crypto;
825 :
826 51162 : ret = krb5_auth_con_getauthenticator(context, ac, &auth);
827 51162 : if (ret) {
828 0 : kdc_log(context, config, 2,
829 : "Out of memory checking PA-TGS Authenticator");
830 0 : goto out;
831 : }
832 51162 : if(auth->cksum == NULL){
833 0 : kdc_log(context, config, 4, "No authenticator in request");
834 0 : ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
835 0 : goto out;
836 : }
837 :
838 51162 : if (!krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
839 0 : kdc_log(context, config, 4, "Bad checksum type in authenticator: %d",
840 0 : auth->cksum->cksumtype);
841 0 : ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
842 0 : goto out;
843 : }
844 :
845 51162 : ret = krb5_crypto_init(context, key, 0, &crypto);
846 51162 : if (ret) {
847 0 : const char *msg = krb5_get_error_message(context, ret);
848 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
849 0 : krb5_free_error_message(context, msg);
850 0 : goto out;
851 : }
852 :
853 : /*
854 : * RFC4120 says the checksum must be collision-proof, but it does
855 : * not require it to be keyed (as the authenticator is encrypted).
856 : */
857 51162 : _krb5_crypto_set_flags(context, crypto, KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM);
858 52820 : ret = _kdc_verify_checksum(context,
859 : crypto,
860 : KRB5_KU_TGS_REQ_AUTH_CKSUM,
861 51162 : &b->_save,
862 51162 : auth->cksum);
863 51162 : krb5_crypto_destroy(context, crypto);
864 51162 : if(ret){
865 0 : const char *msg = krb5_get_error_message(context, ret);
866 0 : kdc_log(context, config, 4,
867 : "Failed to verify authenticator checksum: %s", msg);
868 0 : krb5_free_error_message(context, msg);
869 : }
870 51162 : out:
871 51162 : free_Authenticator(auth);
872 51162 : free(auth);
873 51162 : return ret;
874 : }
875 :
876 : static krb5_boolean
877 0 : need_referral(krb5_context context, krb5_kdc_configuration *config,
878 : const KDCOptions * const options, krb5_principal server,
879 : krb5_realm **realms)
880 : {
881 0 : const char *name;
882 :
883 0 : if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
884 0 : return FALSE;
885 :
886 0 : if (server->name.name_string.len == 1)
887 0 : name = server->name.name_string.val[0];
888 0 : else if (server->name.name_string.len > 1)
889 0 : name = server->name.name_string.val[1];
890 : else
891 0 : return FALSE;
892 :
893 0 : kdc_log(context, config, 5, "Searching referral for %s", name);
894 :
895 0 : return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
896 : }
897 :
898 : static krb5_error_code
899 102325 : validate_fast_ad(astgs_request_t r, krb5_authdata *auth_data)
900 : {
901 3316 : krb5_error_code ret;
902 3316 : krb5_data data;
903 :
904 102325 : krb5_data_zero(&data);
905 :
906 102325 : if (!r->config->enable_fast)
907 7572 : return 0;
908 :
909 94753 : ret = _krb5_get_ad(r->context, auth_data, NULL,
910 : KRB5_AUTHDATA_FX_FAST_USED, &data);
911 94753 : if (ret == 0) {
912 43994 : r->fast_asserted = 1;
913 43994 : krb5_data_free(&data);
914 : }
915 :
916 94753 : ret = _krb5_get_ad(r->context, auth_data, NULL,
917 : KRB5_AUTHDATA_FX_FAST_ARMOR, &data);
918 94753 : if (ret == 0) {
919 2 : kdc_log(r->context, r->config, 2,
920 : "Invalid ticket usage: TGS-REQ contains AD-fx-fast-armor");
921 2 : krb5_data_free(&data);
922 2 : return KRB5KRB_AP_ERR_BAD_INTEGRITY;
923 : }
924 :
925 91435 : return 0;
926 : }
927 :
928 : static krb5_error_code
929 52529 : tgs_parse_request(astgs_request_t r,
930 : const PA_DATA *tgs_req,
931 : krb5_enctype *krbtgt_etype,
932 : const char *from,
933 : const struct sockaddr *from_addr,
934 : time_t **csec,
935 : int **cusec)
936 : {
937 52529 : krb5_kdc_configuration *config = r->config;
938 52529 : KDC_REQ_BODY *b = &r->req.req_body;
939 1658 : static char failed[] = "<unparse_name failed>";
940 1658 : krb5_ap_req ap_req;
941 1658 : krb5_error_code ret;
942 1658 : krb5_principal princ;
943 52529 : krb5_auth_context ac = NULL;
944 1658 : krb5_flags ap_req_options;
945 52529 : krb5_flags verify_ap_req_flags = 0;
946 1658 : krb5uint32 krbtgt_kvno; /* kvno used for the PA-TGS-REQ AP-REQ Ticket */
947 1658 : krb5uint32 krbtgt_kvno_try;
948 52529 : int kvno_search_tries = 4; /* number of kvnos to try when tkt_vno == 0 */
949 1658 : const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */
950 1658 : Key *tkey;
951 52529 : krb5_keyblock *subkey = NULL;
952 :
953 52529 : *csec = NULL;
954 52529 : *cusec = NULL;
955 :
956 52529 : memset(&ap_req, 0, sizeof(ap_req));
957 52529 : ret = krb5_decode_ap_req(r->context, &tgs_req->padata_value, &ap_req);
958 52529 : if(ret){
959 0 : const char *msg = krb5_get_error_message(r->context, ret);
960 0 : kdc_log(r->context, config, 4, "Failed to decode AP-REQ: %s", msg);
961 0 : krb5_free_error_message(r->context, msg);
962 0 : goto out;
963 : }
964 :
965 52529 : if(!krb5_principalname_is_krbtgt(r->context, &ap_req.ticket.sname)){
966 : /*
967 : * Note: this check is not to be depended upon for security. Nothing
968 : * prevents a client modifying the sname, as it is located in the
969 : * unencrypted part of the ticket.
970 : */
971 :
972 : /* XXX check for ticket.sname == req.sname */
973 8 : kdc_log(r->context, config, 4, "PA-DATA is not a ticket-granting ticket");
974 8 : ret = KRB5KDC_ERR_POLICY; /* ? */
975 8 : goto out;
976 : }
977 :
978 52521 : _krb5_principalname2krb5_principal(r->context,
979 : &princ,
980 : ap_req.ticket.sname,
981 : ap_req.ticket.realm);
982 :
983 52521 : krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0;
984 52521 : ret = _kdc_db_fetch(r->context, config, princ, HDB_F_GET_KRBTGT,
985 : &krbtgt_kvno, &r->krbtgtdb, &r->krbtgt);
986 :
987 52521 : if (ret == HDB_ERR_NOT_FOUND_HERE) {
988 : /* XXX Factor out this unparsing of the same princ all over */
989 0 : char *p;
990 1351 : ret = krb5_unparse_name(r->context, princ, &p);
991 1351 : if (ret != 0)
992 0 : p = failed;
993 1351 : krb5_free_principal(r->context, princ);
994 1351 : kdc_log(r->context, config, 5,
995 : "Ticket-granting ticket account %s does not have secrets at "
996 : "this KDC, need to proxy", p);
997 1351 : if (ret == 0)
998 1351 : free(p);
999 1351 : ret = HDB_ERR_NOT_FOUND_HERE;
1000 1351 : goto out;
1001 51170 : } else if (ret == HDB_ERR_KVNO_NOT_FOUND) {
1002 0 : char *p;
1003 0 : ret = krb5_unparse_name(r->context, princ, &p);
1004 0 : if (ret != 0)
1005 0 : p = failed;
1006 0 : krb5_free_principal(r->context, princ);
1007 0 : kdc_log(r->context, config, 5,
1008 : "Ticket-granting ticket account %s does not have keys for "
1009 : "kvno %d at this KDC", p, krbtgt_kvno);
1010 0 : if (ret == 0)
1011 0 : free(p);
1012 0 : ret = HDB_ERR_KVNO_NOT_FOUND;
1013 0 : goto out;
1014 51170 : } else if (ret == HDB_ERR_NO_MKEY) {
1015 0 : char *p;
1016 0 : ret = krb5_unparse_name(r->context, princ, &p);
1017 0 : if (ret != 0)
1018 0 : p = failed;
1019 0 : krb5_free_principal(r->context, princ);
1020 0 : kdc_log(r->context, config, 5,
1021 : "Missing master key for decrypting keys for ticket-granting "
1022 : "ticket account %s with kvno %d at this KDC", p, krbtgt_kvno);
1023 0 : if (ret == 0)
1024 0 : free(p);
1025 0 : ret = HDB_ERR_KVNO_NOT_FOUND;
1026 0 : goto out;
1027 51170 : } else if (ret) {
1028 0 : const char *msg = krb5_get_error_message(r->context, ret);
1029 0 : char *p;
1030 0 : ret = krb5_unparse_name(r->context, princ, &p);
1031 0 : if (ret != 0)
1032 0 : p = failed;
1033 0 : kdc_log(r->context, config, 4,
1034 : "Ticket-granting ticket %s not found in database: %s", p, msg);
1035 0 : krb5_free_principal(r->context, princ);
1036 0 : krb5_free_error_message(r->context, msg);
1037 0 : if (ret == 0)
1038 0 : free(p);
1039 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1040 0 : goto out;
1041 : }
1042 :
1043 51170 : krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : r->krbtgt->kvno;
1044 51170 : *krbtgt_etype = ap_req.ticket.enc_part.etype;
1045 :
1046 49512 : next_kvno:
1047 51170 : krbtgt_keys = hdb_kvno2keys(r->context, r->krbtgt, krbtgt_kvno_try);
1048 51170 : ret = hdb_enctype2key(r->context, r->krbtgt, krbtgt_keys,
1049 : ap_req.ticket.enc_part.etype, &tkey);
1050 51170 : if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) {
1051 0 : kvno_search_tries--;
1052 0 : krbtgt_kvno_try--;
1053 0 : goto next_kvno;
1054 51170 : } else if (ret) {
1055 4 : char *str = NULL, *p = NULL;
1056 :
1057 : /* We should implement the MIT `trace_format()' concept */
1058 4 : (void) krb5_enctype_to_string(r->context, ap_req.ticket.enc_part.etype, &str);
1059 4 : (void) krb5_unparse_name(r->context, princ, &p);
1060 8 : kdc_log(r->context, config, 4,
1061 : "No server key with enctype %s found for %s",
1062 4 : str ? str : "<unknown enctype>",
1063 4 : p ? p : "<unparse_name failed>");
1064 4 : free(str);
1065 4 : free(p);
1066 4 : ret = KRB5KRB_AP_ERR_BADKEYVER;
1067 4 : goto out;
1068 : }
1069 :
1070 51166 : if (b->kdc_options.validate)
1071 26 : verify_ap_req_flags |= KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1072 :
1073 51166 : if (r->config->warn_ticket_addresses)
1074 0 : verify_ap_req_flags |= KRB5_VERIFY_AP_REQ_IGNORE_ADDRS;
1075 :
1076 52824 : ret = krb5_verify_ap_req2(r->context,
1077 : &ac,
1078 : &ap_req,
1079 : princ,
1080 51166 : &tkey->key,
1081 : verify_ap_req_flags,
1082 : &ap_req_options,
1083 : &r->ticket,
1084 : KRB5_KU_TGS_REQ_AUTH);
1085 51166 : if (r->ticket && r->ticket->ticket.caddr)
1086 319 : kdc_audit_addaddrs((kdc_request_t)r, r->ticket->ticket.caddr, "tixaddrs");
1087 51166 : if (r->config->warn_ticket_addresses && ret == KRB5KRB_AP_ERR_BADADDR &&
1088 0 : r->ticket != NULL) {
1089 0 : kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
1090 0 : ret = 0;
1091 : }
1092 51166 : if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) {
1093 0 : kvno_search_tries--;
1094 0 : krbtgt_kvno_try--;
1095 0 : goto next_kvno;
1096 : }
1097 :
1098 51166 : krb5_free_principal(r->context, princ);
1099 51166 : if(ret) {
1100 3 : const char *msg = krb5_get_error_message(r->context, ret);
1101 3 : kdc_log(r->context, config, 4, "Failed to verify AP-REQ: %s", msg);
1102 3 : krb5_free_error_message(r->context, msg);
1103 3 : goto out;
1104 : }
1105 :
1106 51163 : r->ticket_key = tkey;
1107 :
1108 : {
1109 1658 : krb5_authenticator auth;
1110 :
1111 51163 : ret = krb5_auth_con_getauthenticator(r->context, ac, &auth);
1112 51163 : if (ret == 0) {
1113 51163 : *csec = malloc(sizeof(**csec));
1114 51163 : if (*csec == NULL) {
1115 0 : krb5_free_authenticator(r->context, &auth);
1116 0 : kdc_log(r->context, config, 4, "malloc failed");
1117 1 : goto out;
1118 : }
1119 51163 : **csec = auth->ctime;
1120 51163 : *cusec = malloc(sizeof(**cusec));
1121 51163 : if (*cusec == NULL) {
1122 0 : krb5_free_authenticator(r->context, &auth);
1123 0 : kdc_log(r->context, config, 4, "malloc failed");
1124 0 : goto out;
1125 : }
1126 51163 : **cusec = auth->cusec;
1127 :
1128 51163 : ret = validate_fast_ad(r, auth->authorization_data);
1129 51163 : krb5_free_authenticator(r->context, &auth);
1130 51163 : if (ret)
1131 1 : goto out;
1132 : }
1133 : }
1134 :
1135 51162 : ret = tgs_check_authenticator(r->context, config, ac, b, &r->ticket->ticket.key);
1136 51162 : if (ret) {
1137 0 : krb5_auth_con_free(r->context, ac);
1138 0 : goto out;
1139 : }
1140 :
1141 51162 : r->rk_is_subkey = 1;
1142 :
1143 51162 : ret = krb5_auth_con_getremotesubkey(r->context, ac, &subkey);
1144 51162 : if(ret){
1145 0 : const char *msg = krb5_get_error_message(r->context, ret);
1146 0 : krb5_auth_con_free(r->context, ac);
1147 0 : kdc_log(r->context, config, 4, "Failed to get remote subkey: %s", msg);
1148 0 : krb5_free_error_message(r->context, msg);
1149 0 : goto out;
1150 : }
1151 51162 : if(subkey == NULL){
1152 4 : r->rk_is_subkey = 0;
1153 :
1154 4 : ret = krb5_auth_con_getkey(r->context, ac, &subkey);
1155 4 : if(ret) {
1156 0 : const char *msg = krb5_get_error_message(r->context, ret);
1157 0 : krb5_auth_con_free(r->context, ac);
1158 0 : kdc_log(r->context, config, 4, "Failed to get session key: %s", msg);
1159 0 : krb5_free_error_message(r->context, msg);
1160 0 : goto out;
1161 : }
1162 : }
1163 51162 : if(subkey == NULL){
1164 0 : krb5_auth_con_free(r->context, ac);
1165 0 : kdc_log(r->context, config, 4,
1166 : "Failed to get key for enc-authorization-data");
1167 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1168 0 : goto out;
1169 : }
1170 :
1171 51162 : krb5_free_keyblock_contents(r->context, &r->reply_key);
1172 51162 : ret = krb5_copy_keyblock_contents(r->context, subkey, &r->reply_key);
1173 51162 : krb5_free_keyblock(r->context, subkey);
1174 51162 : if (ret)
1175 0 : goto out;
1176 :
1177 51162 : krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
1178 51162 : if (b->enc_authorization_data) {
1179 5 : ret = krb5_copy_keyblock_contents(r->context,
1180 5 : &r->reply_key,
1181 : &r->enc_ad_key);
1182 5 : if (ret)
1183 0 : goto out;
1184 : }
1185 :
1186 51162 : ret = validate_fast_ad(r, r->ticket->ticket.authorization_data);
1187 51162 : if (ret)
1188 1 : goto out;
1189 :
1190 :
1191 : /*
1192 : * Check for FAST request
1193 : */
1194 :
1195 51161 : ret = _kdc_fast_unwrap_request(r, r->ticket, ac);
1196 51161 : if (ret)
1197 5 : goto out;
1198 :
1199 51156 : krb5_auth_con_free(r->context, ac);
1200 :
1201 52529 : out:
1202 52529 : free_AP_REQ(&ap_req);
1203 :
1204 52529 : return ret;
1205 : }
1206 :
1207 : static krb5_error_code
1208 1152 : build_server_referral(krb5_context context,
1209 : krb5_kdc_configuration *config,
1210 : krb5_crypto session,
1211 : krb5_const_realm referred_realm,
1212 : const PrincipalName *true_principal_name,
1213 : const PrincipalName *requested_principal,
1214 : krb5_data *outdata)
1215 : {
1216 0 : PA_ServerReferralData ref;
1217 0 : krb5_error_code ret;
1218 0 : EncryptedData ed;
1219 0 : krb5_data data;
1220 1152 : size_t size = 0;
1221 :
1222 1152 : memset(&ref, 0, sizeof(ref));
1223 :
1224 1152 : if (referred_realm) {
1225 1152 : ALLOC(ref.referred_realm);
1226 1152 : if (ref.referred_realm == NULL)
1227 0 : goto eout;
1228 1152 : *ref.referred_realm = strdup(referred_realm);
1229 1152 : if (*ref.referred_realm == NULL)
1230 0 : goto eout;
1231 : }
1232 1152 : if (true_principal_name) {
1233 0 : ALLOC(ref.true_principal_name);
1234 0 : if (ref.true_principal_name == NULL)
1235 0 : goto eout;
1236 0 : ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1237 0 : if (ret)
1238 0 : goto eout;
1239 : }
1240 1152 : if (requested_principal) {
1241 1152 : ALLOC(ref.requested_principal_name);
1242 1152 : if (ref.requested_principal_name == NULL)
1243 0 : goto eout;
1244 1152 : ret = copy_PrincipalName(requested_principal,
1245 : ref.requested_principal_name);
1246 1152 : if (ret)
1247 0 : goto eout;
1248 : }
1249 :
1250 1152 : ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1251 : data.data, data.length,
1252 : &ref, &size, ret);
1253 1152 : free_PA_ServerReferralData(&ref);
1254 1152 : if (ret)
1255 0 : return ret;
1256 1152 : if (data.length != size)
1257 0 : krb5_abortx(context, "internal asn.1 encoder error");
1258 :
1259 1152 : ret = krb5_encrypt_EncryptedData(context, session,
1260 : KRB5_KU_PA_SERVER_REFERRAL,
1261 : data.data, data.length,
1262 : 0 /* kvno */, &ed);
1263 1152 : free(data.data);
1264 1152 : if (ret)
1265 0 : return ret;
1266 :
1267 1152 : ASN1_MALLOC_ENCODE(EncryptedData,
1268 : outdata->data, outdata->length,
1269 : &ed, &size, ret);
1270 1152 : free_EncryptedData(&ed);
1271 1152 : if (ret)
1272 0 : return ret;
1273 1152 : if (outdata->length != size)
1274 0 : krb5_abortx(context, "internal asn.1 encoder error");
1275 :
1276 1152 : return 0;
1277 0 : eout:
1278 0 : free_PA_ServerReferralData(&ref);
1279 0 : krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1280 0 : return ENOMEM;
1281 : }
1282 :
1283 : /*
1284 : * This function is intended to be used when failure to find the client is
1285 : * acceptable.
1286 : */
1287 : krb5_error_code
1288 50611 : _kdc_db_fetch_client(krb5_context context,
1289 : krb5_kdc_configuration *config,
1290 : int flags,
1291 : krb5_principal cp,
1292 : const char *cpn,
1293 : const char *krbtgt_realm,
1294 : HDB **clientdb,
1295 : hdb_entry **client_out)
1296 : {
1297 1658 : krb5_error_code ret;
1298 50611 : hdb_entry *client = NULL;
1299 :
1300 50611 : *clientdb = NULL;
1301 50611 : *client_out = NULL;
1302 :
1303 50611 : ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags,
1304 : NULL, clientdb, &client);
1305 50611 : if (ret == HDB_ERR_NOT_FOUND_HERE) {
1306 : /*
1307 : * This is OK, we are just trying to find out if they have
1308 : * been disabled or deleted in the meantime; missing secrets
1309 : * are OK.
1310 : */
1311 50611 : } else if (ret) {
1312 : /*
1313 : * If the client belongs to the same realm as our TGS, it
1314 : * should exist in the local database.
1315 : */
1316 0 : const char *msg;
1317 :
1318 53 : if (strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1319 1 : if (ret == HDB_ERR_NOENTRY)
1320 1 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1321 1 : kdc_log(context, config, 4, "Client no longer in database: %s", cpn);
1322 1 : return ret;
1323 : }
1324 :
1325 52 : msg = krb5_get_error_message(context, ret);
1326 52 : kdc_log(context, config, 4, "Client not found in database: %s", msg);
1327 52 : krb5_free_error_message(context, msg);
1328 50558 : } else if (client->flags.invalid || !client->flags.client) {
1329 0 : kdc_log(context, config, 4, "Client has invalid bit set");
1330 0 : _kdc_free_ent(context, *clientdb, client);
1331 0 : return KRB5KDC_ERR_POLICY;
1332 : }
1333 :
1334 50610 : *client_out = client;
1335 :
1336 50610 : return 0;
1337 : }
1338 :
1339 : static krb5_error_code
1340 51156 : tgs_build_reply(astgs_request_t priv,
1341 : krb5_enctype krbtgt_etype,
1342 : const struct sockaddr *from_addr)
1343 : {
1344 51156 : krb5_context context = priv->context;
1345 51156 : krb5_kdc_configuration *config = priv->config;
1346 51156 : KDC_REQ_BODY *b = &priv->req.req_body;
1347 51156 : const char *from = priv->from;
1348 1658 : krb5_error_code ret, ret2;
1349 51156 : krb5_principal krbtgt_out_principal = NULL;
1350 51156 : krb5_principal user2user_princ = NULL;
1351 51156 : char *spn = NULL, *cpn = NULL, *krbtgt_out_n = NULL;
1352 51156 : char *user2user_name = NULL;
1353 1658 : HDB *user2user_krbtgtdb;
1354 51156 : hdb_entry *user2user_krbtgt = NULL;
1355 51156 : HDB *clientdb = NULL;
1356 51156 : HDB *serverdb = NULL;
1357 51156 : krb5_realm ref_realm = NULL;
1358 51156 : EncTicketPart *tgt = &priv->ticket->ticket;
1359 1658 : const EncryptionKey *ekey;
1360 1658 : krb5_keyblock sessionkey;
1361 1658 : krb5_kvno kvno;
1362 51156 : krb5_pac user2user_pac = NULL;
1363 1658 : uint16_t rodc_id;
1364 51156 : krb5_boolean add_ticket_sig = FALSE;
1365 1658 : const char *tgt_realm = /* Realm of TGT issuer */
1366 51156 : krb5_principal_get_realm(context, priv->krbtgt->principal);
1367 1658 : const char *our_realm = /* Realm of this KDC */
1368 51156 : krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1);
1369 51156 : char **capath = NULL;
1370 51156 : size_t num_capath = 0;
1371 51156 : AuthorizationData *auth_data = NULL;
1372 :
1373 1658 : HDB *krbtgt_outdb;
1374 51156 : hdb_entry *krbtgt_out = NULL;
1375 :
1376 1658 : PrincipalName *s;
1377 1658 : Realm r;
1378 1658 : EncTicketPart adtkt;
1379 1658 : char opt_str[128];
1380 51156 : krb5_boolean kdc_issued = FALSE;
1381 :
1382 1658 : Key *tkey_sign;
1383 51156 : int flags = HDB_F_FOR_TGS_REQ;
1384 1658 : int server_flags;
1385 :
1386 1658 : int result;
1387 :
1388 51156 : const PA_DATA *for_user = NULL;
1389 51156 : int for_user_idx = 0;
1390 :
1391 51156 : memset(&sessionkey, 0, sizeof(sessionkey));
1392 51156 : memset(&adtkt, 0, sizeof(adtkt));
1393 :
1394 51156 : s = b->sname;
1395 51156 : r = b->realm;
1396 :
1397 : /*
1398 : * The canonicalize KDC option is passed as a hint to the backend, but
1399 : * can typically be ignored. Per RFC 6806, names are not canonicalized
1400 : * in response to a TGS request (although we make an exception, see
1401 : * force-canonicalize below).
1402 : */
1403 51156 : if (b->kdc_options.canonicalize)
1404 8985 : flags |= HDB_F_CANON;
1405 :
1406 51156 : server_flags = HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags;
1407 51156 : if (b->kdc_options.enc_tkt_in_skey)
1408 43 : server_flags |= HDB_F_USER2USER_PRINCIPAL;
1409 :
1410 51156 : if (s == NULL) {
1411 4 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1412 4 : _kdc_set_const_e_text(priv, "No server in request");
1413 4 : goto out;
1414 : }
1415 :
1416 51152 : _krb5_principalname2krb5_principal(context, &priv->server_princ, *s, r);
1417 51152 : ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
1418 51152 : if (ret)
1419 0 : goto out;
1420 51152 : spn = priv->sname;
1421 51152 : _krb5_principalname2krb5_principal(context, &priv->client_princ,
1422 : tgt->cname, tgt->crealm);
1423 51152 : ret = krb5_unparse_name(context, priv->client_princ, &priv->cname);
1424 51152 : if (ret)
1425 0 : goto out;
1426 51152 : cpn = priv->cname;
1427 51152 : result = unparse_flags(KDCOptions2int(b->kdc_options),
1428 : asn1_KDCOptions_units(),
1429 : opt_str, sizeof(opt_str));
1430 51152 : if (result > 0)
1431 46127 : kdc_log(context, config, 4,
1432 : "TGS-REQ %s from %s for %s [%s]",
1433 : cpn, from, spn, opt_str);
1434 : else
1435 5025 : kdc_log(context, config, 4,
1436 : "TGS-REQ %s from %s for %s", cpn, from, spn);
1437 :
1438 : /*
1439 : * Fetch server
1440 : */
1441 :
1442 49494 : server_lookup:
1443 52304 : if (priv->server)
1444 1152 : _kdc_free_ent(context, serverdb, priv->server);
1445 52304 : priv->server = NULL;
1446 52304 : ret = _kdc_db_fetch(context, config, priv->server_princ,
1447 : server_flags,
1448 : NULL, &serverdb, &priv->server);
1449 52304 : priv->serverdb = serverdb;
1450 52304 : if (ret == HDB_ERR_NOT_FOUND_HERE) {
1451 42 : kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", spn);
1452 42 : kdc_audit_addreason((kdc_request_t)priv, "Target not found here");
1453 42 : goto out;
1454 52262 : } else if (ret == HDB_ERR_WRONG_REALM) {
1455 1152 : free(ref_realm);
1456 1152 : ref_realm = strdup(priv->server->principal->realm);
1457 1152 : if (ref_realm == NULL) {
1458 0 : ret = krb5_enomem(context);
1459 0 : goto out;
1460 : }
1461 :
1462 1152 : kdc_log(context, config, 4,
1463 : "Returning a referral to realm %s for "
1464 : "server %s.",
1465 : ref_realm, spn);
1466 1152 : krb5_free_principal(context, priv->server_princ);
1467 1152 : priv->server_princ = NULL;
1468 1152 : ret = krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
1469 : ref_realm, NULL);
1470 1152 : if (ret)
1471 0 : goto out;
1472 1152 : free(priv->sname);
1473 1152 : priv->sname = NULL;
1474 1152 : ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
1475 1152 : if (ret)
1476 0 : goto out;
1477 1152 : spn = priv->sname;
1478 :
1479 1152 : goto server_lookup;
1480 51110 : } else if (ret) {
1481 0 : const char *new_rlm, *msg;
1482 0 : Realm req_rlm;
1483 0 : krb5_realm *realms;
1484 :
1485 1246 : priv->error_code = ret; /* advise policy plugin of failure reason */
1486 1246 : ret2 = _kdc_referral_policy(priv);
1487 1246 : if (ret2 == 0) {
1488 0 : krb5_xfree(priv->sname);
1489 0 : priv->sname = NULL;
1490 0 : ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
1491 0 : if (ret)
1492 1246 : goto out;
1493 0 : goto server_lookup;
1494 1246 : } else if (ret2 != KRB5_PLUGIN_NO_HANDLE) {
1495 1246 : ret = ret2;
1496 0 : } else if ((req_rlm = get_krbtgt_realm(&priv->server_princ->name)) != NULL) {
1497 0 : if (capath == NULL) {
1498 : /* With referalls, hierarchical capaths are always enabled */
1499 0 : ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
1500 : req_rlm, TRUE, &capath, &num_capath);
1501 0 : if (ret2) {
1502 0 : ret = ret2;
1503 0 : kdc_audit_addreason((kdc_request_t)priv,
1504 : "No trusted path from client realm to ours");
1505 0 : goto out;
1506 : }
1507 : }
1508 0 : new_rlm = num_capath > 0 ? capath[--num_capath] : NULL;
1509 0 : if (new_rlm) {
1510 0 : kdc_log(context, config, 5, "krbtgt from %s via %s for "
1511 : "realm %s not found, trying %s", tgt->crealm,
1512 : our_realm, req_rlm, new_rlm);
1513 :
1514 0 : free(ref_realm);
1515 0 : ref_realm = strdup(new_rlm);
1516 0 : if (ref_realm == NULL) {
1517 0 : ret = krb5_enomem(context);
1518 0 : goto out;
1519 : }
1520 :
1521 0 : krb5_free_principal(context, priv->server_princ);
1522 0 : priv->server_princ = NULL;
1523 0 : krb5_make_principal(context, &priv->server_princ, r,
1524 : KRB5_TGS_NAME, ref_realm, NULL);
1525 0 : free(priv->sname);
1526 0 : priv->sname = NULL;
1527 0 : ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
1528 0 : if (ret)
1529 0 : goto out;
1530 0 : spn = priv->sname;
1531 0 : goto server_lookup;
1532 : }
1533 0 : } else if (need_referral(context, config, &b->kdc_options, priv->server_princ, &realms)) {
1534 0 : if (strcmp(realms[0], priv->server_princ->realm) != 0) {
1535 0 : kdc_log(context, config, 4,
1536 : "Returning a referral to realm %s for "
1537 : "server %s that was not found",
1538 : realms[0], spn);
1539 0 : krb5_free_principal(context, priv->server_princ);
1540 0 : priv->server_princ = NULL;
1541 0 : krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
1542 : realms[0], NULL);
1543 0 : free(priv->sname);
1544 0 : priv->sname = NULL;
1545 0 : ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
1546 0 : if (ret) {
1547 0 : krb5_free_host_realm(context, realms);
1548 0 : goto out;
1549 : }
1550 0 : spn = priv->sname;
1551 :
1552 0 : free(ref_realm);
1553 0 : ref_realm = strdup(realms[0]);
1554 :
1555 0 : krb5_free_host_realm(context, realms);
1556 0 : goto server_lookup;
1557 : }
1558 0 : krb5_free_host_realm(context, realms);
1559 : }
1560 1246 : msg = krb5_get_error_message(context, ret);
1561 1246 : kdc_log(context, config, 3,
1562 : "Server not found in database: %s: %s", spn, msg);
1563 1246 : krb5_free_error_message(context, msg);
1564 1246 : if (ret == HDB_ERR_NOENTRY)
1565 1246 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1566 1246 : kdc_audit_addreason((kdc_request_t)priv,
1567 : "Service principal unknown");
1568 1246 : goto out;
1569 : }
1570 :
1571 : /*
1572 : * Now refetch the primary krbtgt, and get the current kvno (the
1573 : * sign check may have been on an old kvno, and the server may
1574 : * have been an incoming trust)
1575 : */
1576 :
1577 49864 : ret = krb5_make_principal(context,
1578 : &krbtgt_out_principal,
1579 : our_realm,
1580 : KRB5_TGS_NAME,
1581 : our_realm,
1582 : NULL);
1583 49864 : if (ret) {
1584 0 : kdc_log(context, config, 4,
1585 : "Failed to make krbtgt principal name object for "
1586 : "authz-data signatures");
1587 0 : goto out;
1588 : }
1589 49864 : ret = krb5_unparse_name(context, krbtgt_out_principal, &krbtgt_out_n);
1590 49864 : if (ret) {
1591 0 : kdc_log(context, config, 4,
1592 : "Failed to make krbtgt principal name object for "
1593 : "authz-data signatures");
1594 0 : goto out;
1595 : }
1596 :
1597 49864 : ret = _kdc_db_fetch(context, config, krbtgt_out_principal,
1598 : HDB_F_GET_KRBTGT, NULL, &krbtgt_outdb, &krbtgt_out);
1599 49864 : if (ret) {
1600 0 : char *ktpn = NULL;
1601 0 : ret = krb5_unparse_name(context, priv->krbtgt->principal, &ktpn);
1602 0 : kdc_log(context, config, 4,
1603 : "No such principal %s (needed for authz-data signature keys) "
1604 : "while processing TGS-REQ for service %s with krbtgt %s",
1605 : krbtgt_out_n, spn, (ret == 0) ? ktpn : "<unknown>");
1606 0 : free(ktpn);
1607 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1608 0 : goto out;
1609 : }
1610 :
1611 : /*
1612 : * Select enctype, return key and kvno.
1613 : */
1614 :
1615 : {
1616 1658 : krb5_enctype etype;
1617 :
1618 49864 : if(b->kdc_options.enc_tkt_in_skey) {
1619 0 : Ticket *t;
1620 0 : krb5_principal p;
1621 0 : Key *uukey;
1622 39 : krb5uint32 second_kvno = 0;
1623 39 : krb5uint32 *kvno_ptr = NULL;
1624 0 : size_t i;
1625 0 : HDB *user2user_db;
1626 39 : hdb_entry *user2user_client = NULL;
1627 39 : krb5_boolean user2user_kdc_issued = FALSE;
1628 0 : char *tpn;
1629 :
1630 39 : if(b->additional_tickets == NULL ||
1631 39 : b->additional_tickets->len == 0){
1632 0 : ret = KRB5KDC_ERR_BADOPTION; /* ? */
1633 0 : kdc_log(context, config, 4,
1634 : "No second ticket present in user-to-user request");
1635 0 : kdc_audit_addreason((kdc_request_t)priv,
1636 : "No second ticket present in user-to-user request");
1637 19 : goto out;
1638 : }
1639 39 : t = &b->additional_tickets->val[0];
1640 39 : if(!krb5_principalname_is_krbtgt(context, &t->sname)){
1641 : /*
1642 : * Note: this check is not to be depended upon for
1643 : * security. Nothing prevents a client modifying the sname, as
1644 : * it is located in the unencrypted part of the ticket.
1645 : */
1646 :
1647 1 : kdc_log(context, config, 4,
1648 : "Additional ticket is not a ticket-granting ticket");
1649 1 : kdc_audit_addreason((kdc_request_t)priv,
1650 : "Additional ticket is not a ticket-granting ticket");
1651 1 : ret = KRB5KDC_ERR_POLICY;
1652 1 : goto out;
1653 : }
1654 38 : ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1655 38 : if (ret)
1656 0 : goto out;
1657 :
1658 38 : ret = krb5_unparse_name(context, p, &tpn);
1659 38 : if (ret)
1660 0 : goto out;
1661 38 : if(t->enc_part.kvno){
1662 38 : second_kvno = *t->enc_part.kvno;
1663 38 : kvno_ptr = &second_kvno;
1664 : }
1665 38 : ret = _kdc_db_fetch(context, config, p,
1666 : HDB_F_GET_KRBTGT, kvno_ptr,
1667 : &user2user_krbtgtdb, &user2user_krbtgt);
1668 38 : krb5_free_principal(context, p);
1669 38 : if(ret){
1670 0 : if (ret == HDB_ERR_NOENTRY)
1671 0 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1672 0 : kdc_audit_addreason((kdc_request_t)priv,
1673 : "User-to-user service principal (TGS) unknown");
1674 0 : krb5_xfree(tpn);
1675 0 : goto out;
1676 : }
1677 38 : ret = hdb_enctype2key(context, user2user_krbtgt, NULL,
1678 : t->enc_part.etype, &uukey);
1679 38 : if(ret){
1680 1 : ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1681 1 : kdc_audit_addreason((kdc_request_t)priv,
1682 : "User-to-user enctype not supported");
1683 1 : krb5_xfree(tpn);
1684 1 : goto out;
1685 : }
1686 37 : ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1687 37 : if(ret) {
1688 1 : kdc_audit_addreason((kdc_request_t)priv,
1689 : "User-to-user TGT decrypt failure");
1690 1 : krb5_xfree(tpn);
1691 1 : goto out;
1692 : }
1693 :
1694 36 : ret = _kdc_verify_flags(context, config, &adtkt, tpn);
1695 36 : if (ret) {
1696 0 : kdc_audit_addreason((kdc_request_t)priv,
1697 : "User-to-user TGT expired or invalid");
1698 0 : krb5_xfree(tpn);
1699 0 : goto out;
1700 : }
1701 36 : krb5_xfree(tpn);
1702 :
1703 : /* Fetch the name from the TGT. */
1704 36 : ret = _krb5_principalname2krb5_principal(context, &user2user_princ,
1705 : adtkt.cname, adtkt.crealm);
1706 36 : if (ret)
1707 0 : goto out;
1708 :
1709 36 : ret = krb5_unparse_name(context, user2user_princ, &user2user_name);
1710 36 : if (ret)
1711 0 : goto out;
1712 :
1713 : /*
1714 : * Look up the name given in the TGT in the database. The user
1715 : * claims to have a ticket-granting-ticket to our KDC, so we should
1716 : * fail hard if we can't find the user - otherwise we can't do
1717 : * proper checks.
1718 : */
1719 36 : ret = _kdc_db_fetch(context, config, user2user_princ,
1720 36 : HDB_F_GET_CLIENT | flags,
1721 : NULL, &user2user_db, &user2user_client);
1722 36 : if (ret == HDB_ERR_NOENTRY)
1723 2 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1724 36 : if (ret)
1725 2 : goto out;
1726 :
1727 : /*
1728 : * The account is present in the database, now check the
1729 : * account flags.
1730 : *
1731 : * We check this as a client (because the purpose of
1732 : * user2user is that the server flag is not set, because
1733 : * the long-term key is not strong, but this does mean
1734 : * that a client with an expired password can't get accept
1735 : * a user2user ticket.
1736 : */
1737 34 : ret = kdc_check_flags(priv,
1738 : FALSE,
1739 : user2user_client,
1740 : NULL);
1741 34 : if (ret) {
1742 0 : _kdc_free_ent(context, user2user_db, user2user_client);
1743 0 : goto out;
1744 : }
1745 :
1746 : /*
1747 : * Also check that the account is the same one specified in the
1748 : * request.
1749 : */
1750 34 : ret = _kdc_check_client_matches_target_service(context,
1751 : config,
1752 : serverdb,
1753 : priv->server,
1754 : user2user_client,
1755 : user2user_princ);
1756 34 : if (ret) {
1757 2 : _kdc_free_ent(context, user2user_db, user2user_client);
1758 2 : goto out;
1759 : }
1760 :
1761 : /* Verify the PAC of the TGT. */
1762 32 : ret = _kdc_check_pac(priv, user2user_princ, NULL,
1763 : user2user_client, user2user_krbtgt, user2user_krbtgt, user2user_krbtgt,
1764 32 : &uukey->key, &priv->ticket_key->key, &adtkt,
1765 : &user2user_kdc_issued, &user2user_pac, NULL, NULL);
1766 32 : _kdc_free_ent(context, user2user_db, user2user_client);
1767 32 : if (ret) {
1768 12 : const char *msg = krb5_get_error_message(context, ret);
1769 12 : kdc_log(context, config, 0,
1770 : "Verify PAC failed for %s (%s) from %s with %s",
1771 : spn, user2user_name, from, msg);
1772 12 : krb5_free_error_message(context, msg);
1773 12 : goto out;
1774 : }
1775 :
1776 20 : if ((config->require_pac && !user2user_pac)
1777 20 : || (user2user_pac && !user2user_kdc_issued))
1778 : {
1779 0 : ret = KRB5KDC_ERR_BADOPTION;
1780 0 : kdc_log(context, config, 0,
1781 : "Ticket not signed with PAC; user-to-user failed (%s).",
1782 0 : user2user_pac ? "Ticket unsigned" : "No PAC");
1783 0 : goto out;
1784 : }
1785 :
1786 20 : ekey = &adtkt.key;
1787 20 : for(i = 0; i < b->etype.len; i++)
1788 20 : if (b->etype.val[i] == adtkt.key.keytype)
1789 20 : break;
1790 20 : if(i == b->etype.len) {
1791 0 : kdc_log(context, config, 4,
1792 : "Addition ticket has no matching etypes");
1793 0 : krb5_clear_error_message(context);
1794 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1795 0 : kdc_audit_addreason((kdc_request_t)priv,
1796 : "No matching enctypes for 2nd ticket");
1797 0 : goto out;
1798 : }
1799 20 : etype = b->etype.val[i];
1800 20 : kvno = 0;
1801 : } else {
1802 1658 : Key *skey;
1803 :
1804 51483 : ret = _kdc_find_session_etype(priv, b->etype.val, b->etype.len,
1805 49825 : priv->server, &etype);
1806 49825 : if(ret) {
1807 113 : kdc_log(context, config, 4,
1808 : "Server (%s) has no support for etypes", spn);
1809 113 : kdc_audit_addreason((kdc_request_t)priv,
1810 : "Enctype not supported");
1811 251 : goto out;
1812 : }
1813 49712 : ret = _kdc_get_preferred_key(context, config, priv->server, spn,
1814 : NULL, &skey);
1815 49712 : if(ret) {
1816 138 : kdc_log(context, config, 4,
1817 : "Server (%s) has no supported etypes", spn);
1818 138 : kdc_audit_addreason((kdc_request_t)priv,
1819 : "Enctype not supported");
1820 138 : goto out;
1821 : }
1822 49574 : ekey = &skey->key;
1823 49574 : kvno = priv->server->kvno;
1824 : }
1825 :
1826 49594 : ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1827 49594 : if (ret)
1828 0 : goto out;
1829 : }
1830 :
1831 : /*
1832 : * Check that service is in the same realm as the krbtgt. If it's
1833 : * not the same, it's someone that is using a uni-directional trust
1834 : * backward.
1835 : */
1836 :
1837 : /*
1838 : * The first realm is the realm of the service, the second is
1839 : * krbtgt/<this>/@REALM component of the krbtgt DN the request was
1840 : * encrypted to. The redirection via the krbtgt_out entry allows
1841 : * the DB to possibly correct the case of the realm (Samba4 does
1842 : * this) before the strcmp()
1843 : */
1844 49594 : if (strcmp(krb5_principal_get_realm(context, priv->server->principal),
1845 49594 : krb5_principal_get_realm(context, krbtgt_out->principal)) != 0) {
1846 0 : char *ktpn;
1847 0 : ret = krb5_unparse_name(context, krbtgt_out->principal, &ktpn);
1848 0 : kdc_log(context, config, 4,
1849 : "Request with wrong krbtgt: %s",
1850 : (ret == 0) ? ktpn : "<unknown>");
1851 0 : if(ret == 0)
1852 0 : free(ktpn);
1853 0 : ret = KRB5KRB_AP_ERR_NOT_US;
1854 0 : kdc_audit_addreason((kdc_request_t)priv, "Request with wrong TGT");
1855 0 : goto out;
1856 : }
1857 :
1858 49594 : ret = _kdc_get_preferred_key(context, config, krbtgt_out, krbtgt_out_n,
1859 : NULL, &tkey_sign);
1860 49594 : if (ret) {
1861 0 : kdc_log(context, config, 4,
1862 : "Failed to find key for krbtgt PAC signature");
1863 0 : kdc_audit_addreason((kdc_request_t)priv,
1864 : "Failed to find key for krbtgt PAC signature");
1865 0 : goto out;
1866 : }
1867 51252 : ret = hdb_enctype2key(context, krbtgt_out, NULL,
1868 49594 : tkey_sign->key.keytype, &tkey_sign);
1869 49594 : if(ret) {
1870 0 : kdc_log(context, config, 4,
1871 : "Failed to find key for krbtgt PAC signature");
1872 0 : kdc_audit_addreason((kdc_request_t)priv,
1873 : "Failed to find key for krbtgt PAC signature");
1874 0 : goto out;
1875 : }
1876 :
1877 49594 : if (_kdc_synthetic_princ_used_p(context, priv->ticket))
1878 16 : flags |= HDB_F_SYNTHETIC_OK;
1879 :
1880 49594 : ret = _kdc_db_fetch_client(context, config, flags, priv->client_princ,
1881 : cpn, our_realm, &clientdb, &priv->client);
1882 49594 : if (ret)
1883 1 : goto out;
1884 : /* flags &= ~HDB_F_SYNTHETIC_OK; */ /* `flags' is not used again below */
1885 49593 : priv->clientdb = clientdb;
1886 :
1887 : /* Validate armor TGT before potentially including device claims */
1888 49593 : if (priv->armor_ticket) {
1889 324 : ret = _kdc_fast_check_armor_pac(priv, HDB_F_FOR_TGS_REQ);
1890 324 : if (ret)
1891 12 : goto out;
1892 : }
1893 :
1894 51239 : ret = _kdc_check_pac(priv, priv->client_princ, NULL,
1895 : priv->client, priv->server,
1896 : priv->krbtgt, priv->krbtgt,
1897 49581 : &priv->ticket_key->key, &priv->ticket_key->key, tgt,
1898 : &kdc_issued, &priv->pac, &priv->canon_client_princ,
1899 : &priv->pac_attributes);
1900 49581 : if (ret) {
1901 99 : const char *msg = krb5_get_error_message(context, ret);
1902 99 : kdc_audit_addreason((kdc_request_t)priv, "PAC check failed");
1903 99 : kdc_log(context, config, 4,
1904 : "Verify PAC failed for %s (%s) from %s with %s",
1905 : spn, cpn, from, msg);
1906 99 : krb5_free_error_message(context, msg);
1907 99 : goto out;
1908 : }
1909 :
1910 : /*
1911 : * Process request
1912 : */
1913 :
1914 : /*
1915 : * Services for User: protocol transition and constrained delegation
1916 : */
1917 :
1918 97255 : if (priv->client != NULL &&
1919 49431 : (for_user = _kdc_find_padata(&priv->req,
1920 : &for_user_idx,
1921 : KRB5_PADATA_FOR_USER)) != NULL)
1922 : {
1923 : /* Process an S4U2Self request. */
1924 658 : ret = _kdc_validate_protocol_transition(priv, for_user);
1925 658 : if (ret)
1926 8 : goto out;
1927 48824 : } else if (priv->client != NULL
1928 48773 : && b->additional_tickets != NULL
1929 284 : && b->additional_tickets->len != 0
1930 284 : && b->kdc_options.cname_in_addl_tkt
1931 264 : && b->kdc_options.enc_tkt_in_skey == 0)
1932 : {
1933 : /* Process an S4U2Proxy request. */
1934 264 : ret = _kdc_validate_constrained_delegation(priv);
1935 264 : if (ret)
1936 124 : goto out;
1937 48560 : } else if (priv->pac != NULL) {
1938 48560 : ret = _kdc_pac_update(priv, priv->client_princ, NULL, NULL,
1939 : priv->client, priv->server, priv->krbtgt,
1940 : &priv->pac);
1941 48560 : if (ret == KRB5_PLUGIN_NO_HANDLE) {
1942 0 : ret = 0;
1943 : }
1944 48560 : if (ret) {
1945 51 : const char *msg = krb5_get_error_message(context, ret);
1946 51 : kdc_audit_addreason((kdc_request_t)priv, "PAC update failed");
1947 51 : kdc_log(context, config, 4,
1948 : "Update PAC failed for %s (%s) from %s with %s",
1949 : spn, cpn, from, msg);
1950 51 : krb5_free_error_message(context, msg);
1951 51 : goto out;
1952 : }
1953 :
1954 48509 : if (priv->pac == NULL) {
1955 : /* the plugin may indicate no PAC should be generated */
1956 8 : priv->pac_attributes = 0;
1957 : }
1958 : }
1959 :
1960 49299 : if (b->enc_authorization_data) {
1961 0 : unsigned auth_data_usage;
1962 0 : krb5_crypto crypto;
1963 0 : krb5_data ad;
1964 :
1965 5 : if (priv->rk_is_subkey != 0) {
1966 3 : auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1967 : } else {
1968 2 : auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1969 : }
1970 :
1971 5 : ret = krb5_crypto_init(context, &priv->enc_ad_key, 0, &crypto);
1972 5 : if (ret) {
1973 0 : const char *msg = krb5_get_error_message(context, ret);
1974 0 : kdc_audit_addreason((kdc_request_t)priv,
1975 : "krb5_crypto_init() failed for "
1976 : "enc_authorization_data");
1977 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1978 0 : krb5_free_error_message(context, msg);
1979 0 : goto out;
1980 : }
1981 5 : ret = krb5_decrypt_EncryptedData(context,
1982 : crypto,
1983 : auth_data_usage,
1984 5 : b->enc_authorization_data,
1985 : &ad);
1986 5 : krb5_crypto_destroy(context, crypto);
1987 5 : if(ret){
1988 0 : kdc_audit_addreason((kdc_request_t)priv,
1989 : "Failed to decrypt enc-authorization-data");
1990 0 : kdc_log(context, config, 4,
1991 : "Failed to decrypt enc-authorization-data");
1992 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1993 0 : goto out;
1994 : }
1995 5 : ALLOC(auth_data);
1996 5 : if (auth_data == NULL) {
1997 0 : krb5_data_free(&ad);
1998 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1999 0 : goto out;
2000 : }
2001 5 : ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2002 5 : krb5_data_free(&ad);
2003 5 : if(ret){
2004 0 : free(auth_data);
2005 0 : auth_data = NULL;
2006 0 : kdc_audit_addreason((kdc_request_t)priv,
2007 : "Failed to decode authorization data");
2008 0 : kdc_log(context, config, 4, "Failed to decode authorization data");
2009 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2010 0 : goto out;
2011 : }
2012 : }
2013 :
2014 : /*
2015 : * Check flags
2016 : */
2017 :
2018 49299 : ret = kdc_check_flags(priv, FALSE, priv->client, priv->server);
2019 49299 : if(ret)
2020 0 : goto out;
2021 :
2022 49359 : if((b->kdc_options.validate || b->kdc_options.renew) &&
2023 60 : !krb5_principal_compare(context,
2024 60 : priv->krbtgt->principal,
2025 60 : priv->server->principal)){
2026 0 : kdc_audit_addreason((kdc_request_t)priv, "Inconsistent request");
2027 0 : kdc_log(context, config, 4, "Inconsistent request.");
2028 0 : ret = KRB5KDC_ERR_SERVER_NOMATCH;
2029 0 : goto out;
2030 : }
2031 :
2032 : /* check for valid set of addresses */
2033 49299 : if (!_kdc_check_addresses(priv, tgt->caddr, from_addr)) {
2034 0 : if (config->check_ticket_addresses) {
2035 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2036 0 : kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE);
2037 0 : kdc_log(context, config, 4, "Request from wrong address");
2038 0 : kdc_audit_addreason((kdc_request_t)priv, "Request from wrong address");
2039 0 : goto out;
2040 0 : } else if (config->warn_ticket_addresses) {
2041 0 : kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE);
2042 : }
2043 : }
2044 :
2045 : /* check local and per-principal anonymous ticket issuance policy */
2046 50957 : if (is_anon_tgs_request_p(b, tgt)) {
2047 0 : ret = _kdc_check_anon_policy(priv);
2048 0 : if (ret)
2049 0 : goto out;
2050 : }
2051 :
2052 : /*
2053 : * If this is an referral, add server referral data to the
2054 : * auth_data reply .
2055 : */
2056 49299 : if (ref_realm) {
2057 0 : PA_DATA pa;
2058 0 : krb5_crypto crypto;
2059 :
2060 1152 : kdc_log(context, config, 3,
2061 : "Adding server referral to %s", ref_realm);
2062 :
2063 1152 : ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
2064 1152 : if (ret)
2065 0 : goto out;
2066 :
2067 1152 : ret = build_server_referral(context, config, crypto, ref_realm,
2068 : NULL, s, &pa.padata_value);
2069 1152 : krb5_crypto_destroy(context, crypto);
2070 1152 : if (ret) {
2071 0 : kdc_audit_addreason((kdc_request_t)priv, "Referral build failed");
2072 0 : kdc_log(context, config, 4,
2073 : "Failed building server referral");
2074 0 : goto out;
2075 : }
2076 1152 : pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
2077 :
2078 1152 : ret = add_METHOD_DATA(priv->rep.padata, &pa);
2079 1152 : krb5_data_free(&pa.padata_value);
2080 1152 : if (ret) {
2081 0 : kdc_log(context, config, 4,
2082 : "Add server referral METHOD-DATA failed");
2083 0 : goto out;
2084 : }
2085 : }
2086 :
2087 : /*
2088 : * Only add ticket signature if the requested server is not krbtgt, and
2089 : * either the header server is krbtgt or, in the case of renewal/validation
2090 : * if it was signed with PAC ticket signature and we verified it.
2091 : * Currently Heimdal only allows renewal of krbtgt anyway but that might
2092 : * change one day (see issue #763) so make sure to check for it.
2093 : */
2094 :
2095 98598 : if (kdc_issued &&
2096 49299 : !krb5_principal_is_krbtgt(context, priv->server->principal)) {
2097 :
2098 21230 : add_ticket_sig = TRUE;
2099 : }
2100 :
2101 : /*
2102 : * Active-Directory implementations use the high part of the kvno as the
2103 : * read-only-dc identifier, we need to embed it in the PAC KDC signatures.
2104 : */
2105 :
2106 49299 : rodc_id = krbtgt_out->kvno >> 16;
2107 :
2108 : /*
2109 : *
2110 : */
2111 :
2112 49299 : ret = tgs_make_reply(priv,
2113 : tgt,
2114 : ekey,
2115 49299 : &tkey_sign->key,
2116 : &sessionkey,
2117 : kvno,
2118 : auth_data,
2119 : tgt_realm,
2120 : rodc_id,
2121 : add_ticket_sig);
2122 :
2123 51156 : out:
2124 51156 : free(user2user_name);
2125 51156 : free(krbtgt_out_n);
2126 51156 : _krb5_free_capath(context, capath);
2127 :
2128 51156 : krb5_free_keyblock_contents(context, &sessionkey);
2129 51156 : if(krbtgt_out)
2130 49864 : _kdc_free_ent(context, krbtgt_outdb, krbtgt_out);
2131 51156 : if(user2user_krbtgt)
2132 38 : _kdc_free_ent(context, user2user_krbtgtdb, user2user_krbtgt);
2133 :
2134 51156 : krb5_free_principal(context, user2user_princ);
2135 51156 : krb5_free_principal(context, krbtgt_out_principal);
2136 51156 : free(ref_realm);
2137 :
2138 51156 : if (auth_data) {
2139 5 : free_AuthorizationData(auth_data);
2140 5 : free(auth_data);
2141 : }
2142 :
2143 51156 : free_EncTicketPart(&adtkt);
2144 :
2145 51156 : krb5_pac_free(context, user2user_pac);
2146 :
2147 51156 : return ret;
2148 : }
2149 :
2150 : /*
2151 : *
2152 : */
2153 :
2154 : krb5_error_code
2155 52529 : _kdc_tgs_rep(astgs_request_t r)
2156 : {
2157 52529 : krb5_kdc_configuration *config = r->config;
2158 52529 : KDC_REQ *req = &r->req;
2159 52529 : krb5_data *data = r->reply;
2160 52529 : const char *from = r->from;
2161 52529 : struct sockaddr *from_addr = r->addr;
2162 52529 : int datagram_reply = r->datagram_reply;
2163 1658 : krb5_error_code ret;
2164 52529 : int i = 0;
2165 1658 : const PA_DATA *tgs_req, *pa;
2166 52529 : krb5_enctype krbtgt_etype = ETYPE_NULL;
2167 :
2168 52529 : time_t *csec = NULL;
2169 52529 : int *cusec = NULL;
2170 :
2171 52529 : r->e_text = NULL;
2172 :
2173 52529 : if(req->padata == NULL){
2174 0 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2175 0 : kdc_log(r->context, config, 4,
2176 : "TGS-REQ from %s without PA-DATA", from);
2177 0 : goto out;
2178 : }
2179 :
2180 52529 : i = 0;
2181 52529 : pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST_ARMOR);
2182 52529 : if (pa) {
2183 0 : kdc_log(r->context, r->config, 10, "Found TGS-REQ FAST armor inside TGS-REQ pa-data");
2184 0 : ret = KRB5KRB_ERR_GENERIC;
2185 0 : goto out;
2186 : }
2187 :
2188 52529 : i = 0;
2189 52529 : tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2190 52529 : if(tgs_req == NULL){
2191 0 : ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2192 :
2193 0 : kdc_log(r->context, config, 4,
2194 : "TGS-REQ from %s without PA-TGS-REQ", from);
2195 0 : goto out;
2196 : }
2197 52529 : ret = tgs_parse_request(r, tgs_req,
2198 : &krbtgt_etype,
2199 : from, from_addr,
2200 : &csec, &cusec);
2201 52529 : if (ret == HDB_ERR_NOT_FOUND_HERE) {
2202 : /* kdc_log() is called in tgs_parse_request() */
2203 1351 : goto out;
2204 : }
2205 51178 : if (ret) {
2206 22 : kdc_log(r->context, config, 4,
2207 : "Failed parsing TGS-REQ from %s", from);
2208 22 : goto out;
2209 : }
2210 :
2211 51156 : ret = _kdc_fast_strengthen_reply_key(r);
2212 51156 : if (ret)
2213 0 : goto out;
2214 :
2215 51156 : ALLOC(r->rep.padata);
2216 51156 : if (r->rep.padata == NULL) {
2217 0 : ret = ENOMEM;
2218 0 : krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2219 0 : goto out;
2220 : }
2221 :
2222 51156 : ret = tgs_build_reply(r,
2223 : krbtgt_etype,
2224 : from_addr);
2225 51156 : if (ret) {
2226 1859 : kdc_log(r->context, config, 4,
2227 : "Failed building TGS-REP to %s", from);
2228 1859 : goto out;
2229 : }
2230 :
2231 : /* */
2232 49297 : if (datagram_reply && data->length > config->max_datagram_reply_length) {
2233 0 : krb5_data_free(data);
2234 0 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2235 0 : _kdc_set_const_e_text(r, "Reply packet too large");
2236 : }
2237 :
2238 49297 : out:
2239 52529 : if (ret) {
2240 : /* Overwrite ‘error_code’ only if we have an actual error. */
2241 3232 : r->error_code = ret;
2242 : }
2243 : {
2244 52529 : krb5_error_code ret2 = _kdc_audit_request(r);
2245 52529 : if (ret2) {
2246 0 : krb5_data_free(data);
2247 0 : ret = ret2;
2248 : }
2249 : }
2250 :
2251 52529 : if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
2252 1839 : METHOD_DATA error_method = { 0, NULL };
2253 :
2254 1839 : kdc_log(r->context, config, 5, "tgs-req: sending error: %d to client", ret);
2255 5517 : ret = _kdc_fast_mk_error(r,
2256 : &error_method,
2257 : r->armor_crypto,
2258 1839 : &req->req_body,
2259 1839 : r->error_code ? r->error_code : ret,
2260 1839 : r->client_princ ? r->client_princ :(r->ticket != NULL ? r->ticket->client : NULL),
2261 1839 : r->server_princ ? r->server_princ :(r->ticket != NULL ? r->ticket->server : NULL),
2262 : csec, cusec,
2263 : data);
2264 1839 : free_METHOD_DATA(&error_method);
2265 : }
2266 52529 : free(csec);
2267 52529 : free(cusec);
2268 :
2269 52529 : free_TGS_REP(&r->rep);
2270 52529 : free_TransitedEncoding(&r->et.transited);
2271 52529 : free(r->et.starttime);
2272 52529 : free(r->et.renew_till);
2273 52529 : if(r->et.authorization_data) {
2274 49286 : free_AuthorizationData(r->et.authorization_data);
2275 49286 : free(r->et.authorization_data);
2276 : }
2277 52529 : free_LastReq(&r->ek.last_req);
2278 52529 : if (r->et.key.keyvalue.data) {
2279 49297 : memset_s(r->et.key.keyvalue.data, 0, r->et.key.keyvalue.length,
2280 : r->et.key.keyvalue.length);
2281 : }
2282 52529 : free_EncryptionKey(&r->et.key);
2283 :
2284 52529 : if (r->canon_client_princ) {
2285 49482 : krb5_free_principal(r->context, r->canon_client_princ);
2286 49482 : r->canon_client_princ = NULL;
2287 : }
2288 52529 : if (r->armor_crypto) {
2289 44335 : krb5_crypto_destroy(r->context, r->armor_crypto);
2290 44335 : r->armor_crypto = NULL;
2291 : }
2292 52529 : if (r->armor_ticket)
2293 324 : krb5_free_ticket(r->context, r->armor_ticket);
2294 52529 : if (r->armor_server)
2295 326 : _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
2296 52529 : if (r->armor_client)
2297 312 : _kdc_free_ent(r->context,
2298 : r->armor_clientdb,
2299 : r->armor_client);
2300 52529 : if (r->armor_pac)
2301 312 : krb5_pac_free(r->context, r->armor_pac);
2302 52529 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2303 52529 : krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
2304 52529 : krb5_free_keyblock_contents(r->context, &r->strengthen_key);
2305 :
2306 52529 : if (r->ticket)
2307 51163 : krb5_free_ticket(r->context, r->ticket);
2308 52529 : if (r->krbtgt)
2309 51170 : _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
2310 :
2311 52529 : if (r->client)
2312 49541 : _kdc_free_ent(r->context, r->clientdb, r->client);
2313 52529 : krb5_free_principal(r->context, r->client_princ);
2314 52529 : if (r->server)
2315 49864 : _kdc_free_ent(r->context, r->serverdb, r->server);
2316 52529 : krb5_free_principal(r->context, r->server_princ);
2317 52529 : _kdc_free_fast_state(&r->fast);
2318 52529 : krb5_pac_free(r->context, r->pac);
2319 :
2320 52529 : return ret;
2321 : }
|