2 * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
36 RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
47 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
51 realloc_method_data(METHOD_DATA *md)
54 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
63 set_salt_padata (METHOD_DATA *md, Salt *salt)
66 realloc_method_data(md);
67 md->val[md->len - 1].padata_type = salt->type;
68 copy_octet_string(&salt->salt,
69 &md->val[md->len - 1].padata_value);
74 find_padata(KDC_REQ *req, int *start, int type)
76 while(*start < req->padata->len){
78 if(req->padata->val[*start - 1].padata_type == type)
79 return &req->padata->val[*start - 1];
85 * return the first appropriate key of `princ' in `ret_key'. Look for
86 * all the etypes in (`etypes', `len'), stopping as soon as we find
87 * one, but preferring one that has default salt
90 static krb5_error_code
91 find_etype(krb5_context context, hdb_entry *princ,
92 krb5_enctype *etypes, unsigned len,
93 Key **ret_key, krb5_enctype *ret_etype)
96 krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
98 for(i = 0; ret != 0 && i < len ; i++) {
101 if (krb5_enctype_valid(context, etypes[i]) != 0)
104 while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
105 if (key->key.keyvalue.length == 0) {
106 ret = KRB5KDC_ERR_NULL_KEY;
110 *ret_etype = etypes[i];
112 if (key->salt == NULL)
119 static krb5_error_code
120 find_keys(krb5_context context,
121 krb5_kdc_configuration *config,
125 krb5_enctype *cetype,
127 krb5_enctype *setype,
128 krb5_enctype *etypes,
131 char unparse_name[] = "krb5_unparse_name failed";
136 /* find client key */
137 ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
139 if (krb5_unparse_name(context, client->principal, &name) != 0)
141 kdc_log(context, config, 0,
142 "Client (%s) has no support for etypes", name);
143 if (name != unparse_name)
150 /* find server key */
151 ret = find_etype(context, server, etypes, num_etypes, skey, setype);
153 if (krb5_unparse_name(context, server->principal, &name) != 0)
155 kdc_log(context, config, 0,
156 "Server (%s) has no support for etypes", name);
157 if (name != unparse_name)
165 static krb5_error_code
166 make_anonymous_principalname (PrincipalName *pn)
168 pn->name_type = KRB5_NT_PRINCIPAL;
169 pn->name_string.len = 1;
170 pn->name_string.val = malloc(sizeof(*pn->name_string.val));
171 if (pn->name_string.val == NULL)
173 pn->name_string.val[0] = strdup("anonymous");
174 if (pn->name_string.val[0] == NULL) {
175 free(pn->name_string.val);
176 pn->name_string.val = NULL;
183 log_timestamp(krb5_context context,
184 krb5_kdc_configuration *config,
186 KerberosTime authtime, KerberosTime *starttime,
187 KerberosTime endtime, KerberosTime *renew_till)
189 char authtime_str[100], starttime_str[100],
190 endtime_str[100], renewtime_str[100];
192 krb5_format_time(context, authtime,
193 authtime_str, sizeof(authtime_str), TRUE);
195 krb5_format_time(context, *starttime,
196 starttime_str, sizeof(starttime_str), TRUE);
198 strlcpy(starttime_str, "unset", sizeof(starttime_str));
199 krb5_format_time(context, endtime,
200 endtime_str, sizeof(endtime_str), TRUE);
202 krb5_format_time(context, *renew_till,
203 renewtime_str, sizeof(renewtime_str), TRUE);
205 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
207 kdc_log(context, config, 5,
208 "%s authtime: %s starttime: %s endtime: %s renew till: %s",
209 type, authtime_str, starttime_str, endtime_str, renewtime_str);
212 static krb5_error_code
213 encode_reply(krb5_context context,
214 krb5_kdc_configuration *config,
215 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
217 int skvno, EncryptionKey *skey,
218 int ckvno, EncryptionKey *ckey,
228 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
230 kdc_log(context, config, 0, "Failed to encode ticket: %s",
231 krb5_get_err_text(context, ret));
234 if(buf_size != len) {
236 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
237 *e_text = "KDC internal error";
238 return KRB5KRB_ERR_GENERIC;
241 ret = krb5_crypto_init(context, skey, etype, &crypto);
244 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
245 krb5_get_err_text(context, ret));
249 ret = krb5_encrypt_EncryptedData(context,
255 &rep->ticket.enc_part);
257 krb5_crypto_destroy(context, crypto);
259 kdc_log(context, config, 0, "Failed to encrypt data: %s",
260 krb5_get_err_text(context, ret));
264 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
265 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
267 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
269 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
270 krb5_get_err_text(context, ret));
273 if(buf_size != len) {
275 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
276 *e_text = "KDC internal error";
277 return KRB5KRB_ERR_GENERIC;
279 ret = krb5_crypto_init(context, ckey, 0, &crypto);
282 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
283 krb5_get_err_text(context, ret));
286 if(rep->msg_type == krb_as_rep) {
287 krb5_encrypt_EncryptedData(context,
289 KRB5_KU_AS_REP_ENC_PART,
295 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
297 krb5_encrypt_EncryptedData(context,
299 KRB5_KU_TGS_REP_ENC_PART_SESSION,
305 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
307 krb5_crypto_destroy(context, crypto);
309 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
310 krb5_get_err_text(context, ret));
313 if(buf_size != len) {
315 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
316 *e_text = "KDC internal error";
317 return KRB5KRB_ERR_GENERIC;
320 reply->length = buf_size;
324 static krb5_error_code
325 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
327 ent->etype = key->key.keytype;
330 ALLOC(ent->salttype);
332 if(key->salt->type == hdb_pw_salt)
333 *ent->salttype = 0; /* or 1? or NULL? */
334 else if(key->salt->type == hdb_afs3_salt)
337 kdc_log(context, config, 0, "unknown salt-type: %d",
339 return KRB5KRB_ERR_GENERIC;
341 /* according to `the specs', we can't send a salt if
342 we have AFS3 salted key, but that requires that you
343 *know* what cell you are using (e.g by assuming
344 that the cell is the same as the realm in lower
347 ALLOC(ent->salttype);
348 *ent->salttype = key->salt->type;
351 * We shouldn't sent salttype since its incompatible with the
352 * specification and its break windows clients. The afs
353 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
354 * implemented in Heimdal 0.7 and later.
356 ent->salttype = NULL;
358 krb5_copy_data(context, &key->salt->salt,
361 /* we return no salt type at all, as that should indicate
362 * the default salt type and make everybody happy. some
363 * systems (like w2k) dislike being told the salt type
366 ent->salttype = NULL;
372 static krb5_error_code
373 get_pa_etype_info(krb5_context context,
374 krb5_kdc_configuration *config,
375 METHOD_DATA *md, hdb_entry *client,
376 ENCTYPE *etypes, unsigned int etypes_len)
378 krb5_error_code ret = 0;
386 pa.len = client->keys.len;
387 if(pa.len > UINT_MAX/sizeof(*pa.val))
389 pa.val = malloc(pa.len * sizeof(*pa.val));
392 memset(pa.val, 0, pa.len * sizeof(*pa.val));
394 for(j = 0; j < etypes_len; j++) {
395 for (i = 0; i < n; i++)
396 if (pa.val[i].etype == etypes[j])
398 for(i = 0; i < client->keys.len; i++) {
399 if(client->keys.val[i].key.keytype == etypes[j]) {
400 if (krb5_enctype_valid(context, etypes[j]) != 0)
402 if((ret = make_etype_info_entry(context,
404 &client->keys.val[i])) != 0) {
405 free_ETYPE_INFO(&pa);
412 for(i = 0; i < client->keys.len; i++) {
413 for(j = 0; j < etypes_len; j++) {
414 if(client->keys.val[i].key.keytype == etypes[j])
417 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
419 if((ret = make_etype_info_entry(context,
421 &client->keys.val[i])) != 0) {
422 free_ETYPE_INFO(&pa);
430 ret = krb5_unparse_name(context, client->principal, &name);
432 name = "<unparse_name failed>";
433 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
440 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
441 free_ETYPE_INFO(&pa);
444 ret = realloc_method_data(md);
449 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
450 md->val[md->len - 1].padata_value.length = len;
451 md->val[md->len - 1].padata_value.data = buf;
459 extern int _krb5_AES_string_to_default_iterator;
461 static krb5_error_code
462 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
464 ent->etype = key->key.keytype;
467 if (ent->salt == NULL)
469 *ent->salt = malloc(key->salt->salt.length + 1);
470 if (*ent->salt == NULL) {
475 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
476 (*ent->salt)[key->salt->salt.length] = '\0';
480 ent->s2kparams = NULL;
482 switch (key->key.keytype) {
483 case ETYPE_AES128_CTS_HMAC_SHA1_96:
484 case ETYPE_AES256_CTS_HMAC_SHA1_96:
485 ALLOC(ent->s2kparams);
486 if (ent->s2kparams == NULL)
488 ent->s2kparams->length = 4;
489 ent->s2kparams->data = malloc(ent->s2kparams->length);
490 if (ent->s2kparams->data == NULL) {
491 free(ent->s2kparams);
492 ent->s2kparams = NULL;
495 _krb5_put_int(ent->s2kparams->data,
496 _krb5_AES_string_to_default_iterator,
497 ent->s2kparams->length);
499 case ETYPE_DES_CBC_CRC:
500 case ETYPE_DES_CBC_MD4:
501 case ETYPE_DES_CBC_MD5:
502 /* Check if this was a AFS3 salted key */
503 if(key->salt && key->salt->type == hdb_afs3_salt){
504 ALLOC(ent->s2kparams);
505 if (ent->s2kparams == NULL)
507 ent->s2kparams->length = 1;
508 ent->s2kparams->data = malloc(ent->s2kparams->length);
509 if (ent->s2kparams->data == NULL) {
510 free(ent->s2kparams);
511 ent->s2kparams = NULL;
514 _krb5_put_int(ent->s2kparams->data,
516 ent->s2kparams->length);
526 * Return 1 if the client have only older enctypes, this is for
527 * determining if the server should send ETYPE_INFO2 or not.
531 only_older_enctype_p(const KDC_REQ *req)
535 for(i = 0; i < req->req_body.etype.len; i++) {
536 switch (req->req_body.etype.val[i]) {
537 case ETYPE_DES_CBC_CRC:
538 case ETYPE_DES_CBC_MD4:
539 case ETYPE_DES_CBC_MD5:
540 case ETYPE_DES3_CBC_SHA1:
541 case ETYPE_ARCFOUR_HMAC_MD5:
542 case ETYPE_ARCFOUR_HMAC_MD5_56:
555 static krb5_error_code
556 get_pa_etype_info2(krb5_context context,
557 krb5_kdc_configuration *config,
558 METHOD_DATA *md, hdb_entry *client,
559 ENCTYPE *etypes, unsigned int etypes_len)
561 krb5_error_code ret = 0;
568 pa.len = client->keys.len;
569 if(pa.len > UINT_MAX/sizeof(*pa.val))
571 pa.val = malloc(pa.len * sizeof(*pa.val));
574 memset(pa.val, 0, pa.len * sizeof(*pa.val));
576 for(j = 0; j < etypes_len; j++) {
577 for (i = 0; i < n; i++)
578 if (pa.val[i].etype == etypes[j])
580 for(i = 0; i < client->keys.len; i++) {
581 if(client->keys.val[i].key.keytype == etypes[j]) {
582 if (krb5_enctype_valid(context, etypes[j]) != 0)
584 if((ret = make_etype_info2_entry(&pa.val[n++],
585 &client->keys.val[i])) != 0) {
586 free_ETYPE_INFO2(&pa);
593 for(i = 0; i < client->keys.len; i++) {
594 for(j = 0; j < etypes_len; j++) {
595 if(client->keys.val[i].key.keytype == etypes[j])
598 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
600 if((ret = make_etype_info2_entry(&pa.val[n++],
601 &client->keys.val[i])) != 0) {
602 free_ETYPE_INFO2(&pa);
610 ret = krb5_unparse_name(context, client->principal, &name);
612 name = "<unparse_name failed>";
613 kdc_log(context, config, 0,
614 "internal error in get_pa_etype_info2(%s): %d != %d",
621 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
622 free_ETYPE_INFO2(&pa);
625 ret = realloc_method_data(md);
630 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
631 md->val[md->len - 1].padata_value.length = len;
632 md->val[md->len - 1].padata_value.data = buf;
637 * verify the flags on `client' and `server', returning 0
638 * if they are OK and generating an error messages and returning
639 * and error code otherwise.
643 _kdc_check_flags(krb5_context context,
644 krb5_kdc_configuration *config,
645 hdb_entry *client, const char *client_name,
646 hdb_entry *server, const char *server_name,
647 krb5_boolean is_as_req)
651 if (client->flags.invalid) {
652 kdc_log(context, config, 0,
653 "Client (%s) has invalid bit set", client_name);
654 return KRB5KDC_ERR_POLICY;
657 if(!client->flags.client){
658 kdc_log(context, config, 0,
659 "Principal may not act as client -- %s", client_name);
660 return KRB5KDC_ERR_POLICY;
663 if (client->valid_start && *client->valid_start > kdc_time) {
664 char starttime_str[100];
665 krb5_format_time(context, *client->valid_start,
666 starttime_str, sizeof(starttime_str), TRUE);
667 kdc_log(context, config, 0,
668 "Client not yet valid until %s -- %s",
671 return KRB5KDC_ERR_CLIENT_NOTYET;
674 if (client->valid_end && *client->valid_end < kdc_time) {
675 char endtime_str[100];
676 krb5_format_time(context, *client->valid_end,
677 endtime_str, sizeof(endtime_str), TRUE);
678 kdc_log(context, config, 0,
679 "Client expired at %s -- %s", endtime_str, client_name);
680 return KRB5KDC_ERR_NAME_EXP;
683 if (client->pw_end && *client->pw_end < kdc_time
684 && !server->flags.change_pw) {
686 krb5_format_time(context, *client->pw_end,
687 pwend_str, sizeof(pwend_str), TRUE);
688 kdc_log(context, config, 0,
689 "Client's key has expired at %s -- %s", pwend_str, client_name);
690 return KRB5KDC_ERR_KEY_EXPIRED;
696 if (server != NULL) {
697 if (server->flags.invalid) {
698 kdc_log(context, config, 0,
699 "Server has invalid flag set -- %s", server_name);
700 return KRB5KDC_ERR_POLICY;
703 if(!server->flags.server){
704 kdc_log(context, config, 0,
705 "Principal may not act as server -- %s", server_name);
706 return KRB5KDC_ERR_POLICY;
709 if(!is_as_req && server->flags.initial) {
710 kdc_log(context, config, 0,
711 "AS-REQ is required for server -- %s", server_name);
712 return KRB5KDC_ERR_POLICY;
715 if (server->valid_start && *server->valid_start > kdc_time) {
716 char starttime_str[100];
717 krb5_format_time(context, *server->valid_start,
718 starttime_str, sizeof(starttime_str), TRUE);
719 kdc_log(context, config, 0,
720 "Server not yet valid until %s -- %s", server_name);
721 return KRB5KDC_ERR_SERVICE_NOTYET;
724 if (server->valid_end && *server->valid_end < kdc_time) {
725 char endtime_str[100];
726 krb5_format_time(context, *server->valid_end,
727 endtime_str, sizeof(endtime_str), TRUE);
728 kdc_log(context, config, 0,
729 "Server expired at %s -- %s",
730 endtime_str, server_name);
731 return KRB5KDC_ERR_SERVICE_EXP;
734 if (server->pw_end && *server->pw_end < kdc_time) {
736 krb5_format_time(context, *server->pw_end,
737 pwend_str, sizeof(pwend_str), TRUE);
738 kdc_log(context, config, 0,
739 "Server's key has expired at -- %s",
740 pwend_str, server_name);
741 return KRB5KDC_ERR_KEY_EXPIRED;
748 * Return TRUE if `from' is part of `addresses' taking into consideration
749 * the configuration variables that tells us how strict we should be about
754 check_addresses(krb5_context context,
755 krb5_kdc_configuration *config,
756 HostAddresses *addresses, const struct sockaddr *from)
761 krb5_boolean only_netbios = TRUE;
764 if(config->check_ticket_addresses == 0)
767 if(addresses == NULL)
768 return config->allow_null_ticket_addresses;
770 for (i = 0; i < addresses->len; ++i) {
771 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
772 only_netbios = FALSE;
776 /* Windows sends it's netbios name, which I can only assume is
777 * used for the 'allowed workstations' check. This is painful, but
778 * we still want to check IP addresses if they happen to be
782 return config->allow_null_ticket_addresses;
784 ret = krb5_sockaddr2address (context, from, &addr);
788 result = krb5_address_search(context, &addr, addresses);
789 krb5_free_address (context, &addr);
794 _kdc_as_rep(krb5_context context,
795 krb5_kdc_configuration *config,
797 const krb5_data *req_buffer,
800 struct sockaddr *from_addr)
802 KDC_REQ_BODY *b = &req->req_body;
804 KDCOptions f = b->kdc_options;
805 hdb_entry_ex *client = NULL;
806 hdb_entry *server = NULL;
807 krb5_enctype cetype, setype;
810 krb5_principal client_princ = NULL, server_princ = NULL;
811 char *client_name = NULL, *server_name = NULL;
812 krb5_error_code ret = 0;
813 const char *e_text = NULL;
816 EncryptionKey *reply_key;
818 pk_client_params *pkp = NULL;
821 memset(&rep, 0, sizeof(rep));
823 if(b->sname == NULL){
824 ret = KRB5KRB_ERR_GENERIC;
825 e_text = "No server in request";
827 _krb5_principalname2krb5_principal (&server_princ,
828 *(b->sname), b->realm);
829 ret = krb5_unparse_name(context, server_princ, &server_name);
832 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
836 if(b->cname == NULL){
837 ret = KRB5KRB_ERR_GENERIC;
838 e_text = "No client in request";
840 _krb5_principalname2krb5_principal (&client_princ,
841 *(b->cname), b->realm);
842 ret = krb5_unparse_name(context, client_princ, &client_name);
845 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
849 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
850 client_name, from, server_name);
852 ret = _kdc_db_fetch_ex(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
854 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
855 krb5_get_err_text(context, ret));
856 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
860 ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
862 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
863 krb5_get_err_text(context, ret));
864 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
868 ret = _kdc_check_flags(context, config,
869 &client->entry, client_name,
875 if (client->check_client_access) {
876 ret = client->check_client_access(context, client,
882 memset(&et, 0, sizeof(et));
883 memset(&ek, 0, sizeof(ek));
891 kdc_log(context, config, 5,
892 "Looking for PKINIT pa-data -- %s", client_name);
894 e_text = "No PKINIT PA found";
897 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
901 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
905 char *client_cert = NULL;
907 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
909 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
910 kdc_log(context, config, 5,
911 "Failed to decode PKINIT PA-DATA -- %s",
915 if (ret == 0 && pkp == NULL)
918 ret = _kdc_pk_check_client(context,
925 e_text = "PKINIT certificate not allowed to "
926 "impersonate principal";
927 _kdc_pk_free_client_param(context, pkp);
929 kdc_log(context, config, 0, "%s", e_text);
934 et.flags.pre_authent = 1;
935 kdc_log(context, config, 0,
936 "PKINIT pre-authentication succeeded -- %s using %s",
937 client_name, client_cert);
944 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
948 e_text = "No ENC-TS found";
949 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
953 EncryptedData enc_data;
959 ret = decode_EncryptedData(pa->padata_value.data,
960 pa->padata_value.length,
964 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
965 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
970 ret = hdb_enctype2key(context, &client->entry, enc_data.etype, &pa_key);
973 e_text = "No key matches pa-data";
974 ret = KRB5KDC_ERR_PREAUTH_FAILED;
975 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
978 kdc_log(context, config, 5,
979 "No client key matching pa-data (%d) -- %s",
980 enc_data.etype, client_name);
982 kdc_log(context, config, 5,
983 "No client key matching pa-data (%s) -- %s",
987 free_EncryptedData(&enc_data);
992 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
994 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
995 krb5_get_err_text(context, ret));
996 free_EncryptedData(&enc_data);
1000 ret = krb5_decrypt_EncryptedData (context,
1002 KRB5_KU_PA_ENC_TIMESTAMP,
1005 krb5_crypto_destroy(context, crypto);
1007 krb5_error_code ret2;
1008 ret2 = krb5_enctype_to_string(context,
1009 pa_key->key.keytype, &str);
1012 kdc_log(context, config, 5,
1013 "Failed to decrypt PA-DATA -- %s "
1014 "(enctype %s) error %s",
1016 str ? str : "unknown enctype",
1017 krb5_get_err_text(context, ret));
1020 if(hdb_next_enctype2key(context, &client->entry,
1021 enc_data.etype, &pa_key) == 0)
1023 e_text = "Failed to decrypt PA-DATA";
1025 free_EncryptedData(&enc_data);
1026 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1029 free_EncryptedData(&enc_data);
1030 ret = decode_PA_ENC_TS_ENC(ts_data.data,
1034 krb5_data_free(&ts_data);
1036 e_text = "Failed to decode PA-ENC-TS-ENC";
1037 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1038 kdc_log(context, config,
1039 5, "Failed to decode PA-ENC-TS_ENC -- %s",
1043 free_PA_ENC_TS_ENC(&p);
1044 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1045 ret = KRB5KRB_AP_ERR_SKEW;
1046 e_text = "Too large time skew";
1047 kdc_log(context, config, 0,
1048 "Too large time skew -- %s", client_name);
1051 et.flags.pre_authent = 1;
1053 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1057 kdc_log(context, config, 2,
1058 "ENC-TS Pre-authentication succeeded -- %s using %s",
1059 client_name, str ? str : "unknown enctype");
1066 if(found_pa == 0 && config->require_preauth)
1068 /* We come here if we found a pa-enc-timestamp, but if there
1069 was some problem with it, other than too large skew */
1070 if(found_pa && et.flags.pre_authent == 0){
1071 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1075 }else if (config->require_preauth
1076 || client->entry.flags.require_preauth
1077 || server->flags.require_preauth) {
1078 METHOD_DATA method_data;
1085 method_data.len = 0;
1086 method_data.val = NULL;
1088 ret = realloc_method_data(&method_data);
1089 pa = &method_data.val[method_data.len-1];
1090 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
1091 pa->padata_value.length = 0;
1092 pa->padata_value.data = NULL;
1095 ret = realloc_method_data(&method_data);
1096 pa = &method_data.val[method_data.len-1];
1097 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
1098 pa->padata_value.length = 0;
1099 pa->padata_value.data = NULL;
1102 /* RFC4120 requires:
1103 - If the client only knows about old enctypes, then send both info replies
1104 (we send 'info' first in the list).
1105 - If the client is 'modern', because it knows about 'new' enc types, then
1106 only send the 'info2' reply.
1109 if (only_older_enctype_p(req))
1110 ret = get_pa_etype_info(context, config, &method_data, &client->entry,
1111 b->etype.val, b->etype.len);
1113 ret = get_pa_etype_info2(context, config, &method_data, &client->entry,
1114 b->etype.val, b->etype.len);
1117 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1118 free_METHOD_DATA(&method_data);
1119 foo_data.data = buf;
1120 foo_data.length = len;
1122 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1123 krb5_mk_error(context,
1125 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1133 kdc_log(context, config, 0,
1134 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1140 ret = find_keys(context, config,
1141 &client->entry, server, &ckey, &cetype, &skey, &setype,
1142 b->etype.val, b->etype.len);
1144 kdc_log(context, config, 0, "Server/client has no support for etypes");
1149 struct rk_strpool *p = NULL;
1153 for (i = 0; i < b->etype.len; i++) {
1154 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1156 p = rk_strpoolprintf(p, "%s", str);
1159 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1160 if (p && i + 1 < b->etype.len)
1161 p = rk_strpoolprintf(p, ", ");
1163 kdc_log(context, config, 0, "out of meory");
1167 str = rk_strpoolcollect(p);
1168 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1175 ret = krb5_enctype_to_string(context, cetype, &cet);
1177 ret = krb5_enctype_to_string(context, setype, &set);
1179 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1185 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1190 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1193 kdc_log(context, config, 2, "Requested flags: %s", str);
1197 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1198 || (f.request_anonymous && !config->allow_anonymous)) {
1199 ret = KRB5KDC_ERR_BADOPTION;
1200 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1205 rep.msg_type = krb_as_rep;
1206 copy_Realm(&client->entry.principal->realm, &rep.crealm);
1207 if (f.request_anonymous)
1208 make_anonymous_principalname (&rep.cname);
1210 _krb5_principal2principalname(&rep.cname,
1211 client->entry.principal);
1212 rep.ticket.tkt_vno = 5;
1213 copy_Realm(&server->principal->realm, &rep.ticket.realm);
1214 _krb5_principal2principalname(&rep.ticket.sname,
1217 et.flags.initial = 1;
1218 if(client->entry.flags.forwardable && server->flags.forwardable)
1219 et.flags.forwardable = f.forwardable;
1220 else if (f.forwardable) {
1221 ret = KRB5KDC_ERR_POLICY;
1222 kdc_log(context, config, 0,
1223 "Ticket may not be forwardable -- %s", client_name);
1226 if(client->entry.flags.proxiable && server->flags.proxiable)
1227 et.flags.proxiable = f.proxiable;
1228 else if (f.proxiable) {
1229 ret = KRB5KDC_ERR_POLICY;
1230 kdc_log(context, config, 0,
1231 "Ticket may not be proxiable -- %s", client_name);
1234 if(client->entry.flags.postdate && server->flags.postdate)
1235 et.flags.may_postdate = f.allow_postdate;
1236 else if (f.allow_postdate){
1237 ret = KRB5KDC_ERR_POLICY;
1238 kdc_log(context, config, 0,
1239 "Ticket may not be postdatable -- %s", client_name);
1243 /* check for valid set of addresses */
1244 if(!check_addresses(context, config, b->addresses, from_addr)) {
1245 ret = KRB5KRB_AP_ERR_BADADDR;
1246 kdc_log(context, config, 0,
1247 "Bad address list requested -- %s", client_name);
1251 krb5_generate_random_keyblock(context, setype, &et.key);
1252 copy_PrincipalName(&rep.cname, &et.cname);
1253 copy_Realm(&rep.crealm, &et.crealm);
1259 start = et.authtime = kdc_time;
1261 if(f.postdated && req->req_body.from){
1262 ALLOC(et.starttime);
1263 start = *et.starttime = *req->req_body.from;
1264 et.flags.invalid = 1;
1265 et.flags.postdated = 1; /* XXX ??? */
1270 /* be careful not overflowing */
1272 if(client->entry.max_life)
1273 t = start + min(t - start, *client->entry.max_life);
1274 if(server->max_life)
1275 t = start + min(t - start, *server->max_life);
1277 t = min(t, start + realm->max_life);
1280 if(f.renewable_ok && et.endtime < *b->till){
1282 if(b->rtime == NULL){
1286 if(*b->rtime < *b->till)
1287 *b->rtime = *b->till;
1289 if(f.renewable && b->rtime){
1293 if(client->entry.max_renew)
1294 t = start + min(t - start, *client->entry.max_renew);
1295 if(server->max_renew)
1296 t = start + min(t - start, *server->max_renew);
1298 t = min(t, start + realm->max_renew);
1300 ALLOC(et.renew_till);
1302 et.flags.renewable = 1;
1306 if (f.request_anonymous)
1307 et.flags.anonymous = 1;
1311 copy_HostAddresses(b->addresses, et.caddr);
1314 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1315 krb5_data_zero(&et.transited.contents);
1317 copy_EncryptionKey(&et.key, &ek.key);
1319 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1320 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1321 * incapable of correctly decoding SEQUENCE OF's of zero length.
1323 * To fix this, always send at least one no-op last_req
1325 * If there's a pw_end or valid_end we will use that,
1326 * otherwise just a dummy lr.
1328 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1329 ek.last_req.len = 0;
1330 if (client->entry.pw_end
1331 && (config->kdc_warn_pwexpire == 0
1332 || kdc_time + config->kdc_warn_pwexpire <= *client->entry.pw_end)) {
1333 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1334 ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1337 if (client->entry.valid_end) {
1338 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1339 ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1342 if (ek.last_req.len == 0) {
1343 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1344 ek.last_req.val[ek.last_req.len].lr_value = 0;
1347 ek.nonce = b->nonce;
1348 if (client->entry.valid_end || client->entry.pw_end) {
1349 ALLOC(ek.key_expiration);
1350 if (client->entry.valid_end) {
1351 if (client->entry.pw_end)
1352 *ek.key_expiration = min(*client->entry.valid_end, *client->entry.pw_end);
1354 *ek.key_expiration = *client->entry.valid_end;
1356 *ek.key_expiration = *client->entry.pw_end;
1358 ek.key_expiration = NULL;
1359 ek.flags = et.flags;
1360 ek.authtime = et.authtime;
1362 ALLOC(ek.starttime);
1363 *ek.starttime = *et.starttime;
1365 ek.endtime = et.endtime;
1366 if (et.renew_till) {
1367 ALLOC(ek.renew_till);
1368 *ek.renew_till = *et.renew_till;
1370 copy_Realm(&rep.ticket.realm, &ek.srealm);
1371 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1374 copy_HostAddresses(et.caddr, ek.caddr);
1378 rep.padata->len = 0;
1379 rep.padata->val = NULL;
1381 reply_key = &ckey->key;
1384 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1386 &reply_key, rep.padata);
1392 set_salt_padata (rep.padata, ckey->salt);
1394 if (rep.padata->len == 0) {
1399 /* Add the PAC, via a HDB abstraction */
1400 if (client->authz_data_as_req) {
1401 ret = client->authz_data_as_req(context, client,
1406 &et.authorization_data);
1411 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1412 et.endtime, et.renew_till);
1414 ret = encode_reply(context, config,
1415 &rep, &et, &ek, setype, server->kvno, &skey->key,
1416 client->entry.kvno, reply_key, &e_text, reply);
1417 free_EncTicketPart(&et);
1418 free_EncKDCRepPart(&ek);
1422 krb5_mk_error(context,
1436 _kdc_pk_free_client_param(context, pkp);
1439 krb5_free_principal(context, client_princ);
1442 krb5_free_principal(context, server_princ);
1445 _kdc_free_ent_ex(context, client);
1447 _kdc_free_ent(context, server);
1452 static krb5_error_code
1453 check_tgs_flags(krb5_context context,
1454 krb5_kdc_configuration *config,
1455 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1457 KDCOptions f = b->kdc_options;
1460 if(!tgt->flags.invalid || tgt->starttime == NULL){
1461 kdc_log(context, config, 0,
1462 "Bad request to validate ticket");
1463 return KRB5KDC_ERR_BADOPTION;
1465 if(*tgt->starttime > kdc_time){
1466 kdc_log(context, config, 0,
1467 "Early request to validate ticket");
1468 return KRB5KRB_AP_ERR_TKT_NYV;
1471 et->flags.invalid = 0;
1472 }else if(tgt->flags.invalid){
1473 kdc_log(context, config, 0,
1474 "Ticket-granting ticket has INVALID flag set");
1475 return KRB5KRB_AP_ERR_TKT_INVALID;
1479 if(!tgt->flags.forwardable){
1480 kdc_log(context, config, 0,
1481 "Bad request for forwardable ticket");
1482 return KRB5KDC_ERR_BADOPTION;
1484 et->flags.forwardable = 1;
1487 if(!tgt->flags.forwardable){
1488 kdc_log(context, config, 0,
1489 "Request to forward non-forwardable ticket");
1490 return KRB5KDC_ERR_BADOPTION;
1492 et->flags.forwarded = 1;
1493 et->caddr = b->addresses;
1495 if(tgt->flags.forwarded)
1496 et->flags.forwarded = 1;
1499 if(!tgt->flags.proxiable){
1500 kdc_log(context, config, 0,
1501 "Bad request for proxiable ticket");
1502 return KRB5KDC_ERR_BADOPTION;
1504 et->flags.proxiable = 1;
1507 if(!tgt->flags.proxiable){
1508 kdc_log(context, config, 0,
1509 "Request to proxy non-proxiable ticket");
1510 return KRB5KDC_ERR_BADOPTION;
1512 et->flags.proxy = 1;
1513 et->caddr = b->addresses;
1515 if(tgt->flags.proxy)
1516 et->flags.proxy = 1;
1518 if(f.allow_postdate){
1519 if(!tgt->flags.may_postdate){
1520 kdc_log(context, config, 0,
1521 "Bad request for post-datable ticket");
1522 return KRB5KDC_ERR_BADOPTION;
1524 et->flags.may_postdate = 1;
1527 if(!tgt->flags.may_postdate){
1528 kdc_log(context, config, 0,
1529 "Bad request for postdated ticket");
1530 return KRB5KDC_ERR_BADOPTION;
1533 *et->starttime = *b->from;
1534 et->flags.postdated = 1;
1535 et->flags.invalid = 1;
1536 }else if(b->from && *b->from > kdc_time + context->max_skew){
1537 kdc_log(context, config, 0, "Ticket cannot be postdated");
1538 return KRB5KDC_ERR_CANNOT_POSTDATE;
1542 if(!tgt->flags.renewable){
1543 kdc_log(context, config, 0,
1544 "Bad request for renewable ticket");
1545 return KRB5KDC_ERR_BADOPTION;
1547 et->flags.renewable = 1;
1548 ALLOC(et->renew_till);
1549 fix_time(&b->rtime);
1550 *et->renew_till = *b->rtime;
1554 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1555 kdc_log(context, config, 0,
1556 "Request to renew non-renewable ticket");
1557 return KRB5KDC_ERR_BADOPTION;
1559 old_life = tgt->endtime;
1561 old_life -= *tgt->starttime;
1563 old_life -= tgt->authtime;
1564 et->endtime = *et->starttime + old_life;
1565 if (et->renew_till != NULL)
1566 et->endtime = min(*et->renew_till, et->endtime);
1569 /* checks for excess flags */
1570 if(f.request_anonymous && !config->allow_anonymous){
1571 kdc_log(context, config, 0,
1572 "Request for anonymous ticket");
1573 return KRB5KDC_ERR_BADOPTION;
1578 static krb5_error_code
1579 fix_transited_encoding(krb5_context context,
1580 krb5_kdc_configuration *config,
1581 krb5_boolean check_policy,
1582 TransitedEncoding *tr,
1584 const char *client_realm,
1585 const char *server_realm,
1586 const char *tgt_realm)
1588 krb5_error_code ret = 0;
1589 char **realms, **tmp;
1593 switch (tr->tr_type) {
1594 case DOMAIN_X500_COMPRESS:
1598 * Allow empty content of type 0 because that is was Microsoft
1599 * generates in their TGT.
1601 if (tr->contents.length == 0)
1603 kdc_log(context, config, 0,
1604 "Transited type 0 with non empty content");
1605 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1607 kdc_log(context, config, 0,
1608 "Unknown transited type: %u", tr->tr_type);
1609 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1612 ret = krb5_domain_x500_decode(context,
1619 krb5_warn(context, ret,
1620 "Decoding transited encoding");
1623 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1624 /* not us, so add the previous realm to transited set */
1625 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1629 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1635 realms[num_realms] = strdup(tgt_realm);
1636 if(realms[num_realms] == NULL){
1642 if(num_realms == 0) {
1643 if(strcmp(client_realm, server_realm))
1644 kdc_log(context, config, 0,
1645 "cross-realm %s -> %s", client_realm, server_realm);
1649 for(i = 0; i < num_realms; i++)
1650 l += strlen(realms[i]) + 2;
1654 for(i = 0; i < num_realms; i++) {
1656 strlcat(rs, ", ", l);
1657 strlcat(rs, realms[i], l);
1659 kdc_log(context, config, 0,
1660 "cross-realm %s -> %s via [%s]",
1661 client_realm, server_realm, rs);
1666 ret = krb5_check_transited(context, client_realm,
1668 realms, num_realms, NULL);
1670 krb5_warn(context, ret, "cross-realm %s -> %s",
1671 client_realm, server_realm);
1674 et->flags.transited_policy_checked = 1;
1676 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1677 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1679 krb5_warn(context, ret, "Encoding transited encoding");
1681 for(i = 0; i < num_realms; i++)
1688 static krb5_error_code
1689 tgs_make_reply(krb5_context context,
1690 krb5_kdc_configuration *config,
1693 EncTicketPart *adtkt,
1694 AuthorizationData *auth_data,
1695 krb5_ticket *tgs_ticket,
1696 hdb_entry_ex *server,
1698 krb5_principal client_principal,
1700 EncryptionKey *tgtkey,
1701 krb5_enctype cetype,
1702 const char **e_text,
1708 KDCOptions f = b->kdc_options;
1709 krb5_error_code ret;
1712 EncryptionKey *ekey;
1713 AuthorizationData *new_auth_data = NULL;
1719 for(i = 0; i < b->etype.len; i++){
1720 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1723 if(adtkt->key.keytype == kt)
1726 if(i == b->etype.len)
1727 return KRB5KDC_ERR_ETYPE_NOSUPP;
1728 etype = b->etype.val[i];
1730 ret = find_keys(context, config,
1731 NULL, &server->entry, NULL, NULL, &skey, &etype,
1732 b->etype.val, b->etype.len);
1734 kdc_log(context, config, 0, "Server has no support for etypes");
1740 memset(&rep, 0, sizeof(rep));
1741 memset(&et, 0, sizeof(et));
1742 memset(&ek, 0, sizeof(ek));
1745 rep.msg_type = krb_tgs_rep;
1747 et.authtime = tgt->authtime;
1749 et.endtime = min(tgt->endtime, *b->till);
1750 ALLOC(et.starttime);
1751 *et.starttime = kdc_time;
1753 ret = check_tgs_flags(context, config, b, tgt, &et);
1757 /* We should check the transited encoding if:
1758 1) the request doesn't ask not to be checked
1759 2) globally enforcing a check
1760 3) principal requires checking
1761 4) we allow non-check per-principal, but principal isn't marked as allowing this
1762 5) we don't globally allow this
1765 #define GLOBAL_FORCE_TRANSITED_CHECK \
1766 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1767 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1768 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1769 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1770 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1772 /* these will consult the database in future release */
1773 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1774 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1776 ret = fix_transited_encoding(context, config,
1777 !f.disable_transited_check ||
1778 GLOBAL_FORCE_TRANSITED_CHECK ||
1779 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1780 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1781 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1782 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1783 &tgt->transited, &et,
1784 *krb5_princ_realm(context, client_principal),
1785 *krb5_princ_realm(context, server->entry.principal),
1786 *krb5_princ_realm(context, krbtgt->principal));
1790 copy_Realm(krb5_princ_realm(context, server->entry.principal),
1792 _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
1793 copy_Realm(&tgt->crealm, &rep.crealm);
1794 if (f.request_anonymous)
1795 make_anonymous_principalname (&tgt->cname);
1797 copy_PrincipalName(&tgt->cname, &rep.cname);
1798 rep.ticket.tkt_vno = 5;
1800 ek.caddr = et.caddr;
1801 if(et.caddr == NULL)
1802 et.caddr = tgt->caddr;
1806 life = et.endtime - *et.starttime;
1807 if(client && client->max_life)
1808 life = min(life, *client->max_life);
1809 if(server->entry.max_life)
1810 life = min(life, *server->entry.max_life);
1811 et.endtime = *et.starttime + life;
1813 if(f.renewable_ok && tgt->flags.renewable &&
1814 et.renew_till == NULL && et.endtime < *b->till){
1815 et.flags.renewable = 1;
1816 ALLOC(et.renew_till);
1817 *et.renew_till = *b->till;
1821 renew = *et.renew_till - et.authtime;
1822 if(client && client->max_renew)
1823 renew = min(renew, *client->max_renew);
1824 if(server->entry.max_renew)
1825 renew = min(renew, *server->entry.max_renew);
1826 *et.renew_till = et.authtime + renew;
1830 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1831 *et.starttime = min(*et.starttime, *et.renew_till);
1832 et.endtime = min(et.endtime, *et.renew_till);
1835 *et.starttime = min(*et.starttime, et.endtime);
1837 if(*et.starttime == et.endtime){
1838 ret = KRB5KDC_ERR_NEVER_VALID;
1841 if(et.renew_till && et.endtime == *et.renew_till){
1842 free(et.renew_till);
1843 et.renew_till = NULL;
1844 et.flags.renewable = 0;
1847 et.flags.pre_authent = tgt->flags.pre_authent;
1848 et.flags.hw_authent = tgt->flags.hw_authent;
1849 et.flags.anonymous = tgt->flags.anonymous;
1850 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
1853 krb5_generate_random_keyblock(context, etype, &et.key);
1855 if (server->authz_data_tgs_req) {
1856 ret = server->authz_data_tgs_req(context, server,
1858 tgs_ticket->ticket.authorization_data,
1859 tgs_ticket->ticket.authtime,
1865 new_auth_data = NULL;
1869 /* XXX Check enc-authorization-data */
1870 et.authorization_data = new_auth_data;
1872 et.crealm = tgt->crealm;
1873 et.cname = tgt->cname;
1876 /* MIT must have at least one last_req */
1877 ek.last_req.len = 1;
1878 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1879 ek.nonce = b->nonce;
1880 ek.flags = et.flags;
1881 ek.authtime = et.authtime;
1882 ek.starttime = et.starttime;
1883 ek.endtime = et.endtime;
1884 ek.renew_till = et.renew_till;
1885 ek.srealm = rep.ticket.realm;
1886 ek.sname = rep.ticket.sname;
1888 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1889 et.endtime, et.renew_till);
1891 /* It is somewhat unclear where the etype in the following
1892 encryption should come from. What we have is a session
1893 key in the passed tgt, and a list of preferred etypes
1894 *for the new ticket*. Should we pick the best possible
1895 etype, given the keytype in the tgt, or should we look
1896 at the etype list here as well? What if the tgt
1897 session key is DES3 and we want a ticket with a (say)
1898 CAST session key. Should the DES3 etype be added to the
1899 etype list, even if we don't want a session key with
1901 ret = encode_reply(context, config,
1902 &rep, &et, &ek, etype, adtkt ? 0 : server->entry.kvno, ekey,
1903 0, &tgt->key, e_text, reply);
1906 free_TransitedEncoding(&et.transited);
1910 free(et.renew_till);
1911 free_LastReq(&ek.last_req);
1912 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1913 free_EncryptionKey(&et.key);
1917 static krb5_error_code
1918 tgs_check_authenticator(krb5_context context,
1919 krb5_kdc_configuration *config,
1920 krb5_auth_context ac,
1922 const char **e_text,
1925 krb5_authenticator auth;
1929 krb5_error_code ret;
1932 krb5_auth_con_getauthenticator(context, ac, &auth);
1933 if(auth->cksum == NULL){
1934 kdc_log(context, config, 0, "No authenticator in request");
1935 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1939 * according to RFC1510 it doesn't need to be keyed,
1940 * but according to the latest draft it needs to.
1944 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1947 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1948 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1949 auth->cksum->cksumtype);
1950 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1954 /* XXX should not re-encode this */
1955 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1957 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
1958 krb5_get_err_text(context, ret));
1961 if(buf_size != len) {
1963 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1964 *e_text = "KDC internal error";
1965 ret = KRB5KRB_ERR_GENERIC;
1968 ret = krb5_crypto_init(context, key, 0, &crypto);
1971 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1972 krb5_get_err_text(context, ret));
1975 ret = krb5_verify_checksum(context,
1977 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1982 krb5_crypto_destroy(context, crypto);
1984 kdc_log(context, config, 0,
1985 "Failed to verify authenticator checksum: %s",
1986 krb5_get_err_text(context, ret));
1989 free_Authenticator(auth);
1995 * return the realm of a krbtgt-ticket or NULL
1999 get_krbtgt_realm(const PrincipalName *p)
2001 if(p->name_string.len == 2
2002 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
2003 return p->name_string.val[1];
2009 find_rpath(krb5_context context, Realm crealm, Realm srealm)
2011 const char *new_realm = krb5_config_get_string(context,
2022 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
2024 if(server->name.name_type != KRB5_NT_SRV_INST ||
2025 server->name.name_string.len != 2)
2028 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
2029 FALSE, realms) == 0;
2032 static krb5_error_code
2033 tgs_rep2(krb5_context context,
2034 krb5_kdc_configuration *config,
2039 const struct sockaddr *from_addr,
2044 krb5_error_code ret;
2045 krb5_principal princ;
2046 krb5_auth_context ac = NULL;
2047 krb5_ticket *ticket = NULL;
2048 krb5_flags ap_req_options;
2049 krb5_flags verify_ap_req_flags;
2050 const char *e_text = NULL;
2053 hdb_entry *krbtgt = NULL;
2056 krb5_enctype cetype;
2057 krb5_principal cp = NULL;
2058 krb5_principal sp = NULL;
2059 AuthorizationData *auth_data = NULL;
2064 memset(&ap_req, 0, sizeof(ap_req));
2065 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2067 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
2068 krb5_get_err_text(context, ret));
2072 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2073 /* XXX check for ticket.sname == req.sname */
2074 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2075 ret = KRB5KDC_ERR_POLICY; /* ? */
2079 _krb5_principalname2krb5_principal(&princ,
2080 ap_req.ticket.sname,
2081 ap_req.ticket.realm);
2083 ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
2087 ret = krb5_unparse_name(context, princ, &p);
2089 p = "<unparse_name failed>";
2090 krb5_free_principal(context, princ);
2091 kdc_log(context, config, 0,
2092 "Ticket-granting ticket not found in database: %s: %s",
2093 p, krb5_get_err_text(context, ret));
2096 ret = KRB5KRB_AP_ERR_NOT_US;
2100 if(ap_req.ticket.enc_part.kvno &&
2101 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
2104 ret = krb5_unparse_name (context, princ, &p);
2105 krb5_free_principal(context, princ);
2107 p = "<unparse_name failed>";
2108 kdc_log(context, config, 0,
2109 "Ticket kvno = %d, DB kvno = %d (%s)",
2110 *ap_req.ticket.enc_part.kvno,
2115 ret = KRB5KRB_AP_ERR_BADKEYVER;
2119 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2122 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2123 kdc_log(context, config, 0,
2124 "No server key found for %s", str);
2126 ret = KRB5KRB_AP_ERR_BADKEYVER;
2130 if (b->kdc_options.validate)
2131 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2133 verify_ap_req_flags = 0;
2135 ret = krb5_verify_ap_req2(context,
2140 verify_ap_req_flags,
2143 KRB5_KU_TGS_REQ_AUTH);
2145 krb5_free_principal(context, princ);
2147 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2148 krb5_get_err_text(context, ret));
2153 krb5_authenticator auth;
2155 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2157 *csec = malloc(sizeof(**csec));
2158 if (*csec == NULL) {
2159 krb5_free_authenticator(context, &auth);
2160 kdc_log(context, config, 0, "malloc failed");
2163 **csec = auth->ctime;
2164 *cusec = malloc(sizeof(**cusec));
2165 if (*cusec == NULL) {
2166 krb5_free_authenticator(context, &auth);
2167 kdc_log(context, config, 0, "malloc failed");
2170 **csec = auth->cusec;
2171 krb5_free_authenticator(context, &auth);
2175 cetype = ap_req.authenticator.etype;
2177 tgt = &ticket->ticket;
2179 ret = tgs_check_authenticator(context, config,
2180 ac, b, &e_text, &tgt->key);
2182 krb5_auth_con_free(context, ac);
2186 if (b->enc_authorization_data) {
2187 krb5_keyblock *subkey;
2189 ret = krb5_auth_con_getremotesubkey(context,
2193 krb5_auth_con_free(context, ac);
2194 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2195 krb5_get_err_text(context, ret));
2199 ret = krb5_auth_con_getkey(context, ac, &subkey);
2201 krb5_auth_con_free(context, ac);
2202 kdc_log(context, config, 0, "Failed to get session key: %s",
2203 krb5_get_err_text(context, ret));
2208 krb5_auth_con_free(context, ac);
2209 kdc_log(context, config, 0,
2210 "Failed to get key for enc-authorization-data");
2211 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2214 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2216 krb5_auth_con_free(context, ac);
2217 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2218 krb5_get_err_text(context, ret));
2221 ret = krb5_decrypt_EncryptedData (context,
2223 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2224 b->enc_authorization_data,
2226 krb5_crypto_destroy(context, crypto);
2228 krb5_auth_con_free(context, ac);
2229 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2230 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2233 krb5_free_keyblock(context, subkey);
2235 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2237 krb5_auth_con_free(context, ac);
2240 kdc_log(context, config, 0, "Failed to decode authorization data");
2241 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2246 krb5_auth_con_free(context, ac);
2251 char *spn = NULL, *cpn = NULL;
2252 hdb_entry_ex *server = NULL;
2253 hdb_entry *client = NULL;
2255 EncTicketPart adtkt;
2260 if(b->kdc_options.enc_tkt_in_skey){
2266 if(b->additional_tickets == NULL ||
2267 b->additional_tickets->len == 0){
2268 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2269 kdc_log(context, config, 0,
2270 "No second ticket present in request");
2273 t = &b->additional_tickets->val[0];
2274 if(!get_krbtgt_realm(&t->sname)){
2275 kdc_log(context, config, 0,
2276 "Additional ticket is not a ticket-granting ticket");
2277 ret = KRB5KDC_ERR_POLICY;
2280 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2281 ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2282 krb5_free_principal(context, p);
2284 if (ret == HDB_ERR_NOENTRY)
2285 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2288 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2290 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2293 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2301 _krb5_principalname2krb5_principal(&sp, *s, r);
2302 ret = krb5_unparse_name(context, sp, &spn);
2305 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2306 ret = krb5_unparse_name(context, cp, &cpn);
2309 unparse_flags (KDCOptions2int(b->kdc_options),
2310 asn1_KDCOptions_units(),
2311 opt_str, sizeof(opt_str));
2313 kdc_log(context, config, 0,
2314 "TGS-REQ %s from %s for %s [%s]",
2315 cpn, from, spn, opt_str);
2317 kdc_log(context, config, 0,
2318 "TGS-REQ %s from %s for %s", cpn, from, spn);
2320 ret = _kdc_db_fetch_ex(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2323 const char *new_rlm;
2327 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2329 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2331 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2333 krb5_free_principal(context, sp);
2335 krb5_make_principal(context, &sp, r,
2336 KRB5_TGS_NAME, new_rlm, NULL);
2337 ret = krb5_unparse_name(context, sp, &spn);
2343 } else if(need_referral(context, sp, &realms)) {
2344 if (strcmp(realms[0], sp->realm) != 0) {
2345 kdc_log(context, config, 5,
2346 "Returning a referral to realm %s for "
2347 "server %s that was not found",
2349 krb5_free_principal(context, sp);
2351 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2353 ret = krb5_unparse_name(context, sp, &spn);
2356 krb5_free_host_realm(context, realms);
2359 krb5_free_host_realm(context, realms);
2361 kdc_log(context, config, 0,
2362 "Server not found in database: %s: %s", spn,
2363 krb5_get_err_text(context, ret));
2364 if (ret == HDB_ERR_NOENTRY)
2365 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2369 ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2371 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2372 cpn, krb5_get_err_text(context, ret));
2374 /* XXX check client only if same realm as krbtgt-instance */
2376 kdc_log(context, config, 0,
2377 "Client not found in database: %s: %s",
2378 cpn, krb5_get_err_text(context, ret));
2379 if (ret == HDB_ERR_NOENTRY)
2380 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2385 if(strcmp(krb5_principal_get_realm(context, sp),
2386 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2388 ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2389 kdc_log(context, config, 0,
2390 "Request with wrong krbtgt: %s",
2391 (ret == 0) ? tpn : "<unknown>");
2394 ret = KRB5KRB_AP_ERR_NOT_US;
2399 ret = _kdc_check_flags(context, config,
2401 &server->entry, spn,
2406 if((b->kdc_options.validate || b->kdc_options.renew) &&
2407 !krb5_principal_compare(context,
2409 server->entry.principal)){
2410 kdc_log(context, config, 0, "Inconsistent request.");
2411 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2415 /* check for valid set of addresses */
2416 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2417 ret = KRB5KRB_AP_ERR_BADADDR;
2418 kdc_log(context, config, 0, "Request from wrong address");
2422 ret = tgs_make_reply(context, config,
2425 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2442 _kdc_free_ent_ex(context, server);
2444 _kdc_free_ent(context, client);
2448 krb5_mk_error(context,
2462 krb5_free_principal(context, cp);
2463 krb5_free_principal(context, sp);
2465 krb5_free_ticket(context, ticket);
2466 free_AP_REQ(&ap_req);
2468 free_AuthorizationData(auth_data);
2473 _kdc_free_ent(context, krbtgt);
2480 _kdc_tgs_rep(krb5_context context,
2481 krb5_kdc_configuration *config,
2485 struct sockaddr *from_addr)
2487 krb5_error_code ret;
2489 PA_DATA *tgs_req = NULL;
2490 time_t *csec = NULL;
2493 if(req->padata == NULL){
2494 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2495 kdc_log(context, config, 0,
2496 "TGS-REQ from %s without PA-DATA", from);
2500 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2502 if(tgs_req == NULL){
2503 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2505 kdc_log(context, config, 0,
2506 "TGS-REQ from %s without PA-TGS-REQ", from);
2509 ret = tgs_rep2(context, config,
2510 &req->req_body, tgs_req, data, from, from_addr,
2513 if(ret && data->data == NULL){
2514 krb5_mk_error(context,