Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : *
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : *
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : *
19 : * 3. Neither the name of the Institute nor the names of its contributors
20 : * may be used to endorse or promote products derived from this software
21 : * without specific prior written permission.
22 : *
23 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 : * SUCH DAMAGE.
34 : */
35 :
36 : #include "krb5_locl.h"
37 :
38 : /**
39 : * Free ticket and content
40 : *
41 : * @param context a Kerberos 5 context
42 : * @param ticket ticket to free
43 : *
44 : * @return Returns 0 to indicate success. Otherwise an kerberos et
45 : * error code is returned, see krb5_get_error_message().
46 : *
47 : * @ingroup krb5
48 : */
49 :
50 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
51 133055 : krb5_free_ticket(krb5_context context,
52 : krb5_ticket *ticket)
53 : {
54 133055 : free_EncTicketPart(&ticket->ticket);
55 133055 : krb5_free_principal(context, ticket->client);
56 133055 : krb5_free_principal(context, ticket->server);
57 133055 : free(ticket);
58 133055 : return 0;
59 : }
60 :
61 : /**
62 : * Copy ticket and content
63 : *
64 : * @param context a Kerberos 5 context
65 : * @param from ticket to copy
66 : * @param to new copy of ticket, free with krb5_free_ticket()
67 : *
68 : * @return Returns 0 to indicate success. Otherwise an kerberos et
69 : * error code is returned, see krb5_get_error_message().
70 : *
71 : * @ingroup krb5
72 : */
73 :
74 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
75 46185 : krb5_copy_ticket(krb5_context context,
76 : const krb5_ticket *from,
77 : krb5_ticket **to)
78 : {
79 : krb5_error_code ret;
80 : krb5_ticket *tmp;
81 :
82 46185 : *to = NULL;
83 46185 : tmp = malloc(sizeof(*tmp));
84 46185 : if(tmp == NULL) {
85 0 : krb5_set_error_message(context, ENOMEM,
86 0 : N_("malloc: out of memory", ""));
87 0 : return ENOMEM;
88 : }
89 46185 : if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
90 0 : free(tmp);
91 0 : return ret;
92 : }
93 46185 : ret = krb5_copy_principal(context, from->client, &tmp->client);
94 46185 : if(ret){
95 0 : free_EncTicketPart(&tmp->ticket);
96 0 : free(tmp);
97 0 : return ret;
98 : }
99 46185 : ret = krb5_copy_principal(context, from->server, &tmp->server);
100 46185 : if(ret){
101 0 : krb5_free_principal(context, tmp->client);
102 0 : free_EncTicketPart(&tmp->ticket);
103 0 : free(tmp);
104 0 : return ret;
105 : }
106 46185 : *to = tmp;
107 46185 : return 0;
108 : }
109 :
110 : /**
111 : * Return client principal in ticket
112 : *
113 : * @param context a Kerberos 5 context
114 : * @param ticket ticket to copy
115 : * @param client client principal, free with krb5_free_principal()
116 : *
117 : * @return Returns 0 to indicate success. Otherwise an kerberos et
118 : * error code is returned, see krb5_get_error_message().
119 : *
120 : * @ingroup krb5
121 : */
122 :
123 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
124 1445 : krb5_ticket_get_client(krb5_context context,
125 : const krb5_ticket *ticket,
126 : krb5_principal *client)
127 : {
128 1445 : return krb5_copy_principal(context, ticket->client, client);
129 : }
130 :
131 : /**
132 : * Return server principal in ticket
133 : *
134 : * @param context a Kerberos 5 context
135 : * @param ticket ticket to copy
136 : * @param server server principal, free with krb5_free_principal()
137 : *
138 : * @return Returns 0 to indicate success. Otherwise an kerberos et
139 : * error code is returned, see krb5_get_error_message().
140 : *
141 : * @ingroup krb5
142 : */
143 :
144 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
145 0 : krb5_ticket_get_server(krb5_context context,
146 : const krb5_ticket *ticket,
147 : krb5_principal *server)
148 : {
149 0 : return krb5_copy_principal(context, ticket->server, server);
150 : }
151 :
152 : /**
153 : * Return end time of ticket
154 : *
155 : * @param context a Kerberos 5 context
156 : * @param ticket ticket to copy
157 : *
158 : * @return end time of ticket
159 : *
160 : * @ingroup krb5
161 : */
162 :
163 : KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
164 0 : krb5_ticket_get_endtime(krb5_context context,
165 : const krb5_ticket *ticket)
166 : {
167 0 : return ticket->ticket.endtime;
168 : }
169 :
170 : /**
171 : * Get the flags from the Kerberos ticket
172 : *
173 : * @param context Kerberos context
174 : * @param ticket Kerberos ticket
175 : *
176 : * @return ticket flags
177 : *
178 : * @ingroup krb5_ticket
179 : */
180 : KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL
181 0 : krb5_ticket_get_flags(krb5_context context,
182 : const krb5_ticket *ticket)
183 : {
184 0 : return TicketFlags2int(ticket->ticket.flags);
185 : }
186 :
187 : static int
188 276858 : find_type_in_ad(krb5_context context,
189 : int type,
190 : krb5_data *data,
191 : krb5_boolean *found,
192 : krb5_boolean failp,
193 : krb5_keyblock *sessionkey,
194 : const AuthorizationData *ad,
195 : int level)
196 : {
197 276858 : krb5_error_code ret = 0;
198 : size_t i;
199 :
200 276858 : if (level > 9) {
201 0 : ret = ENOENT; /* XXX */
202 0 : krb5_set_error_message(context, ret,
203 0 : N_("Authorization data nested deeper "
204 : "then %d levels, stop searching", ""),
205 : level);
206 0 : goto out;
207 : }
208 :
209 : /*
210 : * Only copy out the element the first time we get to it, we need
211 : * to run over the whole authorization data fields to check if
212 : * there are any container clases we need to care about.
213 : */
214 641574 : for (i = 0; i < ad->len; i++) {
215 369144 : if (!*found && ad->val[i].ad_type == type) {
216 92286 : ret = der_copy_octet_string(&ad->val[i].ad_data, data);
217 92286 : if (ret) {
218 0 : krb5_set_error_message(context, ret,
219 0 : N_("malloc: out of memory", ""));
220 0 : goto out;
221 : }
222 92286 : *found = TRUE;
223 92286 : continue;
224 : }
225 276858 : switch (ad->val[i].ad_type) {
226 184572 : case KRB5_AUTHDATA_IF_RELEVANT: {
227 : AuthorizationData child;
228 184572 : ret = decode_AuthorizationData(ad->val[i].ad_data.data,
229 181620 : ad->val[i].ad_data.length,
230 : &child,
231 : NULL);
232 184572 : if (ret) {
233 0 : krb5_set_error_message(context, ret,
234 0 : N_("Failed to decode "
235 : "IF_RELEVANT with %d", ""),
236 : (int)ret);
237 0 : goto out;
238 : }
239 184572 : ret = find_type_in_ad(context, type, data, found, FALSE,
240 : sessionkey, &child, level + 1);
241 184572 : free_AuthorizationData(&child);
242 184572 : if (ret)
243 0 : goto out;
244 184572 : break;
245 : }
246 : #if 0 /* XXX test */
247 : case KRB5_AUTHDATA_KDC_ISSUED: {
248 : AD_KDCIssued child;
249 :
250 : ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
251 : ad->val[i].ad_data.length,
252 : &child,
253 : NULL);
254 : if (ret) {
255 : krb5_set_error_message(context, ret,
256 : N_("Failed to decode "
257 : "AD_KDCIssued with %d", ""),
258 : ret);
259 : goto out;
260 : }
261 : if (failp) {
262 : krb5_boolean valid;
263 : krb5_data buf;
264 : size_t len;
265 :
266 : ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
267 : &child.elements, &len, ret);
268 : if (ret) {
269 : free_AD_KDCIssued(&child);
270 : krb5_clear_error_message(context);
271 : goto out;
272 : }
273 : if(buf.length != len)
274 : krb5_abortx(context, "internal error in ASN.1 encoder");
275 :
276 : ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
277 : &child.ad_checksum, &valid);
278 : krb5_data_free(&buf);
279 : if (ret) {
280 : free_AD_KDCIssued(&child);
281 : goto out;
282 : }
283 : if (!valid) {
284 : krb5_clear_error_message(context);
285 : ret = ENOENT;
286 : free_AD_KDCIssued(&child);
287 : goto out;
288 : }
289 : }
290 : ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
291 : &child.elements, level + 1);
292 : free_AD_KDCIssued(&child);
293 : if (ret)
294 : goto out;
295 : break;
296 : }
297 : #endif
298 0 : case KRB5_AUTHDATA_AND_OR:
299 0 : if (!failp)
300 0 : break;
301 0 : ret = ENOENT; /* XXX */
302 0 : krb5_set_error_message(context, ret,
303 0 : N_("Authorization data contains "
304 : "AND-OR element that is unknown to the "
305 : "application", ""));
306 0 : goto out;
307 92286 : default:
308 92286 : if (!failp)
309 90810 : break;
310 0 : ret = ENOENT; /* XXX */
311 0 : krb5_set_error_message(context, ret,
312 0 : N_("Authorization data contains "
313 : "unknown type (%d) ", ""),
314 0 : ad->val[i].ad_type);
315 0 : goto out;
316 : }
317 1476 : }
318 276858 : out:
319 276858 : if (ret) {
320 0 : if (*found) {
321 0 : krb5_data_free(data);
322 0 : *found = 0;
323 : }
324 : }
325 276858 : return ret;
326 : }
327 :
328 : /**
329 : * Extract the authorization data type of type from the ticket. Store
330 : * the field in data. This function is to use for kerberos
331 : * applications.
332 : *
333 : * @param context a Kerberos 5 context
334 : * @param ticket Kerberos ticket
335 : * @param type type to fetch
336 : * @param data returned data, free with krb5_data_free()
337 : *
338 : * @ingroup krb5
339 : */
340 :
341 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
342 92286 : krb5_ticket_get_authorization_data_type(krb5_context context,
343 : krb5_ticket *ticket,
344 : int type,
345 : krb5_data *data)
346 : {
347 : AuthorizationData *ad;
348 : krb5_error_code ret;
349 92286 : krb5_boolean found = FALSE;
350 :
351 92286 : krb5_data_zero(data);
352 :
353 92286 : ad = ticket->ticket.authorization_data;
354 92286 : if (ticket->ticket.authorization_data == NULL) {
355 0 : krb5_set_error_message(context, ENOENT,
356 0 : N_("Ticket have not authorization data", ""));
357 0 : return ENOENT; /* XXX */
358 : }
359 :
360 92286 : ret = find_type_in_ad(context, type, data, &found, TRUE,
361 92286 : &ticket->ticket.key, ad, 0);
362 92286 : if (ret)
363 0 : return ret;
364 92286 : if (!found) {
365 0 : krb5_set_error_message(context, ENOENT,
366 0 : N_("Ticket have not "
367 : "authorization data of type %d", ""),
368 : type);
369 0 : return ENOENT; /* XXX */
370 : }
371 90810 : return 0;
372 : }
373 :
374 : static krb5_error_code
375 0 : check_server_referral(krb5_context context,
376 : krb5_kdc_rep *rep,
377 : unsigned flags,
378 : krb5_const_principal requested,
379 : krb5_const_principal returned,
380 : krb5_keyblock * key)
381 : {
382 : krb5_error_code ret;
383 : PA_ServerReferralData ref;
384 : krb5_crypto session;
385 : EncryptedData ed;
386 : size_t len;
387 : krb5_data data;
388 : PA_DATA *pa;
389 0 : int i = 0, cmp;
390 :
391 0 : if (rep->kdc_rep.padata == NULL)
392 0 : goto noreferral;
393 :
394 0 : pa = krb5_find_padata(rep->kdc_rep.padata->val,
395 0 : rep->kdc_rep.padata->len,
396 : KRB5_PADATA_SERVER_REFERRAL, &i);
397 0 : if (pa == NULL)
398 0 : goto noreferral;
399 :
400 0 : memset(&ed, 0, sizeof(ed));
401 0 : memset(&ref, 0, sizeof(ref));
402 :
403 0 : ret = decode_EncryptedData(pa->padata_value.data,
404 : pa->padata_value.length,
405 : &ed, &len);
406 0 : if (ret)
407 0 : return ret;
408 0 : if (len != pa->padata_value.length) {
409 0 : free_EncryptedData(&ed);
410 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
411 0 : N_("Referral EncryptedData wrong for realm %s",
412 : "realm"), requested->realm);
413 0 : return KRB5KRB_AP_ERR_MODIFIED;
414 : }
415 :
416 0 : ret = krb5_crypto_init(context, key, 0, &session);
417 0 : if (ret) {
418 0 : free_EncryptedData(&ed);
419 0 : return ret;
420 : }
421 :
422 0 : ret = krb5_decrypt_EncryptedData(context, session,
423 : KRB5_KU_PA_SERVER_REFERRAL,
424 : &ed, &data);
425 0 : free_EncryptedData(&ed);
426 0 : krb5_crypto_destroy(context, session);
427 0 : if (ret)
428 0 : return ret;
429 :
430 0 : ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
431 0 : if (ret) {
432 0 : krb5_data_free(&data);
433 0 : return ret;
434 : }
435 0 : krb5_data_free(&data);
436 :
437 0 : if (strcmp(requested->realm, returned->realm) != 0) {
438 0 : free_PA_ServerReferralData(&ref);
439 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
440 0 : N_("server ref realm mismatch, "
441 : "requested realm %s got back %s", ""),
442 : requested->realm, returned->realm);
443 0 : return KRB5KRB_AP_ERR_MODIFIED;
444 : }
445 :
446 0 : if (krb5_principal_is_krbtgt(context, returned)) {
447 0 : const char *realm = returned->name.name_string.val[1];
448 :
449 0 : if (ref.referred_realm == NULL
450 0 : || strcmp(*ref.referred_realm, realm) != 0)
451 : {
452 0 : free_PA_ServerReferralData(&ref);
453 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
454 0 : N_("tgt returned with wrong ref", ""));
455 0 : return KRB5KRB_AP_ERR_MODIFIED;
456 : }
457 0 : } else if (krb5_principal_compare(context, returned, requested) == 0) {
458 0 : free_PA_ServerReferralData(&ref);
459 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
460 0 : N_("req princ no same as returned", ""));
461 0 : return KRB5KRB_AP_ERR_MODIFIED;
462 : }
463 :
464 0 : if (ref.requested_principal_name) {
465 0 : cmp = _krb5_principal_compare_PrincipalName(context,
466 : requested,
467 : ref.requested_principal_name);
468 0 : if (!cmp) {
469 0 : free_PA_ServerReferralData(&ref);
470 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
471 0 : N_("referred principal not same "
472 : "as requested", ""));
473 0 : return KRB5KRB_AP_ERR_MODIFIED;
474 : }
475 0 : } else if (flags & EXTRACT_TICKET_AS_REQ) {
476 0 : free_PA_ServerReferralData(&ref);
477 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
478 0 : N_("Requested principal missing on AS-REQ", ""));
479 0 : return KRB5KRB_AP_ERR_MODIFIED;
480 : }
481 :
482 0 : free_PA_ServerReferralData(&ref);
483 :
484 0 : return ret;
485 0 : noreferral:
486 : /*
487 : * Expect excact match or that we got a krbtgt
488 : */
489 0 : if (krb5_principal_compare(context, requested, returned) != TRUE &&
490 0 : (krb5_realm_compare(context, requested, returned) != TRUE &&
491 0 : krb5_principal_is_krbtgt(context, returned) != TRUE))
492 : {
493 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
494 0 : N_("Not same server principal returned "
495 : "as requested", ""));
496 0 : return KRB5KRB_AP_ERR_MODIFIED;
497 : }
498 0 : return 0;
499 : }
500 :
501 :
502 : /*
503 : * Verify referral data
504 : */
505 :
506 :
507 : static krb5_error_code
508 0 : check_client_referral(krb5_context context,
509 : krb5_kdc_rep *rep,
510 : krb5_const_principal requested,
511 : krb5_const_principal mapped,
512 : krb5_keyblock const * key)
513 : {
514 0 : if (krb5_principal_compare(context, requested, mapped) == FALSE) {
515 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
516 0 : N_("Not same client principal returned "
517 : "as requested", ""));
518 0 : return KRB5KRB_AP_ERR_MODIFIED;
519 : }
520 0 : return 0;
521 : }
522 :
523 :
524 : static krb5_error_code KRB5_CALLCONV
525 13985 : decrypt_tkt (krb5_context context,
526 : krb5_keyblock *key,
527 : krb5_key_usage usage,
528 : krb5_const_pointer decrypt_arg,
529 : krb5_kdc_rep *dec_rep)
530 : {
531 : krb5_error_code ret;
532 : krb5_data data;
533 : size_t size;
534 : krb5_crypto crypto;
535 :
536 13985 : ret = krb5_crypto_init(context, key, 0, &crypto);
537 13985 : if (ret)
538 0 : return ret;
539 :
540 13985 : ret = krb5_decrypt_EncryptedData (context,
541 : crypto,
542 : usage,
543 13985 : &dec_rep->kdc_rep.enc_part,
544 : &data);
545 13985 : krb5_crypto_destroy(context, crypto);
546 :
547 13985 : if (ret)
548 0 : return ret;
549 :
550 13985 : ret = decode_EncASRepPart(data.data,
551 : data.length,
552 13985 : &dec_rep->enc_part,
553 : &size);
554 13985 : if (ret)
555 0 : ret = decode_EncTGSRepPart(data.data,
556 : data.length,
557 0 : &dec_rep->enc_part,
558 : &size);
559 13985 : krb5_data_free (&data);
560 13985 : if (ret) {
561 0 : krb5_set_error_message(context, ret,
562 0 : N_("Failed to decode encpart in ticket", ""));
563 0 : return ret;
564 : }
565 13690 : return 0;
566 : }
567 :
568 : int
569 54695 : _krb5_extract_ticket(krb5_context context,
570 : krb5_kdc_rep *rep,
571 : krb5_creds *creds,
572 : krb5_keyblock *key,
573 : krb5_const_pointer keyseed,
574 : krb5_key_usage key_usage,
575 : krb5_addresses *addrs,
576 : unsigned nonce,
577 : unsigned flags,
578 : krb5_decrypt_proc decrypt_proc,
579 : krb5_const_pointer decryptarg)
580 : {
581 : krb5_error_code ret;
582 : krb5_principal tmp_principal;
583 54695 : size_t len = 0;
584 : time_t tmp_time;
585 : krb5_timestamp sec_now;
586 :
587 : /* decrypt */
588 :
589 54695 : if (decrypt_proc == NULL)
590 13985 : decrypt_proc = decrypt_tkt;
591 :
592 54695 : ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
593 54695 : if (ret)
594 0 : goto out;
595 :
596 : /* save session key */
597 :
598 54695 : creds->session.keyvalue.length = 0;
599 54695 : creds->session.keyvalue.data = NULL;
600 54695 : creds->session.keytype = rep->enc_part.key.keytype;
601 109390 : ret = krb5_data_copy (&creds->session.keyvalue,
602 54695 : rep->enc_part.key.keyvalue.data,
603 : rep->enc_part.key.keyvalue.length);
604 54695 : if (ret) {
605 0 : krb5_clear_error_message(context);
606 0 : goto out;
607 : }
608 :
609 : /*
610 : * HACK:
611 : * this is really a ugly hack, to support using the Netbios Domain Name
612 : * as realm against windows KDC's, they always return the full realm
613 : * based on the DNS Name.
614 : */
615 54695 : flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
616 54695 : flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
617 :
618 : /* compare client and save */
619 54695 : ret = _krb5_principalname2krb5_principal (context,
620 : &tmp_principal,
621 : rep->kdc_rep.cname,
622 : rep->kdc_rep.crealm);
623 54695 : if (ret)
624 0 : goto out;
625 :
626 : /* check client referral and save principal */
627 : /* anonymous here ? */
628 53311 : if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
629 0 : ret = check_client_referral(context, rep,
630 0 : creds->client,
631 : tmp_principal,
632 0 : &creds->session);
633 0 : if (ret) {
634 0 : krb5_free_principal (context, tmp_principal);
635 0 : goto out;
636 : }
637 : }
638 54695 : krb5_free_principal (context, creds->client);
639 54695 : creds->client = tmp_principal;
640 :
641 : /* check server referral and save principal */
642 54695 : ret = _krb5_principalname2krb5_principal (context,
643 : &tmp_principal,
644 : rep->enc_part.sname,
645 : rep->enc_part.srealm);
646 54695 : if (ret)
647 0 : goto out;
648 53311 : if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
649 0 : ret = check_server_referral(context,
650 : rep,
651 : flags,
652 0 : creds->server,
653 : tmp_principal,
654 : &creds->session);
655 0 : if (ret) {
656 0 : krb5_free_principal (context, tmp_principal);
657 0 : goto out;
658 : }
659 : }
660 54695 : krb5_free_principal(context, creds->server);
661 54695 : creds->server = tmp_principal;
662 :
663 : /* verify names */
664 54695 : if(flags & EXTRACT_TICKET_MATCH_REALM){
665 12977 : const char *srealm = krb5_principal_get_realm(context, creds->server);
666 12977 : const char *crealm = krb5_principal_get_realm(context, creds->client);
667 :
668 25954 : if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
669 12977 : strcmp(rep->enc_part.srealm, crealm) != 0)
670 : {
671 0 : ret = KRB5KRB_AP_ERR_MODIFIED;
672 0 : krb5_clear_error_message(context);
673 0 : goto out;
674 : }
675 : }
676 :
677 : /* compare nonces */
678 :
679 54695 : if (nonce != (unsigned)rep->enc_part.nonce) {
680 0 : ret = KRB5KRB_AP_ERR_MODIFIED;
681 0 : krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
682 0 : goto out;
683 : }
684 :
685 : /* set kdc-offset */
686 :
687 54695 : krb5_timeofday (context, &sec_now);
688 54695 : if (rep->enc_part.flags.initial
689 13985 : && (flags & EXTRACT_TICKET_TIMESYNC)
690 13985 : && context->kdc_sec_offset == 0
691 13985 : && krb5_config_get_bool (context, NULL,
692 : "libdefaults",
693 : "kdc_timesync",
694 : NULL)) {
695 0 : context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
696 0 : krb5_timeofday (context, &sec_now);
697 : }
698 :
699 : /* check all times */
700 :
701 54695 : if (rep->enc_part.starttime) {
702 40710 : tmp_time = *rep->enc_part.starttime;
703 : } else
704 13985 : tmp_time = rep->enc_part.authtime;
705 :
706 54695 : if (creds->times.starttime == 0
707 54695 : && abs(tmp_time - sec_now) > context->max_skew) {
708 0 : ret = KRB5KRB_AP_ERR_SKEW;
709 0 : krb5_set_error_message (context, ret,
710 0 : N_("time skew (%d) larger than max (%d)", ""),
711 0 : abs(tmp_time - sec_now),
712 0 : (int)context->max_skew);
713 0 : goto out;
714 : }
715 :
716 54695 : if (creds->times.starttime != 0
717 0 : && tmp_time != creds->times.starttime) {
718 0 : krb5_clear_error_message (context);
719 0 : ret = KRB5KRB_AP_ERR_MODIFIED;
720 0 : goto out;
721 : }
722 :
723 54695 : creds->times.starttime = tmp_time;
724 :
725 54695 : if (rep->enc_part.renew_till) {
726 65 : tmp_time = *rep->enc_part.renew_till;
727 : } else
728 53246 : tmp_time = 0;
729 :
730 54695 : if (creds->times.renew_till != 0
731 35 : && tmp_time > creds->times.renew_till) {
732 0 : krb5_clear_error_message (context);
733 0 : ret = KRB5KRB_AP_ERR_MODIFIED;
734 0 : goto out;
735 : }
736 :
737 54695 : creds->times.renew_till = tmp_time;
738 :
739 54695 : creds->times.authtime = rep->enc_part.authtime;
740 :
741 54695 : if (creds->times.endtime != 0
742 14035 : && rep->enc_part.endtime > creds->times.endtime) {
743 0 : krb5_clear_error_message (context);
744 0 : ret = KRB5KRB_AP_ERR_MODIFIED;
745 0 : goto out;
746 : }
747 :
748 54695 : creds->times.endtime = rep->enc_part.endtime;
749 :
750 54695 : if(rep->enc_part.caddr)
751 3 : krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
752 54692 : else if(addrs)
753 40710 : krb5_copy_addresses (context, addrs, &creds->addresses);
754 : else {
755 13982 : creds->addresses.len = 0;
756 13982 : creds->addresses.val = NULL;
757 : }
758 54695 : creds->flags.b = rep->enc_part.flags;
759 :
760 54695 : creds->authdata.len = 0;
761 54695 : creds->authdata.val = NULL;
762 :
763 : /* extract ticket */
764 54695 : ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
765 : &rep->kdc_rep.ticket, &len, ret);
766 54695 : if(ret)
767 0 : goto out;
768 54695 : if (creds->ticket.length != len)
769 0 : krb5_abortx(context, "internal error in ASN.1 encoder");
770 54695 : creds->second_ticket.length = 0;
771 54695 : creds->second_ticket.data = NULL;
772 :
773 :
774 54695 : out:
775 56079 : memset (rep->enc_part.key.keyvalue.data, 0,
776 : rep->enc_part.key.keyvalue.length);
777 54695 : return ret;
778 : }
|