r9413: Bring Samba4 back up to date with lorikeet-heimdal.
[Samba/aatanasov.git] / source / heimdal / kdc / kerberos5.c
blob27a25d95ff4f79fc2dc6e410e05eae1aedf8aa7f
1 /*
2 * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "kdc_locl.h"
35 #ifdef _SAMBA_BUILD_
36 #include "kdc/pac-glue.h"
37 #endif
39 RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
41 #define MAX_TIME ((time_t)((1U << 31) - 1))
43 static void
44 fix_time(time_t **t)
46 if(*t == NULL){
47 ALLOC(*t);
48 **t = MAX_TIME;
50 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
53 static int
54 realloc_method_data(METHOD_DATA *md)
56 PA_DATA *pa;
57 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
58 if(pa == NULL)
59 return ENOMEM;
60 md->val = pa;
61 md->len++;
62 return 0;
65 static void
66 set_salt_padata (METHOD_DATA *md, Salt *salt)
68 if (salt) {
69 realloc_method_data(md);
70 md->val[md->len - 1].padata_type = salt->type;
71 copy_octet_string(&salt->salt,
72 &md->val[md->len - 1].padata_value);
76 static PA_DATA*
77 find_padata(KDC_REQ *req, int *start, int type)
79 while(*start < req->padata->len){
80 (*start)++;
81 if(req->padata->val[*start - 1].padata_type == type)
82 return &req->padata->val[*start - 1];
84 return NULL;
88 * return the first appropriate key of `princ' in `ret_key'. Look for
89 * all the etypes in (`etypes', `len'), stopping as soon as we find
90 * one, but preferring one that has default salt
93 static krb5_error_code
94 find_etype(krb5_context context, hdb_entry *princ,
95 krb5_enctype *etypes, unsigned len,
96 Key **ret_key, krb5_enctype *ret_etype)
98 int i;
99 krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
101 for(i = 0; ret != 0 && i < len ; i++) {
102 Key *key = NULL;
104 if (krb5_enctype_valid(context, etypes[i]) != 0)
105 continue;
107 while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
108 if (key->key.keyvalue.length == 0) {
109 ret = KRB5KDC_ERR_NULL_KEY;
110 continue;
112 *ret_key = key;
113 *ret_etype = etypes[i];
114 ret = 0;
115 if (key->salt == NULL)
116 return ret;
119 return ret;
122 static krb5_error_code
123 find_keys(krb5_context context,
124 krb5_kdc_configuration *config,
125 hdb_entry *client,
126 hdb_entry *server,
127 Key **ckey,
128 krb5_enctype *cetype,
129 Key **skey,
130 krb5_enctype *setype,
131 krb5_enctype *etypes,
132 unsigned num_etypes)
134 char unparse_name[] = "krb5_unparse_name failed";
135 krb5_error_code ret;
136 char *name;
138 if(client){
139 /* find client key */
140 ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
141 if (ret) {
142 if (krb5_unparse_name(context, client->principal, &name) != 0)
143 name = unparse_name;
144 kdc_log(context, config, 0,
145 "Client (%s) has no support for etypes", name);
146 if (name != unparse_name)
147 free(name);
148 return ret;
152 if(server){
153 /* find server key */
154 ret = find_etype(context, server, etypes, num_etypes, skey, setype);
155 if (ret) {
156 if (krb5_unparse_name(context, server->principal, &name) != 0)
157 name = unparse_name;
158 kdc_log(context, config, 0,
159 "Server (%s) has no support for etypes", name);
160 if (name != unparse_name)
161 free(name);
162 return ret;
165 return 0;
168 static krb5_error_code
169 make_anonymous_principalname (PrincipalName *pn)
171 pn->name_type = KRB5_NT_PRINCIPAL;
172 pn->name_string.len = 1;
173 pn->name_string.val = malloc(sizeof(*pn->name_string.val));
174 if (pn->name_string.val == NULL)
175 return ENOMEM;
176 pn->name_string.val[0] = strdup("anonymous");
177 if (pn->name_string.val[0] == NULL) {
178 free(pn->name_string.val);
179 pn->name_string.val = NULL;
180 return ENOMEM;
182 return 0;
185 static void
186 log_timestamp(krb5_context context,
187 krb5_kdc_configuration *config,
188 const char *type,
189 KerberosTime authtime, KerberosTime *starttime,
190 KerberosTime endtime, KerberosTime *renew_till)
192 char authtime_str[100], starttime_str[100],
193 endtime_str[100], renewtime_str[100];
195 krb5_format_time(context, authtime,
196 authtime_str, sizeof(authtime_str), TRUE);
197 if (starttime)
198 krb5_format_time(context, *starttime,
199 starttime_str, sizeof(starttime_str), TRUE);
200 else
201 strlcpy(starttime_str, "unset", sizeof(starttime_str));
202 krb5_format_time(context, endtime,
203 endtime_str, sizeof(endtime_str), TRUE);
204 if (renew_till)
205 krb5_format_time(context, *renew_till,
206 renewtime_str, sizeof(renewtime_str), TRUE);
207 else
208 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
210 kdc_log(context, config, 5,
211 "%s authtime: %s starttime: %s endtype: %s renew till: %s",
212 type, authtime_str, starttime_str, endtime_str, renewtime_str);
215 static krb5_error_code
216 encode_reply(krb5_context context,
217 krb5_kdc_configuration *config,
218 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
219 krb5_enctype etype,
220 int skvno, EncryptionKey *skey,
221 int ckvno, EncryptionKey *ckey,
222 const char **e_text,
223 krb5_data *reply)
225 unsigned char *buf;
226 size_t buf_size;
227 size_t len;
228 krb5_error_code ret;
229 krb5_crypto crypto;
231 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
232 if(ret) {
233 kdc_log(context, config, 0, "Failed to encode ticket: %s",
234 krb5_get_err_text(context, ret));
235 return ret;
237 if(buf_size != len) {
238 free(buf);
239 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
240 *e_text = "KDC internal error";
241 return KRB5KRB_ERR_GENERIC;
244 ret = krb5_crypto_init(context, skey, etype, &crypto);
245 if (ret) {
246 free(buf);
247 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
248 krb5_get_err_text(context, ret));
249 return ret;
252 ret = krb5_encrypt_EncryptedData(context,
253 crypto,
254 KRB5_KU_TICKET,
255 buf,
256 len,
257 skvno,
258 &rep->ticket.enc_part);
259 free(buf);
260 krb5_crypto_destroy(context, crypto);
261 if(ret) {
262 kdc_log(context, config, 0, "Failed to encrypt data: %s",
263 krb5_get_err_text(context, ret));
264 return ret;
267 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
268 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
269 else
270 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
271 if(ret) {
272 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
273 krb5_get_err_text(context, ret));
274 return ret;
276 if(buf_size != len) {
277 free(buf);
278 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
279 *e_text = "KDC internal error";
280 return KRB5KRB_ERR_GENERIC;
282 ret = krb5_crypto_init(context, ckey, 0, &crypto);
283 if (ret) {
284 free(buf);
285 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
286 krb5_get_err_text(context, ret));
287 return ret;
289 if(rep->msg_type == krb_as_rep) {
290 krb5_encrypt_EncryptedData(context,
291 crypto,
292 KRB5_KU_AS_REP_ENC_PART,
293 buf,
294 len,
295 ckvno,
296 &rep->enc_part);
297 free(buf);
298 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
299 } else {
300 krb5_encrypt_EncryptedData(context,
301 crypto,
302 KRB5_KU_TGS_REP_ENC_PART_SESSION,
303 buf,
304 len,
305 ckvno,
306 &rep->enc_part);
307 free(buf);
308 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
310 krb5_crypto_destroy(context, crypto);
311 if(ret) {
312 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
313 krb5_get_err_text(context, ret));
314 return ret;
316 if(buf_size != len) {
317 free(buf);
318 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
319 *e_text = "KDC internal error";
320 return KRB5KRB_ERR_GENERIC;
322 reply->data = buf;
323 reply->length = buf_size;
324 return 0;
327 static krb5_error_code
328 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
330 ent->etype = key->key.keytype;
331 if(key->salt){
332 ALLOC(ent->salttype);
333 #if 0
334 if(key->salt->type == hdb_pw_salt)
335 *ent->salttype = 0; /* or 1? or NULL? */
336 else if(key->salt->type == hdb_afs3_salt)
337 *ent->salttype = 2;
338 else {
339 kdc_log(context, config, 0, "unknown salt-type: %d",
340 key->salt->type);
341 return KRB5KRB_ERR_GENERIC;
343 /* according to `the specs', we can't send a salt if
344 we have AFS3 salted key, but that requires that you
345 *know* what cell you are using (e.g by assuming
346 that the cell is the same as the realm in lower
347 case) */
348 #else
349 *ent->salttype = key->salt->type;
350 #endif
351 krb5_copy_data(context, &key->salt->salt,
352 &ent->salt);
353 } else {
354 /* we return no salt type at all, as that should indicate
355 * the default salt type and make everybody happy. some
356 * systems (like w2k) dislike being told the salt type
357 * here. */
359 ent->salttype = NULL;
360 ent->salt = NULL;
362 return 0;
365 static krb5_error_code
366 get_pa_etype_info(krb5_context context,
367 krb5_kdc_configuration *config,
368 METHOD_DATA *md, hdb_entry *client,
369 ENCTYPE *etypes, unsigned int etypes_len)
371 krb5_error_code ret = 0;
372 int i, j;
373 unsigned int n = 0;
374 ETYPE_INFO pa;
375 unsigned char *buf;
376 size_t len;
379 pa.len = client->keys.len;
380 if(pa.len > UINT_MAX/sizeof(*pa.val))
381 return ERANGE;
382 pa.val = malloc(pa.len * sizeof(*pa.val));
383 if(pa.val == NULL)
384 return ENOMEM;
385 memset(pa.val, 0, pa.len * sizeof(*pa.val));
387 for(j = 0; j < etypes_len; j++) {
388 for (i = 0; i < n; i++)
389 if (pa.val[i].etype == etypes[j])
390 goto skip1;
391 for(i = 0; i < client->keys.len; i++) {
392 if(client->keys.val[i].key.keytype == etypes[j]) {
393 if (krb5_enctype_valid(context, etypes[j]) != 0)
394 continue;
395 if((ret = make_etype_info_entry(context,
396 &pa.val[n++],
397 &client->keys.val[i])) != 0) {
398 free_ETYPE_INFO(&pa);
399 return ret;
403 skip1:;
405 for(i = 0; i < client->keys.len; i++) {
406 for(j = 0; j < etypes_len; j++) {
407 if(client->keys.val[i].key.keytype == etypes[j])
408 goto skip2;
410 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
411 continue;
412 if((ret = make_etype_info_entry(context,
413 &pa.val[n++],
414 &client->keys.val[i])) != 0) {
415 free_ETYPE_INFO(&pa);
416 return ret;
418 skip2:;
421 if(n != pa.len) {
422 char *name;
423 ret = krb5_unparse_name(context, client->principal, &name);
424 if (ret)
425 name = "<unparse_name failed>";
426 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
427 name, n, pa.len);
428 if (ret == 0)
429 free(name);
430 pa.len = n;
433 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
434 free_ETYPE_INFO(&pa);
435 if(ret)
436 return ret;
437 ret = realloc_method_data(md);
438 if(ret) {
439 free(buf);
440 return ret;
442 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
443 md->val[md->len - 1].padata_value.length = len;
444 md->val[md->len - 1].padata_value.data = buf;
445 return 0;
452 extern int _krb5_AES_string_to_default_iterator;
454 static krb5_error_code
455 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
457 ent->etype = key->key.keytype;
458 if(key->salt) {
459 ALLOC(ent->salt);
460 if (ent->salt == NULL)
461 return ENOMEM;
462 *ent->salt = malloc(key->salt->salt.length + 1);
463 if (*ent->salt == NULL) {
464 free(ent->salt);
465 ent->salt = NULL;
466 return ENOMEM;
468 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
469 (*ent->salt)[key->salt->salt.length] = '\0';
470 } else
471 ent->salt = NULL;
473 ent->s2kparams = NULL;
475 switch (key->key.keytype) {
476 case KEYTYPE_AES128:
477 case KEYTYPE_AES256:
478 ALLOC(ent->s2kparams);
479 if (ent->s2kparams == NULL)
480 return ENOMEM;
481 ent->s2kparams->length = 4;
482 ent->s2kparams->data = malloc(ent->s2kparams->length);
483 if (ent->s2kparams->data == NULL) {
484 free(ent->s2kparams);
485 ent->s2kparams = NULL;
486 return ENOMEM;
488 _krb5_put_int(ent->s2kparams->data,
489 _krb5_AES_string_to_default_iterator,
490 ent->s2kparams->length);
491 break;
492 default:
493 break;
495 return 0;
499 * Return 1 if the client have only older enctypes, this is for
500 * determining if the server should send ETYPE_INFO2 or not.
503 static int
504 only_older_enctype_p(const KDC_REQ *req)
506 int i;
508 for(i = 0; i < req->req_body.etype.len; i++) {
509 switch (req->req_body.etype.val[i]) {
510 case ETYPE_DES_CBC_CRC:
511 case ETYPE_DES_CBC_MD4:
512 case ETYPE_DES_CBC_MD5:
513 case ETYPE_DES3_CBC_SHA1:
514 case ETYPE_ARCFOUR_HMAC_MD5:
515 case ETYPE_ARCFOUR_HMAC_MD5_56:
516 break;
517 default:
518 return 0;
521 return 1;
528 static krb5_error_code
529 get_pa_etype_info2(krb5_context context,
530 krb5_kdc_configuration *config,
531 METHOD_DATA *md, hdb_entry *client,
532 ENCTYPE *etypes, unsigned int etypes_len)
534 krb5_error_code ret = 0;
535 int i, j;
536 unsigned int n = 0;
537 ETYPE_INFO2 pa;
538 unsigned char *buf;
539 size_t len;
541 pa.len = client->keys.len;
542 if(pa.len > UINT_MAX/sizeof(*pa.val))
543 return ERANGE;
544 pa.val = malloc(pa.len * sizeof(*pa.val));
545 if(pa.val == NULL)
546 return ENOMEM;
547 memset(pa.val, 0, pa.len * sizeof(*pa.val));
549 for(j = 0; j < etypes_len; j++) {
550 for (i = 0; i < n; i++)
551 if (pa.val[i].etype == etypes[j])
552 goto skip1;
553 for(i = 0; i < client->keys.len; i++) {
554 if(client->keys.val[i].key.keytype == etypes[j]) {
555 if (krb5_enctype_valid(context, etypes[j]) != 0)
556 continue;
557 if((ret = make_etype_info2_entry(&pa.val[n++],
558 &client->keys.val[i])) != 0) {
559 free_ETYPE_INFO2(&pa);
560 return ret;
564 skip1:;
566 for(i = 0; i < client->keys.len; i++) {
567 for(j = 0; j < etypes_len; j++) {
568 if(client->keys.val[i].key.keytype == etypes[j])
569 goto skip2;
571 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
572 continue;
573 if((ret = make_etype_info2_entry(&pa.val[n++],
574 &client->keys.val[i])) != 0) {
575 free_ETYPE_INFO2(&pa);
576 return ret;
578 skip2:;
581 if(n != pa.len) {
582 char *name;
583 ret = krb5_unparse_name(context, client->principal, &name);
584 if (ret)
585 name = "<unparse_name failed>";
586 kdc_log(context, config, 0,
587 "internal error in get_pa_etype_info2(%s): %d != %d",
588 name, n, pa.len);
589 if (ret == 0)
590 free(name);
591 pa.len = n;
594 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
595 free_ETYPE_INFO2(&pa);
596 if(ret)
597 return ret;
598 ret = realloc_method_data(md);
599 if(ret) {
600 free(buf);
601 return ret;
603 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
604 md->val[md->len - 1].padata_value.length = len;
605 md->val[md->len - 1].padata_value.data = buf;
606 return 0;
610 * verify the flags on `client' and `server', returning 0
611 * if they are OK and generating an error messages and returning
612 * and error code otherwise.
615 krb5_error_code
616 _kdc_check_flags(krb5_context context,
617 krb5_kdc_configuration *config,
618 hdb_entry *client, const char *client_name,
619 hdb_entry *server, const char *server_name,
620 krb5_boolean is_as_req)
622 if(client != NULL) {
623 /* check client */
624 if (client->flags.invalid) {
625 kdc_log(context, config, 0,
626 "Client (%s) has invalid bit set", client_name);
627 return KRB5KDC_ERR_POLICY;
630 if(!client->flags.client){
631 kdc_log(context, config, 0,
632 "Principal may not act as client -- %s", client_name);
633 return KRB5KDC_ERR_POLICY;
636 if (client->valid_start && *client->valid_start > kdc_time) {
637 kdc_log(context, config, 0,
638 "Client not yet valid -- %s", client_name);
639 return KRB5KDC_ERR_CLIENT_NOTYET;
642 if (client->valid_end && *client->valid_end < kdc_time) {
643 kdc_log(context, config, 0,
644 "Client expired -- %s", client_name);
645 return KRB5KDC_ERR_NAME_EXP;
648 if (client->pw_end && *client->pw_end < kdc_time
649 && !server->flags.change_pw) {
650 kdc_log(context, config, 0,
651 "Client's key has expired -- %s", client_name);
652 return KRB5KDC_ERR_KEY_EXPIRED;
656 /* check server */
658 if (server != NULL) {
659 if (server->flags.invalid) {
660 kdc_log(context, config, 0,
661 "Server has invalid flag set -- %s", server_name);
662 return KRB5KDC_ERR_POLICY;
665 if(!server->flags.server){
666 kdc_log(context, config, 0,
667 "Principal may not act as server -- %s", server_name);
668 return KRB5KDC_ERR_POLICY;
671 if(!is_as_req && server->flags.initial) {
672 kdc_log(context, config, 0,
673 "AS-REQ is required for server -- %s", server_name);
674 return KRB5KDC_ERR_POLICY;
677 if (server->valid_start && *server->valid_start > kdc_time) {
678 kdc_log(context, config, 0,
679 "Server not yet valid -- %s", server_name);
680 return KRB5KDC_ERR_SERVICE_NOTYET;
683 if (server->valid_end && *server->valid_end < kdc_time) {
684 kdc_log(context, config, 0,
685 "Server expired -- %s", server_name);
686 return KRB5KDC_ERR_SERVICE_EXP;
689 if (server->pw_end && *server->pw_end < kdc_time) {
690 kdc_log(context, config, 0,
691 "Server's key has expired -- %s", server_name);
692 return KRB5KDC_ERR_KEY_EXPIRED;
695 return 0;
699 * Return TRUE if `from' is part of `addresses' taking into consideration
700 * the configuration variables that tells us how strict we should be about
701 * these checks
704 static krb5_boolean
705 check_addresses(krb5_context context,
706 krb5_kdc_configuration *config,
707 HostAddresses *addresses, const struct sockaddr *from)
709 krb5_error_code ret;
710 krb5_address addr;
711 krb5_boolean result;
713 if(config->check_ticket_addresses == 0)
714 return TRUE;
716 if(addresses == NULL)
717 return config->allow_null_ticket_addresses;
719 ret = krb5_sockaddr2address (context, from, &addr);
720 if(ret)
721 return FALSE;
723 result = krb5_address_search(context, &addr, addresses);
724 krb5_free_address (context, &addr);
725 return result;
728 krb5_error_code
729 _kdc_as_rep(krb5_context context,
730 krb5_kdc_configuration *config,
731 KDC_REQ *req,
732 const krb5_data *req_buffer,
733 krb5_data *reply,
734 const char *from,
735 struct sockaddr *from_addr)
737 KDC_REQ_BODY *b = &req->req_body;
738 AS_REP rep;
739 KDCOptions f = b->kdc_options;
740 hdb_entry *client = NULL, *server = NULL;
741 krb5_enctype cetype, setype;
742 EncTicketPart et;
743 EncKDCRepPart ek;
744 krb5_principal client_princ = NULL, server_princ = NULL;
745 char *client_name = NULL, *server_name = NULL;
746 krb5_error_code ret = 0;
747 const char *e_text = NULL;
748 krb5_crypto crypto;
749 Key *ckey, *skey;
750 EncryptionKey *reply_key;
751 #ifdef PKINIT
752 pk_client_params *pkp = NULL;
753 #endif
755 memset(&rep, 0, sizeof(rep));
757 if(b->sname == NULL){
758 ret = KRB5KRB_ERR_GENERIC;
759 e_text = "No server in request";
760 } else{
761 _krb5_principalname2krb5_principal (&server_princ,
762 *(b->sname), b->realm);
763 ret = krb5_unparse_name(context, server_princ, &server_name);
765 if (ret) {
766 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
767 goto out;
770 if(b->cname == NULL){
771 ret = KRB5KRB_ERR_GENERIC;
772 e_text = "No client in request";
773 } else {
774 _krb5_principalname2krb5_principal (&client_princ,
775 *(b->cname), b->realm);
776 ret = krb5_unparse_name(context, client_princ, &client_name);
778 if (ret) {
779 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
780 goto out;
783 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
784 client_name, from, server_name);
786 ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
787 if(ret){
788 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
789 krb5_get_err_text(context, ret));
790 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
791 goto out;
794 ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
795 if(ret){
796 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
797 krb5_get_err_text(context, ret));
798 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
799 goto out;
802 ret = _kdc_check_flags(context, config,
803 client, client_name,
804 server, server_name,
805 TRUE);
806 if(ret)
807 goto out;
809 memset(&et, 0, sizeof(et));
810 memset(&ek, 0, sizeof(ek));
812 if(req->padata){
813 int i = 0;
814 PA_DATA *pa;
815 int found_pa = 0;
817 #ifdef PKINIT
818 kdc_log(context, config, 5,
819 "Looking for PKINIT pa-data -- %s", client_name);
821 e_text = "No PKINIT PA found";
823 i = 0;
824 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
826 if (pa == NULL) {
827 i = 0;
828 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
831 if (pa == NULL) {
832 i = 0;
833 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
836 if (pa) {
837 char *client_cert = NULL;
839 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
840 if (ret) {
841 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
842 kdc_log(context, config, 5,
843 "Failed to decode PKINIT PA-DATA -- %s",
844 client_name);
845 goto ts_enc;
847 if (ret == 0 && pkp == NULL)
848 goto ts_enc;
850 ret = _kdc_pk_check_client(context,
851 config,
852 client_princ,
853 client,
854 pkp,
855 &client_cert);
856 if (ret) {
857 e_text = "PKINIT certificate not allowed to "
858 "impersonate principal";
859 _kdc_pk_free_client_param(context, pkp);
860 pkp = NULL;
861 goto ts_enc;
863 found_pa = 1;
864 et.flags.pre_authent = 1;
865 kdc_log(context, config, 2,
866 "PKINIT pre-authentication succeeded -- %s using %s",
867 client_name, client_cert);
868 free(client_cert);
869 if (pkp)
870 goto preauth_done;
872 ts_enc:
873 #endif
874 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
875 client_name);
877 i = 0;
878 e_text = "No ENC-TS found";
879 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
880 krb5_data ts_data;
881 PA_ENC_TS_ENC p;
882 size_t len;
883 EncryptedData enc_data;
884 Key *pa_key;
885 char *str;
887 found_pa = 1;
889 ret = decode_EncryptedData(pa->padata_value.data,
890 pa->padata_value.length,
891 &enc_data,
892 &len);
893 if (ret) {
894 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
895 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
896 client_name);
897 goto out;
900 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
901 if(ret){
902 char *estr;
903 e_text = "No key matches pa-data";
904 ret = KRB5KDC_ERR_PREAUTH_FAILED;
905 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
906 estr = NULL;
907 if(estr == NULL)
908 kdc_log(context, config, 5,
909 "No client key matching pa-data (%d) -- %s",
910 enc_data.etype, client_name);
911 else
912 kdc_log(context, config, 5,
913 "No client key matching pa-data (%s) -- %s",
914 estr, client_name);
915 free(estr);
917 free_EncryptedData(&enc_data);
918 continue;
921 try_next_key:
922 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
923 if (ret) {
924 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
925 krb5_get_err_text(context, ret));
926 free_EncryptedData(&enc_data);
927 continue;
930 ret = krb5_decrypt_EncryptedData (context,
931 crypto,
932 KRB5_KU_PA_ENC_TIMESTAMP,
933 &enc_data,
934 &ts_data);
935 krb5_crypto_destroy(context, crypto);
936 if(ret){
937 krb5_error_code ret2;
938 ret2 = krb5_enctype_to_string(context,
939 pa_key->key.keytype, &str);
940 if (ret2)
941 str = NULL;
942 kdc_log(context, config, 5,
943 "Failed to decrypt PA-DATA -- %s "
944 "(enctype %s) error %s",
945 client_name,
946 str ? str : "unknown enctype",
947 krb5_get_err_text(context, ret));
948 free(str);
950 if(hdb_next_enctype2key(context, client,
951 enc_data.etype, &pa_key) == 0)
952 goto try_next_key;
953 e_text = "Failed to decrypt PA-DATA";
955 free_EncryptedData(&enc_data);
956 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
957 continue;
959 free_EncryptedData(&enc_data);
960 ret = decode_PA_ENC_TS_ENC(ts_data.data,
961 ts_data.length,
963 &len);
964 krb5_data_free(&ts_data);
965 if(ret){
966 e_text = "Failed to decode PA-ENC-TS-ENC";
967 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
968 kdc_log(context, config,
969 5, "Failed to decode PA-ENC-TS_ENC -- %s",
970 client_name);
971 continue;
973 free_PA_ENC_TS_ENC(&p);
974 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
975 ret = KRB5KDC_ERR_PREAUTH_FAILED;
976 e_text = "Too large time skew";
977 kdc_log(context, config, 0,
978 "Too large time skew -- %s", client_name);
979 goto out;
981 et.flags.pre_authent = 1;
983 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
984 if (ret)
985 str = NULL;
987 kdc_log(context, config, 2,
988 "ENC-TS Pre-authentication succeeded -- %s using %s",
989 client_name, str ? str : "unknown enctype");
990 free(str);
991 break;
993 #ifdef PKINIT
994 preauth_done:
995 #endif
996 if(found_pa == 0 && config->require_preauth)
997 goto use_pa;
998 /* We come here if we found a pa-enc-timestamp, but if there
999 was some problem with it, other than too large skew */
1000 if(found_pa && et.flags.pre_authent == 0){
1001 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1002 e_text = NULL;
1003 goto out;
1005 }else if (config->require_preauth
1006 || client->flags.require_preauth
1007 || server->flags.require_preauth) {
1008 METHOD_DATA method_data;
1009 PA_DATA *pa;
1010 unsigned char *buf;
1011 size_t len;
1012 krb5_data foo_data;
1014 use_pa:
1015 method_data.len = 0;
1016 method_data.val = NULL;
1018 ret = realloc_method_data(&method_data);
1019 pa = &method_data.val[method_data.len-1];
1020 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
1021 pa->padata_value.length = 0;
1022 pa->padata_value.data = NULL;
1024 #ifdef PKINIT
1025 ret = realloc_method_data(&method_data);
1026 pa = &method_data.val[method_data.len-1];
1027 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
1028 pa->padata_value.length = 0;
1029 pa->padata_value.data = NULL;
1031 ret = realloc_method_data(&method_data);
1032 pa = &method_data.val[method_data.len-1];
1033 pa->padata_type = KRB5_PADATA_PK_AS_REQ_19;
1034 pa->padata_value.length = 0;
1035 pa->padata_value.data = NULL;
1036 #endif
1038 /* XXX check ret */
1039 if (only_older_enctype_p(req))
1040 ret = get_pa_etype_info(context, config, &method_data, client,
1041 b->etype.val, b->etype.len);
1042 /* XXX check ret */
1043 ret = get_pa_etype_info2(context, config, &method_data, client,
1044 b->etype.val, b->etype.len);
1047 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1048 free_METHOD_DATA(&method_data);
1049 foo_data.data = buf;
1050 foo_data.length = len;
1052 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1053 krb5_mk_error(context,
1054 ret,
1055 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1056 &foo_data,
1057 client_princ,
1058 server_princ,
1059 NULL,
1060 NULL,
1061 reply);
1062 free(buf);
1063 kdc_log(context, config, 0,
1064 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1065 client_name);
1066 ret = 0;
1067 goto out2;
1070 ret = find_keys(context, config,
1071 client, server, &ckey, &cetype, &skey, &setype,
1072 b->etype.val, b->etype.len);
1073 if(ret) {
1074 kdc_log(context, config, 0, "Server/client has no support for etypes");
1075 goto out;
1079 struct rk_strpool *p = NULL;
1080 char *str;
1081 int i;
1083 for (i = 0; i < b->etype.len; i++) {
1084 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1085 if (ret == 0) {
1086 p = rk_strpoolprintf(p, "%s", str);
1087 free(str);
1088 } else
1089 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1090 if (p && i + 1 < b->etype.len)
1091 p = rk_strpoolprintf(p, ", ");
1092 if (p == NULL) {
1093 kdc_log(context, config, 0, "out of meory");
1094 goto out;
1097 str = rk_strpoolcollect(p);
1098 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1099 free(str);
1102 char *cet;
1103 char *set;
1105 ret = krb5_enctype_to_string(context, cetype, &cet);
1106 if(ret == 0) {
1107 ret = krb5_enctype_to_string(context, setype, &set);
1108 if (ret == 0) {
1109 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1110 free(set);
1112 free(cet);
1114 if (ret != 0)
1115 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1119 char str[128];
1120 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1121 str, sizeof(str));
1122 if(*str)
1123 kdc_log(context, config, 2, "Requested flags: %s", str);
1127 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1128 || (f.request_anonymous && !config->allow_anonymous)) {
1129 ret = KRB5KDC_ERR_BADOPTION;
1130 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1131 goto out;
1134 rep.pvno = 5;
1135 rep.msg_type = krb_as_rep;
1136 copy_Realm(&client->principal->realm, &rep.crealm);
1137 if (f.request_anonymous)
1138 make_anonymous_principalname (&rep.cname);
1139 else
1140 _krb5_principal2principalname(&rep.cname,
1141 client->principal);
1142 rep.ticket.tkt_vno = 5;
1143 copy_Realm(&server->principal->realm, &rep.ticket.realm);
1144 _krb5_principal2principalname(&rep.ticket.sname,
1145 server->principal);
1147 et.flags.initial = 1;
1148 if(client->flags.forwardable && server->flags.forwardable)
1149 et.flags.forwardable = f.forwardable;
1150 else if (f.forwardable) {
1151 ret = KRB5KDC_ERR_POLICY;
1152 kdc_log(context, config, 0,
1153 "Ticket may not be forwardable -- %s", client_name);
1154 goto out;
1156 if(client->flags.proxiable && server->flags.proxiable)
1157 et.flags.proxiable = f.proxiable;
1158 else if (f.proxiable) {
1159 ret = KRB5KDC_ERR_POLICY;
1160 kdc_log(context, config, 0,
1161 "Ticket may not be proxiable -- %s", client_name);
1162 goto out;
1164 if(client->flags.postdate && server->flags.postdate)
1165 et.flags.may_postdate = f.allow_postdate;
1166 else if (f.allow_postdate){
1167 ret = KRB5KDC_ERR_POLICY;
1168 kdc_log(context, config, 0,
1169 "Ticket may not be postdatable -- %s", client_name);
1170 goto out;
1173 /* check for valid set of addresses */
1174 if(!check_addresses(context, config, b->addresses, from_addr)) {
1175 ret = KRB5KRB_AP_ERR_BADADDR;
1176 kdc_log(context, config, 0,
1177 "Bad address list requested -- %s", client_name);
1178 goto out;
1181 krb5_generate_random_keyblock(context, setype, &et.key);
1182 copy_PrincipalName(&rep.cname, &et.cname);
1183 copy_Realm(&rep.crealm, &et.crealm);
1186 time_t start;
1187 time_t t;
1189 start = et.authtime = kdc_time;
1191 if(f.postdated && req->req_body.from){
1192 ALLOC(et.starttime);
1193 start = *et.starttime = *req->req_body.from;
1194 et.flags.invalid = 1;
1195 et.flags.postdated = 1; /* XXX ??? */
1197 fix_time(&b->till);
1198 t = *b->till;
1200 /* be careful not overflowing */
1202 if(client->max_life)
1203 t = start + min(t - start, *client->max_life);
1204 if(server->max_life)
1205 t = start + min(t - start, *server->max_life);
1206 #if 0
1207 t = min(t, start + realm->max_life);
1208 #endif
1209 et.endtime = t;
1210 if(f.renewable_ok && et.endtime < *b->till){
1211 f.renewable = 1;
1212 if(b->rtime == NULL){
1213 ALLOC(b->rtime);
1214 *b->rtime = 0;
1216 if(*b->rtime < *b->till)
1217 *b->rtime = *b->till;
1219 if(f.renewable && b->rtime){
1220 t = *b->rtime;
1221 if(t == 0)
1222 t = MAX_TIME;
1223 if(client->max_renew)
1224 t = start + min(t - start, *client->max_renew);
1225 if(server->max_renew)
1226 t = start + min(t - start, *server->max_renew);
1227 #if 0
1228 t = min(t, start + realm->max_renew);
1229 #endif
1230 ALLOC(et.renew_till);
1231 *et.renew_till = t;
1232 et.flags.renewable = 1;
1236 if (f.request_anonymous)
1237 et.flags.anonymous = 1;
1239 if(b->addresses){
1240 ALLOC(et.caddr);
1241 copy_HostAddresses(b->addresses, et.caddr);
1244 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1245 krb5_data_zero(&et.transited.contents);
1247 copy_EncryptionKey(&et.key, &ek.key);
1249 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1250 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1251 * incapable of correctly decoding SEQUENCE OF's of zero length.
1253 * To fix this, always send at least one no-op last_req
1255 * If there's a pw_end or valid_end we will use that,
1256 * otherwise just a dummy lr.
1258 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1259 ek.last_req.len = 0;
1260 if (client->pw_end
1261 && (config->kdc_warn_pwexpire == 0
1262 || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) {
1263 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1264 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
1265 ++ek.last_req.len;
1267 if (client->valid_end) {
1268 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1269 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
1270 ++ek.last_req.len;
1272 if (ek.last_req.len == 0) {
1273 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1274 ek.last_req.val[ek.last_req.len].lr_value = 0;
1275 ++ek.last_req.len;
1277 ek.nonce = b->nonce;
1278 if (client->valid_end || client->pw_end) {
1279 ALLOC(ek.key_expiration);
1280 if (client->valid_end) {
1281 if (client->pw_end)
1282 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1283 else
1284 *ek.key_expiration = *client->valid_end;
1285 } else
1286 *ek.key_expiration = *client->pw_end;
1287 } else
1288 ek.key_expiration = NULL;
1289 ek.flags = et.flags;
1290 ek.authtime = et.authtime;
1291 if (et.starttime) {
1292 ALLOC(ek.starttime);
1293 *ek.starttime = *et.starttime;
1295 ek.endtime = et.endtime;
1296 if (et.renew_till) {
1297 ALLOC(ek.renew_till);
1298 *ek.renew_till = *et.renew_till;
1300 copy_Realm(&rep.ticket.realm, &ek.srealm);
1301 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1302 if(et.caddr){
1303 ALLOC(ek.caddr);
1304 copy_HostAddresses(et.caddr, ek.caddr);
1307 ALLOC(rep.padata);
1308 rep.padata->len = 0;
1309 rep.padata->val = NULL;
1311 reply_key = &ckey->key;
1312 #if PKINIT
1313 if (pkp) {
1314 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1315 req, req_buffer,
1316 &reply_key, rep.padata);
1317 if (ret)
1318 goto out;
1320 #endif
1322 set_salt_padata (rep.padata, ckey->salt);
1324 if (rep.padata->len == 0) {
1325 free(rep.padata);
1326 rep.padata = NULL;
1329 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1330 et.endtime, et.renew_till);
1332 ret = encode_reply(context, config,
1333 &rep, &et, &ek, setype, server->kvno, &skey->key,
1334 client->kvno, reply_key, &e_text, reply);
1335 free_EncTicketPart(&et);
1336 free_EncKDCRepPart(&ek);
1337 out:
1338 free_AS_REP(&rep);
1339 if(ret){
1340 krb5_mk_error(context,
1341 ret,
1342 e_text,
1343 NULL,
1344 client_princ,
1345 server_princ,
1346 NULL,
1347 NULL,
1348 reply);
1349 ret = 0;
1351 out2:
1352 #ifdef PKINIT
1353 if (pkp)
1354 _kdc_pk_free_client_param(context, pkp);
1355 #endif
1356 if (client_princ)
1357 krb5_free_principal(context, client_princ);
1358 free(client_name);
1359 if (server_princ)
1360 krb5_free_principal(context, server_princ);
1361 free(server_name);
1362 if(client)
1363 _kdc_free_ent(context, client);
1364 if(server)
1365 _kdc_free_ent(context, server);
1366 return ret;
1370 static krb5_error_code
1371 check_tgs_flags(krb5_context context,
1372 krb5_kdc_configuration *config,
1373 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1375 KDCOptions f = b->kdc_options;
1377 if(f.validate){
1378 if(!tgt->flags.invalid || tgt->starttime == NULL){
1379 kdc_log(context, config, 0,
1380 "Bad request to validate ticket");
1381 return KRB5KDC_ERR_BADOPTION;
1383 if(*tgt->starttime > kdc_time){
1384 kdc_log(context, config, 0,
1385 "Early request to validate ticket");
1386 return KRB5KRB_AP_ERR_TKT_NYV;
1388 /* XXX tkt = tgt */
1389 et->flags.invalid = 0;
1390 }else if(tgt->flags.invalid){
1391 kdc_log(context, config, 0,
1392 "Ticket-granting ticket has INVALID flag set");
1393 return KRB5KRB_AP_ERR_TKT_INVALID;
1396 if(f.forwardable){
1397 if(!tgt->flags.forwardable){
1398 kdc_log(context, config, 0,
1399 "Bad request for forwardable ticket");
1400 return KRB5KDC_ERR_BADOPTION;
1402 et->flags.forwardable = 1;
1404 if(f.forwarded){
1405 if(!tgt->flags.forwardable){
1406 kdc_log(context, config, 0,
1407 "Request to forward non-forwardable ticket");
1408 return KRB5KDC_ERR_BADOPTION;
1410 et->flags.forwarded = 1;
1411 et->caddr = b->addresses;
1413 if(tgt->flags.forwarded)
1414 et->flags.forwarded = 1;
1416 if(f.proxiable){
1417 if(!tgt->flags.proxiable){
1418 kdc_log(context, config, 0,
1419 "Bad request for proxiable ticket");
1420 return KRB5KDC_ERR_BADOPTION;
1422 et->flags.proxiable = 1;
1424 if(f.proxy){
1425 if(!tgt->flags.proxiable){
1426 kdc_log(context, config, 0,
1427 "Request to proxy non-proxiable ticket");
1428 return KRB5KDC_ERR_BADOPTION;
1430 et->flags.proxy = 1;
1431 et->caddr = b->addresses;
1433 if(tgt->flags.proxy)
1434 et->flags.proxy = 1;
1436 if(f.allow_postdate){
1437 if(!tgt->flags.may_postdate){
1438 kdc_log(context, config, 0,
1439 "Bad request for post-datable ticket");
1440 return KRB5KDC_ERR_BADOPTION;
1442 et->flags.may_postdate = 1;
1444 if(f.postdated){
1445 if(!tgt->flags.may_postdate){
1446 kdc_log(context, config, 0,
1447 "Bad request for postdated ticket");
1448 return KRB5KDC_ERR_BADOPTION;
1450 if(b->from)
1451 *et->starttime = *b->from;
1452 et->flags.postdated = 1;
1453 et->flags.invalid = 1;
1454 }else if(b->from && *b->from > kdc_time + context->max_skew){
1455 kdc_log(context, config, 0, "Ticket cannot be postdated");
1456 return KRB5KDC_ERR_CANNOT_POSTDATE;
1459 if(f.renewable){
1460 if(!tgt->flags.renewable){
1461 kdc_log(context, config, 0,
1462 "Bad request for renewable ticket");
1463 return KRB5KDC_ERR_BADOPTION;
1465 et->flags.renewable = 1;
1466 ALLOC(et->renew_till);
1467 fix_time(&b->rtime);
1468 *et->renew_till = *b->rtime;
1470 if(f.renew){
1471 time_t old_life;
1472 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1473 kdc_log(context, config, 0,
1474 "Request to renew non-renewable ticket");
1475 return KRB5KDC_ERR_BADOPTION;
1477 old_life = tgt->endtime;
1478 if(tgt->starttime)
1479 old_life -= *tgt->starttime;
1480 else
1481 old_life -= tgt->authtime;
1482 et->endtime = *et->starttime + old_life;
1483 if (et->renew_till != NULL)
1484 et->endtime = min(*et->renew_till, et->endtime);
1487 /* checks for excess flags */
1488 if(f.request_anonymous && !config->allow_anonymous){
1489 kdc_log(context, config, 0,
1490 "Request for anonymous ticket");
1491 return KRB5KDC_ERR_BADOPTION;
1493 return 0;
1496 static krb5_error_code
1497 fix_transited_encoding(krb5_context context,
1498 krb5_kdc_configuration *config,
1499 krb5_boolean check_policy,
1500 TransitedEncoding *tr,
1501 EncTicketPart *et,
1502 const char *client_realm,
1503 const char *server_realm,
1504 const char *tgt_realm)
1506 krb5_error_code ret = 0;
1507 char **realms, **tmp;
1508 int num_realms;
1509 int i;
1511 if(tr->tr_type != DOMAIN_X500_COMPRESS) {
1512 kdc_log(context, config, 0,
1513 "Unknown transited type: %u", tr->tr_type);
1514 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1517 ret = krb5_domain_x500_decode(context,
1518 tr->contents,
1519 &realms,
1520 &num_realms,
1521 client_realm,
1522 server_realm);
1523 if(ret){
1524 krb5_warn(context, ret,
1525 "Decoding transited encoding");
1526 return ret;
1528 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1529 /* not us, so add the previous realm to transited set */
1530 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1531 ret = ERANGE;
1532 goto free_realms;
1534 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1535 if(tmp == NULL){
1536 ret = ENOMEM;
1537 goto free_realms;
1539 realms = tmp;
1540 realms[num_realms] = strdup(tgt_realm);
1541 if(realms[num_realms] == NULL){
1542 ret = ENOMEM;
1543 goto free_realms;
1545 num_realms++;
1547 if(num_realms == 0) {
1548 if(strcmp(client_realm, server_realm))
1549 kdc_log(context, config, 0,
1550 "cross-realm %s -> %s", client_realm, server_realm);
1551 } else {
1552 size_t l = 0;
1553 char *rs;
1554 for(i = 0; i < num_realms; i++)
1555 l += strlen(realms[i]) + 2;
1556 rs = malloc(l);
1557 if(rs != NULL) {
1558 *rs = '\0';
1559 for(i = 0; i < num_realms; i++) {
1560 if(i > 0)
1561 strlcat(rs, ", ", l);
1562 strlcat(rs, realms[i], l);
1564 kdc_log(context, config, 0,
1565 "cross-realm %s -> %s via [%s]",
1566 client_realm, server_realm, rs);
1567 free(rs);
1570 if(check_policy) {
1571 ret = krb5_check_transited(context, client_realm,
1572 server_realm,
1573 realms, num_realms, NULL);
1574 if(ret) {
1575 krb5_warn(context, ret, "cross-realm %s -> %s",
1576 client_realm, server_realm);
1577 goto free_realms;
1579 et->flags.transited_policy_checked = 1;
1581 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1582 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1583 if(ret)
1584 krb5_warn(context, ret, "Encoding transited encoding");
1585 free_realms:
1586 for(i = 0; i < num_realms; i++)
1587 free(realms[i]);
1588 free(realms);
1589 return ret;
1593 static krb5_error_code
1594 tgs_make_reply(krb5_context context,
1595 krb5_kdc_configuration *config,
1596 KDC_REQ_BODY *b,
1597 EncTicketPart *tgt,
1598 EncTicketPart *adtkt,
1599 AuthorizationData *auth_data,
1600 hdb_entry *server,
1601 hdb_entry *client,
1602 krb5_principal client_principal,
1603 hdb_entry *krbtgt,
1604 EncryptionKey *tgtkey,
1605 krb5_enctype cetype,
1606 const char **e_text,
1607 krb5_data *reply)
1609 KDC_REP rep;
1610 EncKDCRepPart ek;
1611 EncTicketPart et;
1612 KDCOptions f = b->kdc_options;
1613 krb5_error_code ret;
1614 krb5_enctype etype;
1615 Key *skey;
1616 EncryptionKey *ekey;
1618 if(adtkt) {
1619 int i;
1620 krb5_keytype kt;
1621 ekey = &adtkt->key;
1622 for(i = 0; i < b->etype.len; i++){
1623 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1624 if(ret)
1625 continue;
1626 if(adtkt->key.keytype == kt)
1627 break;
1629 if(i == b->etype.len)
1630 return KRB5KDC_ERR_ETYPE_NOSUPP;
1631 etype = b->etype.val[i];
1632 }else{
1633 ret = find_keys(context, config,
1634 NULL, server, NULL, NULL, &skey, &etype,
1635 b->etype.val, b->etype.len);
1636 if(ret) {
1637 kdc_log(context, config, 0, "Server has no support for etypes");
1638 return ret;
1640 ekey = &skey->key;
1643 memset(&rep, 0, sizeof(rep));
1644 memset(&et, 0, sizeof(et));
1645 memset(&ek, 0, sizeof(ek));
1647 rep.pvno = 5;
1648 rep.msg_type = krb_tgs_rep;
1650 et.authtime = tgt->authtime;
1651 fix_time(&b->till);
1652 et.endtime = min(tgt->endtime, *b->till);
1653 ALLOC(et.starttime);
1654 *et.starttime = kdc_time;
1656 ret = check_tgs_flags(context, config, b, tgt, &et);
1657 if(ret)
1658 goto out;
1660 /* We should check the transited encoding if:
1661 1) the request doesn't ask not to be checked
1662 2) globally enforcing a check
1663 3) principal requires checking
1664 4) we allow non-check per-principal, but principal isn't marked as allowing this
1665 5) we don't globally allow this
1668 #define GLOBAL_FORCE_TRANSITED_CHECK \
1669 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1670 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1671 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1672 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1673 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1675 /* these will consult the database in future release */
1676 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1677 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1679 ret = fix_transited_encoding(context, config,
1680 !f.disable_transited_check ||
1681 GLOBAL_FORCE_TRANSITED_CHECK ||
1682 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1683 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1684 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1685 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1686 &tgt->transited, &et,
1687 *krb5_princ_realm(context, client_principal),
1688 *krb5_princ_realm(context, server->principal),
1689 *krb5_princ_realm(context, krbtgt->principal));
1690 if(ret)
1691 goto out;
1693 copy_Realm(krb5_princ_realm(context, server->principal),
1694 &rep.ticket.realm);
1695 _krb5_principal2principalname(&rep.ticket.sname, server->principal);
1696 copy_Realm(&tgt->crealm, &rep.crealm);
1697 if (f.request_anonymous)
1698 make_anonymous_principalname (&tgt->cname);
1699 else
1700 copy_PrincipalName(&tgt->cname, &rep.cname);
1701 rep.ticket.tkt_vno = 5;
1703 ek.caddr = et.caddr;
1704 if(et.caddr == NULL)
1705 et.caddr = tgt->caddr;
1708 time_t life;
1709 life = et.endtime - *et.starttime;
1710 if(client && client->max_life)
1711 life = min(life, *client->max_life);
1712 if(server->max_life)
1713 life = min(life, *server->max_life);
1714 et.endtime = *et.starttime + life;
1716 if(f.renewable_ok && tgt->flags.renewable &&
1717 et.renew_till == NULL && et.endtime < *b->till){
1718 et.flags.renewable = 1;
1719 ALLOC(et.renew_till);
1720 *et.renew_till = *b->till;
1722 if(et.renew_till){
1723 time_t renew;
1724 renew = *et.renew_till - et.authtime;
1725 if(client && client->max_renew)
1726 renew = min(renew, *client->max_renew);
1727 if(server->max_renew)
1728 renew = min(renew, *server->max_renew);
1729 *et.renew_till = et.authtime + renew;
1732 if(et.renew_till){
1733 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1734 *et.starttime = min(*et.starttime, *et.renew_till);
1735 et.endtime = min(et.endtime, *et.renew_till);
1738 *et.starttime = min(*et.starttime, et.endtime);
1740 if(*et.starttime == et.endtime){
1741 ret = KRB5KDC_ERR_NEVER_VALID;
1742 goto out;
1744 if(et.renew_till && et.endtime == *et.renew_till){
1745 free(et.renew_till);
1746 et.renew_till = NULL;
1747 et.flags.renewable = 0;
1750 et.flags.pre_authent = tgt->flags.pre_authent;
1751 et.flags.hw_authent = tgt->flags.hw_authent;
1752 et.flags.anonymous = tgt->flags.anonymous;
1753 et.flags.ok_as_delegate = server->flags.ok_as_delegate;
1755 #ifdef _SAMBA_BUILD_
1759 unsigned char *buf;
1760 size_t buf_size;
1761 size_t len;
1763 krb5_data pac;
1764 AD_IF_RELEVANT *if_relevant;
1765 ALLOC(if_relevant);
1766 if_relevant->len = 1;
1767 if_relevant->val = malloc(sizeof(*if_relevant->val));
1768 if_relevant->val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
1769 if_relevant->val[0].ad_data.data = NULL;
1770 if_relevant->val[0].ad_data.length = 0;
1772 /* Get PAC from Samba */
1773 ret = samba_get_pac(context, config,
1774 client->principal,
1775 tgtkey,
1776 ekey,
1777 &pac);
1778 if (ret) {
1779 free_AuthorizationData(if_relevant);
1780 goto out;
1783 /* pac.data will be freed with this */
1784 if_relevant->val[0].ad_data.data = pac.data;
1785 if_relevant->val[0].ad_data.length = pac.length;
1787 ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1789 auth_data = NULL;
1790 ALLOC(auth_data);
1791 auth_data->len = 1;
1792 auth_data->val = malloc(sizeof(*auth_data->val));
1793 auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1794 auth_data->val[0].ad_data.length = len;
1795 auth_data->val[0].ad_data.data = buf;
1796 if (ret) {
1797 goto out;
1801 #endif
1802 /* XXX Check enc-authorization-data */
1803 et.authorization_data = auth_data;
1805 krb5_generate_random_keyblock(context, etype, &et.key);
1806 et.crealm = tgt->crealm;
1807 et.cname = tgt->cname;
1809 ek.key = et.key;
1810 /* MIT must have at least one last_req */
1811 ek.last_req.len = 1;
1812 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1813 ek.nonce = b->nonce;
1814 ek.flags = et.flags;
1815 ek.authtime = et.authtime;
1816 ek.starttime = et.starttime;
1817 ek.endtime = et.endtime;
1818 ek.renew_till = et.renew_till;
1819 ek.srealm = rep.ticket.realm;
1820 ek.sname = rep.ticket.sname;
1822 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1823 et.endtime, et.renew_till);
1825 /* It is somewhat unclear where the etype in the following
1826 encryption should come from. What we have is a session
1827 key in the passed tgt, and a list of preferred etypes
1828 *for the new ticket*. Should we pick the best possible
1829 etype, given the keytype in the tgt, or should we look
1830 at the etype list here as well? What if the tgt
1831 session key is DES3 and we want a ticket with a (say)
1832 CAST session key. Should the DES3 etype be added to the
1833 etype list, even if we don't want a session key with
1834 DES3? */
1835 ret = encode_reply(context, config,
1836 &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1837 0, &tgt->key, e_text, reply);
1838 out:
1839 free_TGS_REP(&rep);
1840 free_TransitedEncoding(&et.transited);
1841 if(et.starttime)
1842 free(et.starttime);
1843 if(et.renew_till)
1844 free(et.renew_till);
1845 free_LastReq(&ek.last_req);
1846 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1847 free_EncryptionKey(&et.key);
1848 return ret;
1851 static krb5_error_code
1852 tgs_check_authenticator(krb5_context context,
1853 krb5_kdc_configuration *config,
1854 krb5_auth_context ac,
1855 KDC_REQ_BODY *b,
1856 const char **e_text,
1857 krb5_keyblock *key)
1859 krb5_authenticator auth;
1860 size_t len;
1861 unsigned char *buf;
1862 size_t buf_size;
1863 krb5_error_code ret;
1864 krb5_crypto crypto;
1866 krb5_auth_con_getauthenticator(context, ac, &auth);
1867 if(auth->cksum == NULL){
1868 kdc_log(context, config, 0, "No authenticator in request");
1869 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1870 goto out;
1873 * according to RFC1510 it doesn't need to be keyed,
1874 * but according to the latest draft it needs to.
1876 if (
1877 #if 0
1878 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1880 #endif
1881 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1882 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1883 auth->cksum->cksumtype);
1884 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1885 goto out;
1888 /* XXX should not re-encode this */
1889 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1890 if(ret){
1891 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
1892 krb5_get_err_text(context, ret));
1893 goto out;
1895 if(buf_size != len) {
1896 free(buf);
1897 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1898 *e_text = "KDC internal error";
1899 ret = KRB5KRB_ERR_GENERIC;
1900 goto out;
1902 ret = krb5_crypto_init(context, key, 0, &crypto);
1903 if (ret) {
1904 free(buf);
1905 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1906 krb5_get_err_text(context, ret));
1907 goto out;
1909 ret = krb5_verify_checksum(context,
1910 crypto,
1911 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1912 buf,
1913 len,
1914 auth->cksum);
1915 free(buf);
1916 krb5_crypto_destroy(context, crypto);
1917 if(ret){
1918 kdc_log(context, config, 0,
1919 "Failed to verify authenticator checksum: %s",
1920 krb5_get_err_text(context, ret));
1922 out:
1923 free_Authenticator(auth);
1924 free(auth);
1925 return ret;
1929 * return the realm of a krbtgt-ticket or NULL
1932 static Realm
1933 get_krbtgt_realm(const PrincipalName *p)
1935 if(p->name_string.len == 2
1936 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1937 return p->name_string.val[1];
1938 else
1939 return NULL;
1942 static const char *
1943 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1945 const char *new_realm = krb5_config_get_string(context,
1946 NULL,
1947 "capaths",
1948 crealm,
1949 srealm,
1950 NULL);
1951 return new_realm;
1955 static krb5_boolean
1956 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1958 if(server->name.name_type != KRB5_NT_SRV_INST ||
1959 server->name.name_string.len != 2)
1960 return FALSE;
1962 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1963 FALSE, realms) == 0;
1966 static krb5_error_code
1967 tgs_rep2(krb5_context context,
1968 krb5_kdc_configuration *config,
1969 KDC_REQ_BODY *b,
1970 PA_DATA *tgs_req,
1971 krb5_data *reply,
1972 const char *from,
1973 const struct sockaddr *from_addr,
1974 time_t **csec,
1975 int **cusec)
1977 krb5_ap_req ap_req;
1978 krb5_error_code ret;
1979 krb5_principal princ;
1980 krb5_auth_context ac = NULL;
1981 krb5_ticket *ticket = NULL;
1982 krb5_flags ap_req_options;
1983 krb5_flags verify_ap_req_flags;
1984 const char *e_text = NULL;
1985 krb5_crypto crypto;
1987 hdb_entry *krbtgt = NULL;
1988 EncTicketPart *tgt;
1989 Key *tkey;
1990 krb5_enctype cetype;
1991 krb5_principal cp = NULL;
1992 krb5_principal sp = NULL;
1993 AuthorizationData *auth_data = NULL;
1995 *csec = NULL;
1996 *cusec = NULL;
1998 memset(&ap_req, 0, sizeof(ap_req));
1999 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2000 if(ret){
2001 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
2002 krb5_get_err_text(context, ret));
2003 goto out2;
2006 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2007 /* XXX check for ticket.sname == req.sname */
2008 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2009 ret = KRB5KDC_ERR_POLICY; /* ? */
2010 goto out2;
2013 _krb5_principalname2krb5_principal(&princ,
2014 ap_req.ticket.sname,
2015 ap_req.ticket.realm);
2017 ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
2019 if(ret) {
2020 char *p;
2021 ret = krb5_unparse_name(context, princ, &p);
2022 if (ret != 0)
2023 p = "<unparse_name failed>";
2024 krb5_free_principal(context, princ);
2025 kdc_log(context, config, 0,
2026 "Ticket-granting ticket not found in database: %s: %s",
2027 p, krb5_get_err_text(context, ret));
2028 if (ret == 0)
2029 free(p);
2030 ret = KRB5KRB_AP_ERR_NOT_US;
2031 goto out2;
2034 if(ap_req.ticket.enc_part.kvno &&
2035 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
2036 char *p;
2038 ret = krb5_unparse_name (context, princ, &p);
2039 krb5_free_principal(context, princ);
2040 if (ret != 0)
2041 p = "<unparse_name failed>";
2042 kdc_log(context, config, 0,
2043 "Ticket kvno = %d, DB kvno = %d (%s)",
2044 *ap_req.ticket.enc_part.kvno,
2045 krbtgt->kvno,
2047 if (ret == 0)
2048 free (p);
2049 ret = KRB5KRB_AP_ERR_BADKEYVER;
2050 goto out2;
2053 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2054 if(ret){
2055 char *str;
2056 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2057 kdc_log(context, config, 0,
2058 "No server key found for %s", str);
2059 free(str);
2060 ret = KRB5KRB_AP_ERR_BADKEYVER;
2061 goto out2;
2064 if (b->kdc_options.validate)
2065 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2066 else
2067 verify_ap_req_flags = 0;
2069 ret = krb5_verify_ap_req2(context,
2070 &ac,
2071 &ap_req,
2072 princ,
2073 &tkey->key,
2074 verify_ap_req_flags,
2075 &ap_req_options,
2076 &ticket,
2077 KRB5_KU_TGS_REQ_AUTH);
2079 krb5_free_principal(context, princ);
2080 if(ret) {
2081 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2082 krb5_get_err_text(context, ret));
2083 goto out2;
2087 krb5_authenticator auth;
2089 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2090 if (ret == 0) {
2091 *csec = malloc(sizeof(**csec));
2092 if (*csec == NULL) {
2093 krb5_free_authenticator(context, &auth);
2094 kdc_log(context, config, 0, "malloc failed");
2095 goto out2;
2097 **csec = auth->ctime;
2098 *cusec = malloc(sizeof(**cusec));
2099 if (*cusec == NULL) {
2100 krb5_free_authenticator(context, &auth);
2101 kdc_log(context, config, 0, "malloc failed");
2102 goto out2;
2104 **csec = auth->cusec;
2105 krb5_free_authenticator(context, &auth);
2109 cetype = ap_req.authenticator.etype;
2111 tgt = &ticket->ticket;
2113 ret = tgs_check_authenticator(context, config,
2114 ac, b, &e_text, &tgt->key);
2115 if (ret) {
2116 krb5_auth_con_free(context, ac);
2117 goto out2;
2120 if (b->enc_authorization_data) {
2121 krb5_keyblock *subkey;
2122 krb5_data ad;
2123 ret = krb5_auth_con_getremotesubkey(context,
2125 &subkey);
2126 if(ret){
2127 krb5_auth_con_free(context, ac);
2128 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2129 krb5_get_err_text(context, ret));
2130 goto out2;
2132 if(subkey == NULL){
2133 ret = krb5_auth_con_getkey(context, ac, &subkey);
2134 if(ret) {
2135 krb5_auth_con_free(context, ac);
2136 kdc_log(context, config, 0, "Failed to get session key: %s",
2137 krb5_get_err_text(context, ret));
2138 goto out2;
2141 if(subkey == NULL){
2142 krb5_auth_con_free(context, ac);
2143 kdc_log(context, config, 0,
2144 "Failed to get key for enc-authorization-data");
2145 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2146 goto out2;
2148 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2149 if (ret) {
2150 krb5_auth_con_free(context, ac);
2151 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2152 krb5_get_err_text(context, ret));
2153 goto out2;
2155 ret = krb5_decrypt_EncryptedData (context,
2156 crypto,
2157 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2158 b->enc_authorization_data,
2159 &ad);
2160 krb5_crypto_destroy(context, crypto);
2161 if(ret){
2162 krb5_auth_con_free(context, ac);
2163 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2164 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2165 goto out2;
2167 krb5_free_keyblock(context, subkey);
2168 ALLOC(auth_data);
2169 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2170 if(ret){
2171 krb5_auth_con_free(context, ac);
2172 free(auth_data);
2173 auth_data = NULL;
2174 kdc_log(context, config, 0, "Failed to decode authorization data");
2175 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2176 goto out2;
2180 krb5_auth_con_free(context, ac);
2183 PrincipalName *s;
2184 Realm r;
2185 char *spn = NULL, *cpn = NULL;
2186 hdb_entry *server = NULL, *client = NULL;
2187 int nloop = 0;
2188 EncTicketPart adtkt;
2189 char opt_str[128];
2191 s = b->sname;
2192 r = b->realm;
2193 if(b->kdc_options.enc_tkt_in_skey){
2194 Ticket *t;
2195 hdb_entry *uu;
2196 krb5_principal p;
2197 Key *uukey;
2199 if(b->additional_tickets == NULL ||
2200 b->additional_tickets->len == 0){
2201 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2202 kdc_log(context, config, 0,
2203 "No second ticket present in request");
2204 goto out;
2206 t = &b->additional_tickets->val[0];
2207 if(!get_krbtgt_realm(&t->sname)){
2208 kdc_log(context, config, 0,
2209 "Additional ticket is not a ticket-granting ticket");
2210 ret = KRB5KDC_ERR_POLICY;
2211 goto out2;
2213 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2214 ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2215 krb5_free_principal(context, p);
2216 if(ret){
2217 if (ret == HDB_ERR_NOENTRY)
2218 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2219 goto out;
2221 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2222 if(ret){
2223 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2224 goto out;
2226 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2228 if(ret)
2229 goto out;
2230 s = &adtkt.cname;
2231 r = adtkt.crealm;
2234 _krb5_principalname2krb5_principal(&sp, *s, r);
2235 ret = krb5_unparse_name(context, sp, &spn);
2236 if (ret)
2237 goto out;
2238 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2239 ret = krb5_unparse_name(context, cp, &cpn);
2240 if (ret)
2241 goto out;
2242 unparse_flags (KDCOptions2int(b->kdc_options),
2243 asn1_KDCOptions_units(),
2244 opt_str, sizeof(opt_str));
2245 if(*opt_str)
2246 kdc_log(context, config, 0,
2247 "TGS-REQ %s from %s for %s [%s]",
2248 cpn, from, spn, opt_str);
2249 else
2250 kdc_log(context, config, 0,
2251 "TGS-REQ %s from %s for %s", cpn, from, spn);
2252 server_lookup:
2253 ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2255 if(ret){
2256 const char *new_rlm;
2257 Realm req_rlm;
2258 krb5_realm *realms;
2260 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2261 if(nloop++ < 2) {
2262 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2263 if(new_rlm) {
2264 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2265 req_rlm, new_rlm);
2266 krb5_free_principal(context, sp);
2267 free(spn);
2268 krb5_make_principal(context, &sp, r,
2269 KRB5_TGS_NAME, new_rlm, NULL);
2270 ret = krb5_unparse_name(context, sp, &spn);
2271 if (ret)
2272 goto out;
2273 goto server_lookup;
2276 } else if(need_referral(context, sp, &realms)) {
2277 if (strcmp(realms[0], sp->realm) != 0) {
2278 kdc_log(context, config, 5,
2279 "Returning a referral to realm %s for "
2280 "server %s that was not found",
2281 realms[0], spn);
2282 krb5_free_principal(context, sp);
2283 free(spn);
2284 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2285 realms[0], NULL);
2286 ret = krb5_unparse_name(context, sp, &spn);
2287 if (ret)
2288 goto out;
2289 krb5_free_host_realm(context, realms);
2290 goto server_lookup;
2292 krb5_free_host_realm(context, realms);
2294 kdc_log(context, config, 0,
2295 "Server not found in database: %s: %s", spn,
2296 krb5_get_err_text(context, ret));
2297 if (ret == HDB_ERR_NOENTRY)
2298 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2299 goto out;
2302 ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2303 if(ret)
2304 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2305 cpn, krb5_get_err_text(context, ret));
2306 #if 0
2307 /* XXX check client only if same realm as krbtgt-instance */
2308 if(ret){
2309 kdc_log(context, config, 0,
2310 "Client not found in database: %s: %s",
2311 cpn, krb5_get_err_text(context, ret));
2312 if (ret == HDB_ERR_NOENTRY)
2313 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2314 goto out;
2316 #endif
2318 if(strcmp(krb5_principal_get_realm(context, sp),
2319 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2320 char *tpn;
2321 ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2322 kdc_log(context, config, 0,
2323 "Request with wrong krbtgt: %s",
2324 (ret == 0) ? tpn : "<unknown>");
2325 if(ret == 0)
2326 free(tpn);
2327 ret = KRB5KRB_AP_ERR_NOT_US;
2328 goto out;
2332 ret = _kdc_check_flags(context, config,
2333 client, cpn,
2334 server, spn,
2335 FALSE);
2336 if(ret)
2337 goto out;
2339 if((b->kdc_options.validate || b->kdc_options.renew) &&
2340 !krb5_principal_compare(context,
2341 krbtgt->principal,
2342 server->principal)){
2343 kdc_log(context, config, 0, "Inconsistent request.");
2344 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2345 goto out;
2348 /* check for valid set of addresses */
2349 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2350 ret = KRB5KRB_AP_ERR_BADADDR;
2351 kdc_log(context, config, 0, "Request from wrong address");
2352 goto out;
2355 ret = tgs_make_reply(context, config,
2357 tgt,
2358 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2359 auth_data,
2360 server,
2361 client,
2362 cp,
2363 krbtgt,
2364 &tkey->key,
2365 cetype,
2366 &e_text,
2367 reply);
2369 out:
2370 free(spn);
2371 free(cpn);
2373 if(server)
2374 _kdc_free_ent(context, server);
2375 if(client)
2376 _kdc_free_ent(context, client);
2378 out2:
2379 if(ret) {
2380 krb5_mk_error(context,
2381 ret,
2382 e_text,
2383 NULL,
2386 NULL,
2387 NULL,
2388 reply);
2389 free(*csec);
2390 free(*cusec);
2391 *csec = NULL;
2392 *cusec = NULL;
2394 krb5_free_principal(context, cp);
2395 krb5_free_principal(context, sp);
2396 if (ticket)
2397 krb5_free_ticket(context, ticket);
2398 free_AP_REQ(&ap_req);
2399 if(auth_data){
2400 free_AuthorizationData(auth_data);
2401 free(auth_data);
2404 if(krbtgt)
2405 _kdc_free_ent(context, krbtgt);
2407 return ret;
2411 krb5_error_code
2412 _kdc_tgs_rep(krb5_context context,
2413 krb5_kdc_configuration *config,
2414 KDC_REQ *req,
2415 krb5_data *data,
2416 const char *from,
2417 struct sockaddr *from_addr)
2419 krb5_error_code ret;
2420 int i = 0;
2421 PA_DATA *tgs_req = NULL;
2422 time_t *csec = NULL;
2423 int *cusec = NULL;
2425 if(req->padata == NULL){
2426 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2427 kdc_log(context, config, 0,
2428 "TGS-REQ from %s without PA-DATA", from);
2429 goto out;
2432 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2434 if(tgs_req == NULL){
2435 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2437 kdc_log(context, config, 0,
2438 "TGS-REQ from %s without PA-TGS-REQ", from);
2439 goto out;
2441 ret = tgs_rep2(context, config,
2442 &req->req_body, tgs_req, data, from, from_addr,
2443 &csec, &cusec);
2444 out:
2445 if(ret && data->data == NULL){
2446 krb5_mk_error(context,
2447 ret,
2448 NULL,
2449 NULL,
2450 NULL,
2451 NULL,
2452 csec,
2453 cusec,
2454 data);
2456 free(csec);
2457 free(cusec);
2458 return 0;