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.211 2006/04/27 12:01:09 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, const hdb_entry_ex *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->entry, 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,
122 const hdb_entry_ex *client,
123 const char *client_name,
124 const hdb_entry_ex *server,
125 const char *server_name,
127 krb5_enctype *cetype,
129 krb5_enctype *setype,
130 krb5_enctype *etypes,
136 /* find client key */
137 ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
139 kdc_log(context, config, 0,
140 "Client (%s) has no support for etypes", client_name);
146 /* find server key */
147 ret = find_etype(context, server, etypes, num_etypes, skey, setype);
149 kdc_log(context, config, 0,
150 "Server (%s) has no support for etypes", server_name);
157 static krb5_error_code
158 make_anonymous_principalname (PrincipalName *pn)
160 pn->name_type = KRB5_NT_PRINCIPAL;
161 pn->name_string.len = 1;
162 pn->name_string.val = malloc(sizeof(*pn->name_string.val));
163 if (pn->name_string.val == NULL)
165 pn->name_string.val[0] = strdup("anonymous");
166 if (pn->name_string.val[0] == NULL) {
167 free(pn->name_string.val);
168 pn->name_string.val = NULL;
175 log_timestamp(krb5_context context,
176 krb5_kdc_configuration *config,
178 KerberosTime authtime, KerberosTime *starttime,
179 KerberosTime endtime, KerberosTime *renew_till)
181 char authtime_str[100], starttime_str[100],
182 endtime_str[100], renewtime_str[100];
184 krb5_format_time(context, authtime,
185 authtime_str, sizeof(authtime_str), TRUE);
187 krb5_format_time(context, *starttime,
188 starttime_str, sizeof(starttime_str), TRUE);
190 strlcpy(starttime_str, "unset", sizeof(starttime_str));
191 krb5_format_time(context, endtime,
192 endtime_str, sizeof(endtime_str), TRUE);
194 krb5_format_time(context, *renew_till,
195 renewtime_str, sizeof(renewtime_str), TRUE);
197 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
199 kdc_log(context, config, 5,
200 "%s authtime: %s starttime: %s endtime: %s renew till: %s",
201 type, authtime_str, starttime_str, endtime_str, renewtime_str);
205 log_patypes(krb5_context context,
206 krb5_kdc_configuration *config,
209 struct rk_strpool *p = NULL;
213 for (i = 0; i < padata->len; i++) {
214 switch(padata->val[i].padata_type) {
215 case KRB5_PADATA_PK_AS_REQ:
216 p = rk_strpoolprintf(p, "PK-INIT(ietf)");
218 case KRB5_PADATA_PK_AS_REQ_WIN:
219 p = rk_strpoolprintf(p, "PK-INIT(win2k)");
221 case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
222 p = rk_strpoolprintf(p, "OCSP");
224 case KRB5_PADATA_ENC_TIMESTAMP:
225 p = rk_strpoolprintf(p, "encrypted-timestamp");
228 p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
231 if (p && i + 1 < padata->len)
232 p = rk_strpoolprintf(p, ", ");
234 kdc_log(context, config, 0, "out of memory");
239 p = rk_strpoolprintf(p, "none");
241 str = rk_strpoolcollect(p);
242 kdc_log(context, config, 0, "Client sent patypes: %s", str);
251 static krb5_error_code
252 encode_reply(krb5_context context,
253 krb5_kdc_configuration *config,
254 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
256 int skvno, EncryptionKey *skey,
257 int ckvno, EncryptionKey *ckey,
267 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
269 kdc_log(context, config, 0, "Failed to encode ticket: %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;
280 ret = krb5_crypto_init(context, skey, etype, &crypto);
283 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
284 krb5_get_err_text(context, ret));
288 ret = krb5_encrypt_EncryptedData(context,
294 &rep->ticket.enc_part);
296 krb5_crypto_destroy(context, crypto);
298 kdc_log(context, config, 0, "Failed to encrypt data: %s",
299 krb5_get_err_text(context, ret));
303 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
304 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
306 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
308 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
309 krb5_get_err_text(context, ret));
312 if(buf_size != len) {
314 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
315 *e_text = "KDC internal error";
316 return KRB5KRB_ERR_GENERIC;
318 ret = krb5_crypto_init(context, ckey, 0, &crypto);
321 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
322 krb5_get_err_text(context, ret));
325 if(rep->msg_type == krb_as_rep) {
326 krb5_encrypt_EncryptedData(context,
328 KRB5_KU_AS_REP_ENC_PART,
334 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
336 krb5_encrypt_EncryptedData(context,
338 KRB5_KU_TGS_REP_ENC_PART_SESSION,
344 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
346 krb5_crypto_destroy(context, crypto);
348 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
349 krb5_get_err_text(context, ret));
352 if(buf_size != len) {
354 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
355 *e_text = "KDC internal error";
356 return KRB5KRB_ERR_GENERIC;
359 reply->length = buf_size;
363 static krb5_error_code
364 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
366 ent->etype = key->key.keytype;
369 ALLOC(ent->salttype);
371 if(key->salt->type == hdb_pw_salt)
372 *ent->salttype = 0; /* or 1? or NULL? */
373 else if(key->salt->type == hdb_afs3_salt)
376 kdc_log(context, config, 0, "unknown salt-type: %d",
378 return KRB5KRB_ERR_GENERIC;
380 /* according to `the specs', we can't send a salt if
381 we have AFS3 salted key, but that requires that you
382 *know* what cell you are using (e.g by assuming
383 that the cell is the same as the realm in lower
386 ALLOC(ent->salttype);
387 *ent->salttype = key->salt->type;
390 * We shouldn't sent salttype since its incompatible with the
391 * specification and its break windows clients. The afs
392 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
393 * implemented in Heimdal 0.7 and later.
395 ent->salttype = NULL;
397 krb5_copy_data(context, &key->salt->salt,
400 /* we return no salt type at all, as that should indicate
401 * the default salt type and make everybody happy. some
402 * systems (like w2k) dislike being told the salt type
405 ent->salttype = NULL;
411 static krb5_error_code
412 get_pa_etype_info(krb5_context context,
413 krb5_kdc_configuration *config,
414 METHOD_DATA *md, hdb_entry *client,
415 ENCTYPE *etypes, unsigned int etypes_len)
417 krb5_error_code ret = 0;
425 pa.len = client->keys.len;
426 if(pa.len > UINT_MAX/sizeof(*pa.val))
428 pa.val = malloc(pa.len * sizeof(*pa.val));
431 memset(pa.val, 0, pa.len * sizeof(*pa.val));
433 for(j = 0; j < etypes_len; j++) {
434 for (i = 0; i < n; i++)
435 if (pa.val[i].etype == etypes[j])
437 for(i = 0; i < client->keys.len; i++) {
438 if(client->keys.val[i].key.keytype == etypes[j]) {
439 if (krb5_enctype_valid(context, etypes[j]) != 0)
441 if((ret = make_etype_info_entry(context,
443 &client->keys.val[i])) != 0) {
444 free_ETYPE_INFO(&pa);
451 for(i = 0; i < client->keys.len; i++) {
452 for(j = 0; j < etypes_len; j++) {
453 if(client->keys.val[i].key.keytype == etypes[j])
456 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
458 if((ret = make_etype_info_entry(context,
460 &client->keys.val[i])) != 0) {
461 free_ETYPE_INFO(&pa);
469 ret = krb5_unparse_name(context, client->principal, &name);
471 name = "<unparse_name failed>";
472 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
479 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
480 free_ETYPE_INFO(&pa);
483 ret = realloc_method_data(md);
488 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
489 md->val[md->len - 1].padata_value.length = len;
490 md->val[md->len - 1].padata_value.data = buf;
498 extern int _krb5_AES_string_to_default_iterator;
500 static krb5_error_code
501 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
503 ent->etype = key->key.keytype;
506 if (ent->salt == NULL)
508 *ent->salt = malloc(key->salt->salt.length + 1);
509 if (*ent->salt == NULL) {
514 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
515 (*ent->salt)[key->salt->salt.length] = '\0';
519 ent->s2kparams = NULL;
521 switch (key->key.keytype) {
522 case ETYPE_AES128_CTS_HMAC_SHA1_96:
523 case ETYPE_AES256_CTS_HMAC_SHA1_96:
524 ALLOC(ent->s2kparams);
525 if (ent->s2kparams == NULL)
527 ent->s2kparams->length = 4;
528 ent->s2kparams->data = malloc(ent->s2kparams->length);
529 if (ent->s2kparams->data == NULL) {
530 free(ent->s2kparams);
531 ent->s2kparams = NULL;
534 _krb5_put_int(ent->s2kparams->data,
535 _krb5_AES_string_to_default_iterator,
536 ent->s2kparams->length);
538 case ETYPE_DES_CBC_CRC:
539 case ETYPE_DES_CBC_MD4:
540 case ETYPE_DES_CBC_MD5:
541 /* Check if this was a AFS3 salted key */
542 if(key->salt && key->salt->type == hdb_afs3_salt){
543 ALLOC(ent->s2kparams);
544 if (ent->s2kparams == NULL)
546 ent->s2kparams->length = 1;
547 ent->s2kparams->data = malloc(ent->s2kparams->length);
548 if (ent->s2kparams->data == NULL) {
549 free(ent->s2kparams);
550 ent->s2kparams = NULL;
553 _krb5_put_int(ent->s2kparams->data,
555 ent->s2kparams->length);
565 * Return 1 if the client have only older enctypes, this is for
566 * determining if the server should send ETYPE_INFO2 or not.
570 only_older_enctype_p(const KDC_REQ *req)
574 for(i = 0; i < req->req_body.etype.len; i++) {
575 switch (req->req_body.etype.val[i]) {
576 case ETYPE_DES_CBC_CRC:
577 case ETYPE_DES_CBC_MD4:
578 case ETYPE_DES_CBC_MD5:
579 case ETYPE_DES3_CBC_SHA1:
580 case ETYPE_ARCFOUR_HMAC_MD5:
581 case ETYPE_ARCFOUR_HMAC_MD5_56:
594 static krb5_error_code
595 get_pa_etype_info2(krb5_context context,
596 krb5_kdc_configuration *config,
597 METHOD_DATA *md, hdb_entry *client,
598 ENCTYPE *etypes, unsigned int etypes_len)
600 krb5_error_code ret = 0;
607 pa.len = client->keys.len;
608 if(pa.len > UINT_MAX/sizeof(*pa.val))
610 pa.val = malloc(pa.len * sizeof(*pa.val));
613 memset(pa.val, 0, pa.len * sizeof(*pa.val));
615 for(j = 0; j < etypes_len; j++) {
616 for (i = 0; i < n; i++)
617 if (pa.val[i].etype == etypes[j])
619 for(i = 0; i < client->keys.len; i++) {
620 if(client->keys.val[i].key.keytype == etypes[j]) {
621 if (krb5_enctype_valid(context, etypes[j]) != 0)
623 if((ret = make_etype_info2_entry(&pa.val[n++],
624 &client->keys.val[i])) != 0) {
625 free_ETYPE_INFO2(&pa);
632 for(i = 0; i < client->keys.len; i++) {
633 for(j = 0; j < etypes_len; j++) {
634 if(client->keys.val[i].key.keytype == etypes[j])
637 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
639 if((ret = make_etype_info2_entry(&pa.val[n++],
640 &client->keys.val[i])) != 0) {
641 free_ETYPE_INFO2(&pa);
649 ret = krb5_unparse_name(context, client->principal, &name);
651 name = "<unparse_name failed>";
652 kdc_log(context, config, 0,
653 "internal error in get_pa_etype_info2(%s): %d != %d",
660 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
661 free_ETYPE_INFO2(&pa);
664 ret = realloc_method_data(md);
669 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
670 md->val[md->len - 1].padata_value.length = len;
671 md->val[md->len - 1].padata_value.data = buf;
676 * verify the flags on `client' and `server', returning 0
677 * if they are OK and generating an error messages and returning
678 * and error code otherwise.
682 _kdc_check_flags(krb5_context context,
683 krb5_kdc_configuration *config,
684 hdb_entry_ex *client_ex, const char *client_name,
685 hdb_entry_ex *server_ex, const char *server_name,
686 krb5_boolean is_as_req)
688 if(client_ex != NULL) {
689 hdb_entry *client = &client_ex->entry;
692 if (client->flags.invalid) {
693 kdc_log(context, config, 0,
694 "Client (%s) has invalid bit set", client_name);
695 return KRB5KDC_ERR_POLICY;
698 if(!client->flags.client){
699 kdc_log(context, config, 0,
700 "Principal may not act as client -- %s", client_name);
701 return KRB5KDC_ERR_POLICY;
704 if (client->valid_start && *client->valid_start > kdc_time) {
705 char starttime_str[100];
706 krb5_format_time(context, *client->valid_start,
707 starttime_str, sizeof(starttime_str), TRUE);
708 kdc_log(context, config, 0,
709 "Client not yet valid until %s -- %s",
710 starttime_str, client_name);
711 return KRB5KDC_ERR_CLIENT_NOTYET;
714 if (client->valid_end && *client->valid_end < kdc_time) {
715 char endtime_str[100];
716 krb5_format_time(context, *client->valid_end,
717 endtime_str, sizeof(endtime_str), TRUE);
718 kdc_log(context, config, 0,
719 "Client expired at %s -- %s",
720 endtime_str, client_name);
721 return KRB5KDC_ERR_NAME_EXP;
724 if (client->pw_end && *client->pw_end < kdc_time
725 && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
727 krb5_format_time(context, *client->pw_end,
728 pwend_str, sizeof(pwend_str), TRUE);
729 kdc_log(context, config, 0,
730 "Client's key has expired at %s -- %s",
731 pwend_str, client_name);
732 return KRB5KDC_ERR_KEY_EXPIRED;
738 if (server_ex != NULL) {
739 hdb_entry *server = &server_ex->entry;
741 if (server->flags.invalid) {
742 kdc_log(context, config, 0,
743 "Server has invalid flag set -- %s", server_name);
744 return KRB5KDC_ERR_POLICY;
747 if(!server->flags.server){
748 kdc_log(context, config, 0,
749 "Principal may not act as server -- %s", server_name);
750 return KRB5KDC_ERR_POLICY;
753 if(!is_as_req && server->flags.initial) {
754 kdc_log(context, config, 0,
755 "AS-REQ is required for server -- %s", server_name);
756 return KRB5KDC_ERR_POLICY;
759 if (server->valid_start && *server->valid_start > kdc_time) {
760 char starttime_str[100];
761 krb5_format_time(context, *server->valid_start,
762 starttime_str, sizeof(starttime_str), TRUE);
763 kdc_log(context, config, 0,
764 "Server not yet valid until %s -- %s",
765 starttime_str, server_name);
766 return KRB5KDC_ERR_SERVICE_NOTYET;
769 if (server->valid_end && *server->valid_end < kdc_time) {
770 char endtime_str[100];
771 krb5_format_time(context, *server->valid_end,
772 endtime_str, sizeof(endtime_str), TRUE);
773 kdc_log(context, config, 0,
774 "Server expired at %s -- %s",
775 endtime_str, server_name);
776 return KRB5KDC_ERR_SERVICE_EXP;
779 if (server->pw_end && *server->pw_end < kdc_time) {
781 krb5_format_time(context, *server->pw_end,
782 pwend_str, sizeof(pwend_str), TRUE);
783 kdc_log(context, config, 0,
784 "Server's key has expired at -- %s",
785 pwend_str, server_name);
786 return KRB5KDC_ERR_KEY_EXPIRED;
793 * Return TRUE if `from' is part of `addresses' taking into consideration
794 * the configuration variables that tells us how strict we should be about
799 check_addresses(krb5_context context,
800 krb5_kdc_configuration *config,
801 HostAddresses *addresses, const struct sockaddr *from)
806 krb5_boolean only_netbios = TRUE;
809 if(config->check_ticket_addresses == 0)
812 if(addresses == NULL)
813 return config->allow_null_ticket_addresses;
815 for (i = 0; i < addresses->len; ++i) {
816 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
817 only_netbios = FALSE;
821 /* Windows sends it's netbios name, which I can only assume is
822 * used for the 'allowed workstations' check. This is painful,
823 * but we still want to check IP addresses if they happen to be
828 return config->allow_null_ticket_addresses;
830 ret = krb5_sockaddr2address (context, from, &addr);
834 result = krb5_address_search(context, &addr, addresses);
835 krb5_free_address (context, &addr);
840 _kdc_as_rep(krb5_context context,
841 krb5_kdc_configuration *config,
843 const krb5_data *req_buffer,
846 struct sockaddr *from_addr)
848 KDC_REQ_BODY *b = &req->req_body;
850 KDCOptions f = b->kdc_options;
851 hdb_entry_ex *client = NULL, *server = NULL;
852 krb5_enctype cetype, setype;
855 krb5_principal client_princ = NULL, server_princ = NULL;
856 char *client_name = NULL, *server_name = NULL;
857 krb5_error_code ret = 0;
858 const char *e_text = NULL;
861 EncryptionKey *reply_key;
863 pk_client_params *pkp = NULL;
866 memset(&rep, 0, sizeof(rep));
868 if(b->sname == NULL){
869 ret = KRB5KRB_ERR_GENERIC;
870 e_text = "No server in request";
872 _krb5_principalname2krb5_principal (&server_princ,
873 *(b->sname), b->realm);
874 ret = krb5_unparse_name(context, server_princ, &server_name);
877 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
881 if(b->cname == NULL){
882 ret = KRB5KRB_ERR_GENERIC;
883 e_text = "No client in request";
885 _krb5_principalname2krb5_principal (&client_princ,
886 *(b->cname), b->realm);
887 ret = krb5_unparse_name(context, client_princ, &client_name);
890 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
894 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
895 client_name, from, server_name);
897 ret = _kdc_db_fetch(context, config, client_princ,
898 HDB_F_GET_CLIENT, &client);
900 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
901 krb5_get_err_text(context, ret));
902 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
906 ret = _kdc_db_fetch(context, config, server_princ,
907 HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, &server);
909 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
910 krb5_get_err_text(context, ret));
911 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
915 ret = _kdc_check_flags(context, config,
922 if (client->check_client_access) {
923 ret = client->check_client_access(context, client,
929 memset(&et, 0, sizeof(et));
930 memset(&ek, 0, sizeof(ek));
937 log_patypes(context, config, req->padata);
940 kdc_log(context, config, 5,
941 "Looking for PKINIT pa-data -- %s", client_name);
943 e_text = "No PKINIT PA found";
946 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
950 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
954 char *client_cert = NULL;
956 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
958 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
959 kdc_log(context, config, 5,
960 "Failed to decode PKINIT PA-DATA -- %s",
964 if (ret == 0 && pkp == NULL)
967 ret = _kdc_pk_check_client(context,
974 e_text = "PKINIT certificate not allowed to "
975 "impersonate principal";
976 _kdc_pk_free_client_param(context, pkp);
978 kdc_log(context, config, 0, "%s", e_text);
983 et.flags.pre_authent = 1;
984 kdc_log(context, config, 0,
985 "PKINIT pre-authentication succeeded -- %s using %s",
986 client_name, client_cert);
993 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
997 e_text = "No ENC-TS found";
998 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1002 EncryptedData enc_data;
1008 ret = decode_EncryptedData(pa->padata_value.data,
1009 pa->padata_value.length,
1013 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1014 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
1019 ret = hdb_enctype2key(context, &client->entry,
1020 enc_data.etype, &pa_key);
1023 e_text = "No key matches pa-data";
1024 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1025 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1028 kdc_log(context, config, 5,
1029 "No client key matching pa-data (%d) -- %s",
1030 enc_data.etype, client_name);
1032 kdc_log(context, config, 5,
1033 "No client key matching pa-data (%s) -- %s",
1037 free_EncryptedData(&enc_data);
1042 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1044 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1045 krb5_get_err_text(context, ret));
1046 free_EncryptedData(&enc_data);
1050 ret = krb5_decrypt_EncryptedData (context,
1052 KRB5_KU_PA_ENC_TIMESTAMP,
1055 krb5_crypto_destroy(context, crypto);
1057 krb5_error_code ret2;
1058 ret2 = krb5_enctype_to_string(context,
1059 pa_key->key.keytype, &str);
1062 kdc_log(context, config, 5,
1063 "Failed to decrypt PA-DATA -- %s "
1064 "(enctype %s) error %s",
1066 str ? str : "unknown enctype",
1067 krb5_get_err_text(context, ret));
1070 if(hdb_next_enctype2key(context, &client->entry,
1071 enc_data.etype, &pa_key) == 0)
1073 e_text = "Failed to decrypt PA-DATA";
1075 free_EncryptedData(&enc_data);
1076 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1079 free_EncryptedData(&enc_data);
1080 ret = decode_PA_ENC_TS_ENC(ts_data.data,
1084 krb5_data_free(&ts_data);
1086 e_text = "Failed to decode PA-ENC-TS-ENC";
1087 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1088 kdc_log(context, config,
1089 5, "Failed to decode PA-ENC-TS_ENC -- %s",
1093 free_PA_ENC_TS_ENC(&p);
1094 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1095 ret = KRB5KRB_AP_ERR_SKEW;
1096 kdc_log(context, config, 0,
1097 "Too large time skew -- %s", client_name);
1099 * the following is needed to make windows clients
1100 * to retry using the timestamp in the error message
1102 * this is maybe a bug in windows to not trying when e_text
1108 et.flags.pre_authent = 1;
1110 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1114 kdc_log(context, config, 2,
1115 "ENC-TS Pre-authentication succeeded -- %s using %s",
1116 client_name, str ? str : "unknown enctype");
1123 if(found_pa == 0 && config->require_preauth)
1125 /* We come here if we found a pa-enc-timestamp, but if there
1126 was some problem with it, other than too large skew */
1127 if(found_pa && et.flags.pre_authent == 0){
1128 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1132 }else if (config->require_preauth
1133 || client->entry.flags.require_preauth
1134 || server->entry.flags.require_preauth) {
1135 METHOD_DATA method_data;
1142 method_data.len = 0;
1143 method_data.val = NULL;
1145 ret = realloc_method_data(&method_data);
1146 pa = &method_data.val[method_data.len-1];
1147 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
1148 pa->padata_value.length = 0;
1149 pa->padata_value.data = NULL;
1152 ret = realloc_method_data(&method_data);
1153 pa = &method_data.val[method_data.len-1];
1154 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
1155 pa->padata_value.length = 0;
1156 pa->padata_value.data = NULL;
1161 * - If the client only knows about old enctypes, then send
1162 * both info replies (we send 'info' first in the list).
1163 * - If the client is 'modern', because it knows about 'new'
1164 * enctype types, then only send the 'info2' reply.
1168 if (only_older_enctype_p(req))
1169 ret = get_pa_etype_info(context, config,
1170 &method_data, &client->entry,
1171 b->etype.val, b->etype.len);
1173 ret = get_pa_etype_info2(context, config, &method_data,
1174 &client->entry, b->etype.val, b->etype.len);
1177 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1178 free_METHOD_DATA(&method_data);
1179 foo_data.data = buf;
1180 foo_data.length = len;
1182 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1183 krb5_mk_error(context,
1185 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1193 kdc_log(context, config, 0,
1194 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1200 ret = find_keys(context, config,
1201 client, client_name,
1202 server, server_name,
1203 &ckey, &cetype, &skey, &setype,
1204 b->etype.val, b->etype.len);
1209 struct rk_strpool *p = NULL;
1213 for (i = 0; i < b->etype.len; i++) {
1214 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1216 p = rk_strpoolprintf(p, "%s", str);
1219 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1220 if (p && i + 1 < b->etype.len)
1221 p = rk_strpoolprintf(p, ", ");
1223 kdc_log(context, config, 0, "out of memory");
1228 p = rk_strpoolprintf(p, "no encryption types");
1230 str = rk_strpoolcollect(p);
1231 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1238 ret = krb5_enctype_to_string(context, cetype, &cet);
1240 ret = krb5_enctype_to_string(context, setype, &set);
1242 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1248 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1253 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1256 kdc_log(context, config, 2, "Requested flags: %s", str);
1260 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1261 || (f.request_anonymous && !config->allow_anonymous)) {
1262 ret = KRB5KDC_ERR_BADOPTION;
1263 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1268 rep.msg_type = krb_as_rep;
1269 copy_Realm(&client->entry.principal->realm, &rep.crealm);
1270 if (f.request_anonymous)
1271 make_anonymous_principalname (&rep.cname);
1273 _krb5_principal2principalname(&rep.cname,
1274 client->entry.principal);
1275 rep.ticket.tkt_vno = 5;
1276 copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1277 _krb5_principal2principalname(&rep.ticket.sname,
1278 server->entry.principal);
1280 et.flags.initial = 1;
1281 if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1282 et.flags.forwardable = f.forwardable;
1283 else if (f.forwardable) {
1284 ret = KRB5KDC_ERR_POLICY;
1285 kdc_log(context, config, 0,
1286 "Ticket may not be forwardable -- %s", client_name);
1289 if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1290 et.flags.proxiable = f.proxiable;
1291 else if (f.proxiable) {
1292 ret = KRB5KDC_ERR_POLICY;
1293 kdc_log(context, config, 0,
1294 "Ticket may not be proxiable -- %s", client_name);
1297 if(client->entry.flags.postdate && server->entry.flags.postdate)
1298 et.flags.may_postdate = f.allow_postdate;
1299 else if (f.allow_postdate){
1300 ret = KRB5KDC_ERR_POLICY;
1301 kdc_log(context, config, 0,
1302 "Ticket may not be postdatable -- %s", client_name);
1306 /* check for valid set of addresses */
1307 if(!check_addresses(context, config, b->addresses, from_addr)) {
1308 ret = KRB5KRB_AP_ERR_BADADDR;
1309 kdc_log(context, config, 0,
1310 "Bad address list requested -- %s", client_name);
1314 krb5_generate_random_keyblock(context, setype, &et.key);
1315 copy_PrincipalName(&rep.cname, &et.cname);
1316 copy_Realm(&rep.crealm, &et.crealm);
1322 start = et.authtime = kdc_time;
1324 if(f.postdated && req->req_body.from){
1325 ALLOC(et.starttime);
1326 start = *et.starttime = *req->req_body.from;
1327 et.flags.invalid = 1;
1328 et.flags.postdated = 1; /* XXX ??? */
1333 /* be careful not overflowing */
1335 if(client->entry.max_life)
1336 t = start + min(t - start, *client->entry.max_life);
1337 if(server->entry.max_life)
1338 t = start + min(t - start, *server->entry.max_life);
1340 t = min(t, start + realm->max_life);
1343 if(f.renewable_ok && et.endtime < *b->till){
1345 if(b->rtime == NULL){
1349 if(*b->rtime < *b->till)
1350 *b->rtime = *b->till;
1352 if(f.renewable && b->rtime){
1356 if(client->entry.max_renew)
1357 t = start + min(t - start, *client->entry.max_renew);
1358 if(server->entry.max_renew)
1359 t = start + min(t - start, *server->entry.max_renew);
1361 t = min(t, start + realm->max_renew);
1363 ALLOC(et.renew_till);
1365 et.flags.renewable = 1;
1369 if (f.request_anonymous)
1370 et.flags.anonymous = 1;
1374 copy_HostAddresses(b->addresses, et.caddr);
1377 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1378 krb5_data_zero(&et.transited.contents);
1380 copy_EncryptionKey(&et.key, &ek.key);
1382 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1383 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1384 * incapable of correctly decoding SEQUENCE OF's of zero length.
1386 * To fix this, always send at least one no-op last_req
1388 * If there's a pw_end or valid_end we will use that,
1389 * otherwise just a dummy lr.
1391 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1392 ek.last_req.len = 0;
1393 if (client->entry.pw_end
1394 && (config->kdc_warn_pwexpire == 0
1395 || kdc_time + config->kdc_warn_pwexpire <= *client->entry.pw_end)) {
1396 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1397 ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1400 if (client->entry.valid_end) {
1401 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1402 ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1405 if (ek.last_req.len == 0) {
1406 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1407 ek.last_req.val[ek.last_req.len].lr_value = 0;
1410 ek.nonce = b->nonce;
1411 if (client->entry.valid_end || client->entry.pw_end) {
1412 ALLOC(ek.key_expiration);
1413 if (client->entry.valid_end) {
1414 if (client->entry.pw_end)
1415 *ek.key_expiration = min(*client->entry.valid_end,
1416 *client->entry.pw_end);
1418 *ek.key_expiration = *client->entry.valid_end;
1420 *ek.key_expiration = *client->entry.pw_end;
1422 ek.key_expiration = NULL;
1423 ek.flags = et.flags;
1424 ek.authtime = et.authtime;
1426 ALLOC(ek.starttime);
1427 *ek.starttime = *et.starttime;
1429 ek.endtime = et.endtime;
1430 if (et.renew_till) {
1431 ALLOC(ek.renew_till);
1432 *ek.renew_till = *et.renew_till;
1434 copy_Realm(&rep.ticket.realm, &ek.srealm);
1435 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1438 copy_HostAddresses(et.caddr, ek.caddr);
1442 rep.padata->len = 0;
1443 rep.padata->val = NULL;
1445 reply_key = &ckey->key;
1448 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1450 &reply_key, rep.padata);
1456 set_salt_padata (rep.padata, ckey->salt);
1458 if (rep.padata->len == 0) {
1463 /* Add the PAC, via a HDB abstraction */
1464 if (client->authz_data_as_req) {
1465 ret = client->authz_data_as_req(context, client,
1470 &et.authorization_data);
1475 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1476 et.endtime, et.renew_till);
1478 ret = encode_reply(context, config,
1479 &rep, &et, &ek, setype, server->entry.kvno, &skey->key,
1480 client->entry.kvno, reply_key, &e_text, reply);
1481 free_EncTicketPart(&et);
1482 free_EncKDCRepPart(&ek);
1486 krb5_mk_error(context,
1500 _kdc_pk_free_client_param(context, pkp);
1503 krb5_free_principal(context, client_princ);
1506 krb5_free_principal(context, server_princ);
1509 _kdc_free_ent(context, client);
1511 _kdc_free_ent(context, server);
1516 static krb5_error_code
1517 check_tgs_flags(krb5_context context,
1518 krb5_kdc_configuration *config,
1519 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1521 KDCOptions f = b->kdc_options;
1524 if(!tgt->flags.invalid || tgt->starttime == NULL){
1525 kdc_log(context, config, 0,
1526 "Bad request to validate ticket");
1527 return KRB5KDC_ERR_BADOPTION;
1529 if(*tgt->starttime > kdc_time){
1530 kdc_log(context, config, 0,
1531 "Early request to validate ticket");
1532 return KRB5KRB_AP_ERR_TKT_NYV;
1535 et->flags.invalid = 0;
1536 }else if(tgt->flags.invalid){
1537 kdc_log(context, config, 0,
1538 "Ticket-granting ticket has INVALID flag set");
1539 return KRB5KRB_AP_ERR_TKT_INVALID;
1543 if(!tgt->flags.forwardable){
1544 kdc_log(context, config, 0,
1545 "Bad request for forwardable ticket");
1546 return KRB5KDC_ERR_BADOPTION;
1548 et->flags.forwardable = 1;
1551 if(!tgt->flags.forwardable){
1552 kdc_log(context, config, 0,
1553 "Request to forward non-forwardable ticket");
1554 return KRB5KDC_ERR_BADOPTION;
1556 et->flags.forwarded = 1;
1557 et->caddr = b->addresses;
1559 if(tgt->flags.forwarded)
1560 et->flags.forwarded = 1;
1563 if(!tgt->flags.proxiable){
1564 kdc_log(context, config, 0,
1565 "Bad request for proxiable ticket");
1566 return KRB5KDC_ERR_BADOPTION;
1568 et->flags.proxiable = 1;
1571 if(!tgt->flags.proxiable){
1572 kdc_log(context, config, 0,
1573 "Request to proxy non-proxiable ticket");
1574 return KRB5KDC_ERR_BADOPTION;
1576 et->flags.proxy = 1;
1577 et->caddr = b->addresses;
1579 if(tgt->flags.proxy)
1580 et->flags.proxy = 1;
1582 if(f.allow_postdate){
1583 if(!tgt->flags.may_postdate){
1584 kdc_log(context, config, 0,
1585 "Bad request for post-datable ticket");
1586 return KRB5KDC_ERR_BADOPTION;
1588 et->flags.may_postdate = 1;
1591 if(!tgt->flags.may_postdate){
1592 kdc_log(context, config, 0,
1593 "Bad request for postdated ticket");
1594 return KRB5KDC_ERR_BADOPTION;
1597 *et->starttime = *b->from;
1598 et->flags.postdated = 1;
1599 et->flags.invalid = 1;
1600 }else if(b->from && *b->from > kdc_time + context->max_skew){
1601 kdc_log(context, config, 0, "Ticket cannot be postdated");
1602 return KRB5KDC_ERR_CANNOT_POSTDATE;
1606 if(!tgt->flags.renewable){
1607 kdc_log(context, config, 0,
1608 "Bad request for renewable ticket");
1609 return KRB5KDC_ERR_BADOPTION;
1611 et->flags.renewable = 1;
1612 ALLOC(et->renew_till);
1613 fix_time(&b->rtime);
1614 *et->renew_till = *b->rtime;
1618 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1619 kdc_log(context, config, 0,
1620 "Request to renew non-renewable ticket");
1621 return KRB5KDC_ERR_BADOPTION;
1623 old_life = tgt->endtime;
1625 old_life -= *tgt->starttime;
1627 old_life -= tgt->authtime;
1628 et->endtime = *et->starttime + old_life;
1629 if (et->renew_till != NULL)
1630 et->endtime = min(*et->renew_till, et->endtime);
1633 /* checks for excess flags */
1634 if(f.request_anonymous && !config->allow_anonymous){
1635 kdc_log(context, config, 0,
1636 "Request for anonymous ticket");
1637 return KRB5KDC_ERR_BADOPTION;
1642 static krb5_error_code
1643 fix_transited_encoding(krb5_context context,
1644 krb5_kdc_configuration *config,
1645 krb5_boolean check_policy,
1646 TransitedEncoding *tr,
1648 const char *client_realm,
1649 const char *server_realm,
1650 const char *tgt_realm)
1652 krb5_error_code ret = 0;
1653 char **realms, **tmp;
1657 switch (tr->tr_type) {
1658 case DOMAIN_X500_COMPRESS:
1662 * Allow empty content of type 0 because that is was Microsoft
1663 * generates in their TGT.
1665 if (tr->contents.length == 0)
1667 kdc_log(context, config, 0,
1668 "Transited type 0 with non empty content");
1669 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1671 kdc_log(context, config, 0,
1672 "Unknown transited type: %u", tr->tr_type);
1673 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1676 ret = krb5_domain_x500_decode(context,
1683 krb5_warn(context, ret,
1684 "Decoding transited encoding");
1687 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1688 /* not us, so add the previous realm to transited set */
1689 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1693 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1699 realms[num_realms] = strdup(tgt_realm);
1700 if(realms[num_realms] == NULL){
1706 if(num_realms == 0) {
1707 if(strcmp(client_realm, server_realm))
1708 kdc_log(context, config, 0,
1709 "cross-realm %s -> %s", client_realm, server_realm);
1713 for(i = 0; i < num_realms; i++)
1714 l += strlen(realms[i]) + 2;
1718 for(i = 0; i < num_realms; i++) {
1720 strlcat(rs, ", ", l);
1721 strlcat(rs, realms[i], l);
1723 kdc_log(context, config, 0,
1724 "cross-realm %s -> %s via [%s]",
1725 client_realm, server_realm, rs);
1730 ret = krb5_check_transited(context, client_realm,
1732 realms, num_realms, NULL);
1734 krb5_warn(context, ret, "cross-realm %s -> %s",
1735 client_realm, server_realm);
1738 et->flags.transited_policy_checked = 1;
1740 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1741 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1743 krb5_warn(context, ret, "Encoding transited encoding");
1745 for(i = 0; i < num_realms; i++)
1752 static krb5_error_code
1753 tgs_make_reply(krb5_context context,
1754 krb5_kdc_configuration *config,
1757 EncTicketPart *adtkt,
1758 AuthorizationData *auth_data,
1759 krb5_ticket *tgs_ticket,
1760 hdb_entry_ex *server,
1761 const char *server_name,
1762 hdb_entry_ex *client,
1763 krb5_principal client_principal,
1764 hdb_entry_ex *krbtgt,
1765 EncryptionKey *tgtkey,
1766 krb5_enctype cetype,
1767 const char **e_text,
1773 KDCOptions f = b->kdc_options;
1774 krb5_error_code ret;
1777 EncryptionKey *ekey;
1778 AuthorizationData *new_auth_data = NULL;
1783 for(i = 0; i < b->etype.len; i++)
1784 if (b->etype.val[i] == adtkt->key.keytype)
1786 if(i == b->etype.len) {
1787 krb5_clear_error_string(context);
1788 return KRB5KDC_ERR_ETYPE_NOSUPP;
1790 etype = b->etype.val[i];
1792 ret = find_keys(context, config,
1793 NULL, NULL, server, server_name,
1794 NULL, NULL, &skey, &etype,
1795 b->etype.val, b->etype.len);
1801 memset(&rep, 0, sizeof(rep));
1802 memset(&et, 0, sizeof(et));
1803 memset(&ek, 0, sizeof(ek));
1806 rep.msg_type = krb_tgs_rep;
1808 et.authtime = tgt->authtime;
1810 et.endtime = min(tgt->endtime, *b->till);
1811 ALLOC(et.starttime);
1812 *et.starttime = kdc_time;
1814 ret = check_tgs_flags(context, config, b, tgt, &et);
1818 /* We should check the transited encoding if:
1819 1) the request doesn't ask not to be checked
1820 2) globally enforcing a check
1821 3) principal requires checking
1822 4) we allow non-check per-principal, but principal isn't marked as allowing this
1823 5) we don't globally allow this
1826 #define GLOBAL_FORCE_TRANSITED_CHECK \
1827 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1828 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1829 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1830 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1831 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1833 /* these will consult the database in future release */
1834 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1835 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1837 ret = fix_transited_encoding(context, config,
1838 !f.disable_transited_check ||
1839 GLOBAL_FORCE_TRANSITED_CHECK ||
1840 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1841 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1842 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1843 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1844 &tgt->transited, &et,
1845 *krb5_princ_realm(context, client_principal),
1846 *krb5_princ_realm(context, server->entry.principal),
1847 *krb5_princ_realm(context, krbtgt->entry.principal));
1851 copy_Realm(krb5_princ_realm(context, server->entry.principal),
1853 _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
1854 copy_Realm(&tgt->crealm, &rep.crealm);
1855 if (f.request_anonymous)
1856 make_anonymous_principalname (&tgt->cname);
1858 copy_PrincipalName(&tgt->cname, &rep.cname);
1859 rep.ticket.tkt_vno = 5;
1861 ek.caddr = et.caddr;
1862 if(et.caddr == NULL)
1863 et.caddr = tgt->caddr;
1867 life = et.endtime - *et.starttime;
1868 if(client && client->entry.max_life)
1869 life = min(life, *client->entry.max_life);
1870 if(server->entry.max_life)
1871 life = min(life, *server->entry.max_life);
1872 et.endtime = *et.starttime + life;
1874 if(f.renewable_ok && tgt->flags.renewable &&
1875 et.renew_till == NULL && et.endtime < *b->till){
1876 et.flags.renewable = 1;
1877 ALLOC(et.renew_till);
1878 *et.renew_till = *b->till;
1882 renew = *et.renew_till - et.authtime;
1883 if(client && client->entry.max_renew)
1884 renew = min(renew, *client->entry.max_renew);
1885 if(server->entry.max_renew)
1886 renew = min(renew, *server->entry.max_renew);
1887 *et.renew_till = et.authtime + renew;
1891 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1892 *et.starttime = min(*et.starttime, *et.renew_till);
1893 et.endtime = min(et.endtime, *et.renew_till);
1896 *et.starttime = min(*et.starttime, et.endtime);
1898 if(*et.starttime == et.endtime){
1899 ret = KRB5KDC_ERR_NEVER_VALID;
1902 if(et.renew_till && et.endtime == *et.renew_till){
1903 free(et.renew_till);
1904 et.renew_till = NULL;
1905 et.flags.renewable = 0;
1908 et.flags.pre_authent = tgt->flags.pre_authent;
1909 et.flags.hw_authent = tgt->flags.hw_authent;
1910 et.flags.anonymous = tgt->flags.anonymous;
1911 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
1914 krb5_generate_random_keyblock(context, etype, &et.key);
1916 if (server->authz_data_tgs_req) {
1917 ret = server->authz_data_tgs_req(context, server,
1919 tgs_ticket->ticket.authorization_data,
1920 tgs_ticket->ticket.authtime,
1926 new_auth_data = NULL;
1930 /* XXX Check enc-authorization-data */
1931 et.authorization_data = new_auth_data;
1933 et.crealm = tgt->crealm;
1934 et.cname = tgt->cname;
1937 /* MIT must have at least one last_req */
1938 ek.last_req.len = 1;
1939 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1940 ek.nonce = b->nonce;
1941 ek.flags = et.flags;
1942 ek.authtime = et.authtime;
1943 ek.starttime = et.starttime;
1944 ek.endtime = et.endtime;
1945 ek.renew_till = et.renew_till;
1946 ek.srealm = rep.ticket.realm;
1947 ek.sname = rep.ticket.sname;
1949 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1950 et.endtime, et.renew_till);
1952 /* It is somewhat unclear where the etype in the following
1953 encryption should come from. What we have is a session
1954 key in the passed tgt, and a list of preferred etypes
1955 *for the new ticket*. Should we pick the best possible
1956 etype, given the keytype in the tgt, or should we look
1957 at the etype list here as well? What if the tgt
1958 session key is DES3 and we want a ticket with a (say)
1959 CAST session key. Should the DES3 etype be added to the
1960 etype list, even if we don't want a session key with
1962 ret = encode_reply(context, config,
1963 &rep, &et, &ek, etype, adtkt ? 0 : server->entry.kvno,
1964 ekey, 0, &tgt->key, e_text, reply);
1967 free_TransitedEncoding(&et.transited);
1971 free(et.renew_till);
1972 free_LastReq(&ek.last_req);
1973 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1974 free_EncryptionKey(&et.key);
1978 static krb5_error_code
1979 tgs_check_authenticator(krb5_context context,
1980 krb5_kdc_configuration *config,
1981 krb5_auth_context ac,
1983 const char **e_text,
1986 krb5_authenticator auth;
1990 krb5_error_code ret;
1993 krb5_auth_con_getauthenticator(context, ac, &auth);
1994 if(auth->cksum == NULL){
1995 kdc_log(context, config, 0, "No authenticator in request");
1996 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
2000 * according to RFC1510 it doesn't need to be keyed,
2001 * but according to the latest draft it needs to.
2005 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
2008 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
2009 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
2010 auth->cksum->cksumtype);
2011 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
2015 /* XXX should not re-encode this */
2016 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
2018 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
2019 krb5_get_err_text(context, ret));
2022 if(buf_size != len) {
2024 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
2025 *e_text = "KDC internal error";
2026 ret = KRB5KRB_ERR_GENERIC;
2029 ret = krb5_crypto_init(context, key, 0, &crypto);
2032 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2033 krb5_get_err_text(context, ret));
2036 ret = krb5_verify_checksum(context,
2038 KRB5_KU_TGS_REQ_AUTH_CKSUM,
2043 krb5_crypto_destroy(context, crypto);
2045 kdc_log(context, config, 0,
2046 "Failed to verify authenticator checksum: %s",
2047 krb5_get_err_text(context, ret));
2050 free_Authenticator(auth);
2056 * return the realm of a krbtgt-ticket or NULL
2060 get_krbtgt_realm(const PrincipalName *p)
2062 if(p->name_string.len == 2
2063 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
2064 return p->name_string.val[1];
2070 find_rpath(krb5_context context, Realm crealm, Realm srealm)
2072 const char *new_realm = krb5_config_get_string(context,
2083 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
2085 if(server->name.name_type != KRB5_NT_SRV_INST ||
2086 server->name.name_string.len != 2)
2089 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
2090 FALSE, realms) == 0;
2093 static krb5_error_code
2094 tgs_rep2(krb5_context context,
2095 krb5_kdc_configuration *config,
2100 const struct sockaddr *from_addr,
2105 krb5_error_code ret;
2106 krb5_principal princ;
2107 krb5_auth_context ac = NULL;
2108 krb5_ticket *ticket = NULL;
2109 krb5_flags ap_req_options;
2110 krb5_flags verify_ap_req_flags;
2111 const char *e_text = NULL;
2114 hdb_entry_ex *krbtgt = NULL;
2117 krb5_enctype cetype;
2118 krb5_principal cp = NULL;
2119 krb5_principal sp = NULL;
2120 AuthorizationData *auth_data = NULL;
2125 memset(&ap_req, 0, sizeof(ap_req));
2126 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2128 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
2129 krb5_get_err_text(context, ret));
2133 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2134 /* XXX check for ticket.sname == req.sname */
2135 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2136 ret = KRB5KDC_ERR_POLICY; /* ? */
2140 _krb5_principalname2krb5_principal(&princ,
2141 ap_req.ticket.sname,
2142 ap_req.ticket.realm);
2144 ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, &krbtgt);
2148 ret = krb5_unparse_name(context, princ, &p);
2150 p = "<unparse_name failed>";
2151 krb5_free_principal(context, princ);
2152 kdc_log(context, config, 0,
2153 "Ticket-granting ticket not found in database: %s: %s",
2154 p, krb5_get_err_text(context, ret));
2157 ret = KRB5KRB_AP_ERR_NOT_US;
2161 if(ap_req.ticket.enc_part.kvno &&
2162 *ap_req.ticket.enc_part.kvno != krbtgt->entry.kvno){
2165 ret = krb5_unparse_name (context, princ, &p);
2166 krb5_free_principal(context, princ);
2168 p = "<unparse_name failed>";
2169 kdc_log(context, config, 0,
2170 "Ticket kvno = %d, DB kvno = %d (%s)",
2171 *ap_req.ticket.enc_part.kvno,
2176 ret = KRB5KRB_AP_ERR_BADKEYVER;
2180 ret = hdb_enctype2key(context, &krbtgt->entry,
2181 ap_req.ticket.enc_part.etype, &tkey);
2184 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2185 krb5_unparse_name(context, princ, &p);
2186 kdc_log(context, config, 0,
2187 "No server key with enctype %s found for %s", str, p);
2190 ret = KRB5KRB_AP_ERR_BADKEYVER;
2194 if (b->kdc_options.validate)
2195 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2197 verify_ap_req_flags = 0;
2199 ret = krb5_verify_ap_req2(context,
2204 verify_ap_req_flags,
2207 KRB5_KU_TGS_REQ_AUTH);
2209 krb5_free_principal(context, princ);
2211 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2212 krb5_get_err_text(context, ret));
2217 krb5_authenticator auth;
2219 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2221 *csec = malloc(sizeof(**csec));
2222 if (*csec == NULL) {
2223 krb5_free_authenticator(context, &auth);
2224 kdc_log(context, config, 0, "malloc failed");
2227 **csec = auth->ctime;
2228 *cusec = malloc(sizeof(**cusec));
2229 if (*cusec == NULL) {
2230 krb5_free_authenticator(context, &auth);
2231 kdc_log(context, config, 0, "malloc failed");
2234 **csec = auth->cusec;
2235 krb5_free_authenticator(context, &auth);
2239 cetype = ap_req.authenticator.etype;
2241 tgt = &ticket->ticket;
2243 ret = tgs_check_authenticator(context, config,
2244 ac, b, &e_text, &tgt->key);
2246 krb5_auth_con_free(context, ac);
2250 if (b->enc_authorization_data) {
2251 krb5_keyblock *subkey;
2253 ret = krb5_auth_con_getremotesubkey(context,
2257 krb5_auth_con_free(context, ac);
2258 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2259 krb5_get_err_text(context, ret));
2263 ret = krb5_auth_con_getkey(context, ac, &subkey);
2265 krb5_auth_con_free(context, ac);
2266 kdc_log(context, config, 0, "Failed to get session key: %s",
2267 krb5_get_err_text(context, ret));
2272 krb5_auth_con_free(context, ac);
2273 kdc_log(context, config, 0,
2274 "Failed to get key for enc-authorization-data");
2275 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2278 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2280 krb5_auth_con_free(context, ac);
2281 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2282 krb5_get_err_text(context, ret));
2285 ret = krb5_decrypt_EncryptedData (context,
2287 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2288 b->enc_authorization_data,
2290 krb5_crypto_destroy(context, crypto);
2292 krb5_auth_con_free(context, ac);
2293 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2294 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2297 krb5_free_keyblock(context, subkey);
2299 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2301 krb5_auth_con_free(context, ac);
2304 kdc_log(context, config, 0, "Failed to decode authorization data");
2305 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2310 krb5_auth_con_free(context, ac);
2315 char *spn = NULL, *cpn = NULL;
2316 hdb_entry_ex *server = NULL, *client = NULL;
2318 EncTicketPart adtkt;
2323 if(b->kdc_options.enc_tkt_in_skey){
2329 if(b->additional_tickets == NULL ||
2330 b->additional_tickets->len == 0){
2331 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2332 kdc_log(context, config, 0,
2333 "No second ticket present in request");
2336 t = &b->additional_tickets->val[0];
2337 if(!get_krbtgt_realm(&t->sname)){
2338 kdc_log(context, config, 0,
2339 "Additional ticket is not a ticket-granting ticket");
2340 ret = KRB5KDC_ERR_POLICY;
2343 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2344 ret = _kdc_db_fetch(context, config, p,
2345 HDB_F_GET_CLIENT|HDB_F_GET_SERVER, &uu);
2346 krb5_free_principal(context, p);
2348 if (ret == HDB_ERR_NOENTRY)
2349 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2352 ret = hdb_enctype2key(context, &uu->entry,
2353 t->enc_part.etype, &uukey);
2355 _kdc_free_ent(context, uu);
2356 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2359 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2360 _kdc_free_ent(context, uu);
2367 _krb5_principalname2krb5_principal(&sp, *s, r);
2368 ret = krb5_unparse_name(context, sp, &spn);
2371 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2372 ret = krb5_unparse_name(context, cp, &cpn);
2375 unparse_flags (KDCOptions2int(b->kdc_options),
2376 asn1_KDCOptions_units(),
2377 opt_str, sizeof(opt_str));
2379 kdc_log(context, config, 0,
2380 "TGS-REQ %s from %s for %s [%s]",
2381 cpn, from, spn, opt_str);
2383 kdc_log(context, config, 0,
2384 "TGS-REQ %s from %s for %s", cpn, from, spn);
2386 ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER, &server);
2389 const char *new_rlm;
2393 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2395 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2397 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2399 krb5_free_principal(context, sp);
2401 krb5_make_principal(context, &sp, r,
2402 KRB5_TGS_NAME, new_rlm, NULL);
2403 ret = krb5_unparse_name(context, sp, &spn);
2409 } else if(need_referral(context, sp, &realms)) {
2410 if (strcmp(realms[0], sp->realm) != 0) {
2411 kdc_log(context, config, 5,
2412 "Returning a referral to realm %s for "
2413 "server %s that was not found",
2415 krb5_free_principal(context, sp);
2417 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2419 ret = krb5_unparse_name(context, sp, &spn);
2422 krb5_free_host_realm(context, realms);
2425 krb5_free_host_realm(context, realms);
2427 kdc_log(context, config, 0,
2428 "Server not found in database: %s: %s", spn,
2429 krb5_get_err_text(context, ret));
2430 if (ret == HDB_ERR_NOENTRY)
2431 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2435 ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT, &client);
2437 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2438 cpn, krb5_get_err_text(context, ret));
2441 * If the client belongs to the same realm as our krbtgt, it
2442 * should exist in the local database.
2444 * If its not the same, check the "direction" on the krbtgt,
2445 * so its not a backward uni-directional trust.
2448 if(strcmp(krb5_principal_get_realm(context, sp),
2449 krb5_principal_get_comp_string(context,
2450 krbtgt->entry.principal, 1)) == 0) {
2452 if (ret == HDB_ERR_NOENTRY)
2453 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2458 ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
2459 kdc_log(context, config, 0,
2460 "Request with wrong krbtgt: %s",
2461 (ret == 0) ? tpn : "<unknown>");
2464 ret = KRB5KRB_AP_ERR_NOT_US;
2469 ret = _kdc_check_flags(context, config,
2476 if((b->kdc_options.validate || b->kdc_options.renew) &&
2477 !krb5_principal_compare(context,
2478 krbtgt->entry.principal,
2479 server->entry.principal)){
2480 kdc_log(context, config, 0, "Inconsistent request.");
2481 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2485 /* check for valid set of addresses */
2486 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2487 ret = KRB5KRB_AP_ERR_BADADDR;
2488 kdc_log(context, config, 0, "Request from wrong address");
2492 ret = tgs_make_reply(context,
2496 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2514 _kdc_free_ent(context, server);
2516 _kdc_free_ent(context, client);
2520 krb5_mk_error(context,
2534 krb5_free_principal(context, cp);
2535 krb5_free_principal(context, sp);
2537 krb5_free_ticket(context, ticket);
2538 free_AP_REQ(&ap_req);
2540 free_AuthorizationData(auth_data);
2545 _kdc_free_ent(context, krbtgt);
2552 _kdc_tgs_rep(krb5_context context,
2553 krb5_kdc_configuration *config,
2557 struct sockaddr *from_addr)
2559 krb5_error_code ret;
2561 PA_DATA *tgs_req = NULL;
2562 time_t *csec = NULL;
2565 if(req->padata == NULL){
2566 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2567 kdc_log(context, config, 0,
2568 "TGS-REQ from %s without PA-DATA", from);
2572 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2574 if(tgs_req == NULL){
2575 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2577 kdc_log(context, config, 0,
2578 "TGS-REQ from %s without PA-TGS-REQ", from);
2581 ret = tgs_rep2(context, config,
2582 &req->req_body, tgs_req, data, from, from_addr,
2585 if(ret && data->data == NULL){
2586 krb5_mk_error(context,