2 * Copyright (c) 1997-2002 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.143 2002/09/09 14:03:02 nectar Exp $");
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
47 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
51 set_salt_padata (METHOD_DATA **m, Salt *salt)
57 (*m)->val->padata_type = salt->type;
58 copy_octet_string(&salt->salt,
59 &(*m)->val->padata_value);
64 find_padata(KDC_REQ *req, int *start, int type)
66 while(*start < req->padata->len){
68 if(req->padata->val[*start - 1].padata_type == type)
69 return &req->padata->val[*start - 1];
75 * return the first appropriate key of `princ' in `ret_key'. Look for
76 * all the etypes in (`etypes', `len'), stopping as soon as we find
77 * one, but preferring one that has default salt
80 static krb5_error_code
81 find_etype(hdb_entry *princ, krb5_enctype *etypes, unsigned len,
82 Key **ret_key, krb5_enctype *ret_etype)
85 krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
87 for(i = 0; ret != 0 && i < len ; i++) {
90 while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
91 if (key->key.keyvalue.length == 0) {
92 ret = KRB5KDC_ERR_NULL_KEY;
96 *ret_etype = etypes[i];
98 if (key->salt == NULL)
105 static krb5_error_code
106 find_keys(hdb_entry *client,
109 krb5_enctype *cetype,
111 krb5_enctype *setype,
112 krb5_enctype *etypes,
118 /* find client key */
119 ret = find_etype(client, etypes, num_etypes, ckey, cetype);
121 kdc_log(0, "Client has no support for etypes");
127 /* find server key */
128 ret = find_etype(server, etypes, num_etypes, skey, setype);
130 kdc_log(0, "Server has no support for etypes");
137 static krb5_error_code
138 make_anonymous_principalname (PrincipalName *pn)
140 pn->name_type = KRB5_NT_PRINCIPAL;
141 pn->name_string.len = 1;
142 pn->name_string.val = malloc(sizeof(*pn->name_string.val));
143 if (pn->name_string.val == NULL)
145 pn->name_string.val[0] = strdup("anonymous");
146 if (pn->name_string.val[0] == NULL) {
147 free(pn->name_string.val);
148 pn->name_string.val = NULL;
154 static krb5_error_code
155 encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
157 int skvno, EncryptionKey *skey,
158 int ckvno, EncryptionKey *ckey,
168 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
170 kdc_log(0, "Failed to encode ticket: %s",
171 krb5_get_err_text(context, ret));
174 if(buf_size != len) {
176 kdc_log(0, "Internal error in ASN.1 encoder");
177 *e_text = "KDC internal error";
178 return KRB5KRB_ERR_GENERIC;
181 ret = krb5_crypto_init(context, skey, etype, &crypto);
184 kdc_log(0, "krb5_crypto_init failed: %s",
185 krb5_get_err_text(context, ret));
189 ret = krb5_encrypt_EncryptedData(context,
195 &rep->ticket.enc_part);
197 krb5_crypto_destroy(context, crypto);
199 kdc_log(0, "Failed to encrypt data: %s",
200 krb5_get_err_text(context, ret));
204 if(rep->msg_type == krb_as_rep && !encode_as_rep_as_tgs_rep)
205 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
207 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
209 kdc_log(0, "Failed to encode KDC-REP: %s",
210 krb5_get_err_text(context, ret));
213 if(buf_size != len) {
215 kdc_log(0, "Internal error in ASN.1 encoder");
216 *e_text = "KDC internal error";
217 return KRB5KRB_ERR_GENERIC;
219 ret = krb5_crypto_init(context, ckey, 0, &crypto);
222 kdc_log(0, "krb5_crypto_init failed: %s",
223 krb5_get_err_text(context, ret));
226 if(rep->msg_type == krb_as_rep) {
227 krb5_encrypt_EncryptedData(context,
229 KRB5_KU_AS_REP_ENC_PART,
235 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
237 krb5_encrypt_EncryptedData(context,
239 KRB5_KU_TGS_REP_ENC_PART_SESSION,
245 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
247 krb5_crypto_destroy(context, crypto);
249 kdc_log(0, "Failed to encode KDC-REP: %s",
250 krb5_get_err_text(context, ret));
253 if(buf_size != len) {
255 kdc_log(0, "Internal error in ASN.1 encoder");
256 *e_text = "KDC internal error";
257 return KRB5KRB_ERR_GENERIC;
260 reply->length = buf_size;
265 realloc_method_data(METHOD_DATA *md)
268 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
276 static krb5_error_code
277 make_etype_info_entry(ETYPE_INFO_ENTRY *ent, Key *key)
279 ent->etype = key->key.keytype;
281 ALLOC(ent->salttype);
283 if(key->salt->type == hdb_pw_salt)
284 *ent->salttype = 0; /* or 1? or NULL? */
285 else if(key->salt->type == hdb_afs3_salt)
288 kdc_log(0, "unknown salt-type: %d",
290 return KRB5KRB_ERR_GENERIC;
292 /* according to `the specs', we can't send a salt if
293 we have AFS3 salted key, but that requires that you
294 *know* what cell you are using (e.g by assuming
295 that the cell is the same as the realm in lower
298 *ent->salttype = key->salt->type;
300 krb5_copy_data(context, &key->salt->salt,
303 /* we return no salt type at all, as that should indicate
304 * the default salt type and make everybody happy. some
305 * systems (like w2k) dislike being told the salt type
308 ent->salttype = NULL;
314 static krb5_error_code
315 get_pa_etype_info(METHOD_DATA *md, hdb_entry *client,
316 ENCTYPE *etypes, unsigned int etypes_len)
318 krb5_error_code ret = 0;
326 pa.len = client->keys.len;
327 if(pa.len > UINT_MAX/sizeof(*pa.val))
329 pa.val = malloc(pa.len * sizeof(*pa.val));
333 for(j = 0; j < etypes_len; j++) {
334 for(i = 0; i < client->keys.len; i++) {
335 if(client->keys.val[i].key.keytype == etypes[j])
336 if((ret = make_etype_info_entry(&pa.val[n++],
337 &client->keys.val[i])) != 0) {
338 free_ETYPE_INFO(&pa);
343 for(i = 0; i < client->keys.len; i++) {
344 for(j = 0; j < etypes_len; j++) {
345 if(client->keys.val[i].key.keytype == etypes[j])
348 if((ret = make_etype_info_entry(&pa.val[n++],
349 &client->keys.val[i])) != 0) {
350 free_ETYPE_INFO(&pa);
358 krb5_unparse_name(context, client->principal, &name);
359 kdc_log(0, "internal error in get_pa_etype_info(%s): %d != %d",
365 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
366 free_ETYPE_INFO(&pa);
369 ret = realloc_method_data(md);
374 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
375 md->val[md->len - 1].padata_value.length = len;
376 md->val[md->len - 1].padata_value.data = buf;
381 * verify the flags on `client' and `server', returning 0
382 * if they are OK and generating an error messages and returning
383 * and error code otherwise.
387 check_flags(hdb_entry *client, const char *client_name,
388 hdb_entry *server, const char *server_name,
389 krb5_boolean is_as_req)
393 if (client->flags.invalid) {
394 kdc_log(0, "Client (%s) has invalid bit set", client_name);
395 return KRB5KDC_ERR_POLICY;
398 if(!client->flags.client){
399 kdc_log(0, "Principal may not act as client -- %s",
401 return KRB5KDC_ERR_POLICY;
404 if (client->valid_start && *client->valid_start > kdc_time) {
405 kdc_log(0, "Client not yet valid -- %s", client_name);
406 return KRB5KDC_ERR_CLIENT_NOTYET;
409 if (client->valid_end && *client->valid_end < kdc_time) {
410 kdc_log(0, "Client expired -- %s", client_name);
411 return KRB5KDC_ERR_NAME_EXP;
414 if (client->pw_end && *client->pw_end < kdc_time
415 && !server->flags.change_pw) {
416 kdc_log(0, "Client's key has expired -- %s", client_name);
417 return KRB5KDC_ERR_KEY_EXPIRED;
423 if (server != NULL) {
424 if (server->flags.invalid) {
425 kdc_log(0, "Server has invalid flag set -- %s", server_name);
426 return KRB5KDC_ERR_POLICY;
429 if(!server->flags.server){
430 kdc_log(0, "Principal may not act as server -- %s",
432 return KRB5KDC_ERR_POLICY;
435 if(!is_as_req && server->flags.initial) {
436 kdc_log(0, "AS-REQ is required for server -- %s", server_name);
437 return KRB5KDC_ERR_POLICY;
440 if (server->valid_start && *server->valid_start > kdc_time) {
441 kdc_log(0, "Server not yet valid -- %s", server_name);
442 return KRB5KDC_ERR_SERVICE_NOTYET;
445 if (server->valid_end && *server->valid_end < kdc_time) {
446 kdc_log(0, "Server expired -- %s", server_name);
447 return KRB5KDC_ERR_SERVICE_EXP;
450 if (server->pw_end && *server->pw_end < kdc_time) {
451 kdc_log(0, "Server's key has expired -- %s", server_name);
452 return KRB5KDC_ERR_KEY_EXPIRED;
459 * Return TRUE if `from' is part of `addresses' taking into consideration
460 * the configuration variables that tells us how strict we should be about
465 check_addresses(HostAddresses *addresses, const struct sockaddr *from)
471 if(check_ticket_addresses == 0)
474 if(addresses == NULL)
475 return allow_null_ticket_addresses;
477 ret = krb5_sockaddr2address (context, from, &addr);
481 result = krb5_address_search(context, &addr, addresses);
482 krb5_free_address (context, &addr);
490 struct sockaddr *from_addr)
492 KDC_REQ_BODY *b = &req->req_body;
494 KDCOptions f = b->kdc_options;
495 hdb_entry *client = NULL, *server = NULL;
496 krb5_enctype cetype, setype;
499 krb5_principal client_princ, server_princ;
500 char *client_name, *server_name;
501 krb5_error_code ret = 0;
502 const char *e_text = NULL;
506 memset(&rep, 0, sizeof(rep));
508 if(b->sname == NULL){
509 server_name = "<unknown server>";
510 ret = KRB5KRB_ERR_GENERIC;
511 e_text = "No server in request";
513 principalname2krb5_principal (&server_princ, *(b->sname), b->realm);
514 krb5_unparse_name(context, server_princ, &server_name);
517 if(b->cname == NULL){
518 client_name = "<unknown client>";
519 ret = KRB5KRB_ERR_GENERIC;
520 e_text = "No client in request";
522 principalname2krb5_principal (&client_princ, *(b->cname), b->realm);
523 krb5_unparse_name(context, client_princ, &client_name);
525 kdc_log(0, "AS-REQ %s from %s for %s",
526 client_name, from, server_name);
531 ret = db_fetch(client_princ, &client);
533 kdc_log(0, "UNKNOWN -- %s: %s", client_name,
534 krb5_get_err_text(context, ret));
535 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
539 ret = db_fetch(server_princ, &server);
541 kdc_log(0, "UNKNOWN -- %s: %s", server_name,
542 krb5_get_err_text(context, ret));
543 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
547 ret = check_flags(client, client_name, server, server_name, TRUE);
551 memset(&et, 0, sizeof(et));
552 memset(&ek, 0, sizeof(ek));
558 kdc_log(5, "Looking for pa-data -- %s", client_name);
559 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
564 EncryptedData enc_data;
569 ret = decode_EncryptedData(pa->padata_value.data,
570 pa->padata_value.length,
574 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
575 kdc_log(5, "Failed to decode PA-DATA -- %s",
580 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
583 e_text = "No key matches pa-data";
584 ret = KRB5KDC_ERR_PREAUTH_FAILED;
585 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
588 kdc_log(5, "No client key matching pa-data (%d) -- %s",
589 enc_data.etype, client_name);
591 kdc_log(5, "No client key matching pa-data (%s) -- %s",
595 free_EncryptedData(&enc_data);
600 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
602 kdc_log(0, "krb5_crypto_init failed: %s",
603 krb5_get_err_text(context, ret));
604 free_EncryptedData(&enc_data);
608 ret = krb5_decrypt_EncryptedData (context,
610 KRB5_KU_PA_ENC_TIMESTAMP,
613 krb5_crypto_destroy(context, crypto);
615 if(hdb_next_enctype2key(context, client,
616 enc_data.etype, &pa_key) == 0)
618 free_EncryptedData(&enc_data);
619 e_text = "Failed to decrypt PA-DATA";
620 kdc_log (5, "Failed to decrypt PA-DATA -- %s",
622 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
625 free_EncryptedData(&enc_data);
626 ret = decode_PA_ENC_TS_ENC(ts_data.data,
630 krb5_data_free(&ts_data);
632 e_text = "Failed to decode PA-ENC-TS-ENC";
633 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
634 kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s",
638 patime = p.patimestamp;
639 free_PA_ENC_TS_ENC(&p);
640 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
641 ret = KRB5KDC_ERR_PREAUTH_FAILED;
642 e_text = "Too large time skew";
643 kdc_log(0, "Too large time skew -- %s", client_name);
646 et.flags.pre_authent = 1;
647 kdc_log(2, "Pre-authentication succeded -- %s", client_name);
650 if(found_pa == 0 && require_preauth)
652 /* We come here if we found a pa-enc-timestamp, but if there
653 was some problem with it, other than too large skew */
654 if(found_pa && et.flags.pre_authent == 0){
655 kdc_log(0, "%s -- %s", e_text, client_name);
659 }else if (require_preauth
660 || client->flags.require_preauth
661 || server->flags.require_preauth) {
662 METHOD_DATA method_data;
670 method_data.val = NULL;
672 ret = realloc_method_data(&method_data);
673 pa = &method_data.val[method_data.len-1];
674 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
675 pa->padata_value.length = 0;
676 pa->padata_value.data = NULL;
678 ret = get_pa_etype_info(&method_data, client,
679 b->etype.val, b->etype.len); /* XXX check ret */
681 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
682 free_METHOD_DATA(&method_data);
684 foo_data.length = len;
686 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
687 krb5_mk_error(context,
689 "Need to use PA-ENC-TIMESTAMP",
697 kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name);
702 ret = find_keys(client, server, &ckey, &cetype, &skey, &setype,
703 b->etype.val, b->etype.len);
705 kdc_log(0, "Server/client has no support for etypes");
713 ret = krb5_enctype_to_string(context, cetype, &cet);
715 ret = krb5_enctype_to_string(context, setype, &set);
717 kdc_log(5, "Using %s/%s", cet, set);
722 kdc_log(5, "Using e-types %d/%d", cetype, setype);
727 unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str));
729 kdc_log(2, "Requested flags: %s", str);
733 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
734 || (f.request_anonymous && !allow_anonymous)) {
735 ret = KRB5KDC_ERR_BADOPTION;
736 kdc_log(0, "Bad KDC options -- %s", client_name);
741 rep.msg_type = krb_as_rep;
742 copy_Realm(&b->realm, &rep.crealm);
743 if (f.request_anonymous)
744 make_anonymous_principalname (&rep.cname);
746 copy_PrincipalName(b->cname, &rep.cname);
747 rep.ticket.tkt_vno = 5;
748 copy_Realm(&b->realm, &rep.ticket.realm);
749 copy_PrincipalName(b->sname, &rep.ticket.sname);
751 et.flags.initial = 1;
752 if(client->flags.forwardable && server->flags.forwardable)
753 et.flags.forwardable = f.forwardable;
754 else if (f.forwardable) {
755 ret = KRB5KDC_ERR_POLICY;
756 kdc_log(0, "Ticket may not be forwardable -- %s", client_name);
759 if(client->flags.proxiable && server->flags.proxiable)
760 et.flags.proxiable = f.proxiable;
761 else if (f.proxiable) {
762 ret = KRB5KDC_ERR_POLICY;
763 kdc_log(0, "Ticket may not be proxiable -- %s", client_name);
766 if(client->flags.postdate && server->flags.postdate)
767 et.flags.may_postdate = f.allow_postdate;
768 else if (f.allow_postdate){
769 ret = KRB5KDC_ERR_POLICY;
770 kdc_log(0, "Ticket may not be postdatable -- %s", client_name);
774 /* check for valid set of addresses */
775 if(!check_addresses(b->addresses, from_addr)) {
776 ret = KRB5KRB_AP_ERR_BADADDR;
777 kdc_log(0, "Bad address list requested -- %s", client_name);
781 krb5_generate_random_keyblock(context, setype, &et.key);
782 copy_PrincipalName(&rep.cname, &et.cname);
783 copy_Realm(&b->realm, &et.crealm);
789 start = et.authtime = kdc_time;
791 if(f.postdated && req->req_body.from){
793 start = *et.starttime = *req->req_body.from;
794 et.flags.invalid = 1;
795 et.flags.postdated = 1; /* XXX ??? */
800 /* be careful not overflowing */
803 t = start + min(t - start, *client->max_life);
805 t = start + min(t - start, *server->max_life);
807 t = min(t, start + realm->max_life);
810 if(f.renewable_ok && et.endtime < *b->till){
812 if(b->rtime == NULL){
816 if(*b->rtime < *b->till)
817 *b->rtime = *b->till;
819 if(f.renewable && b->rtime){
823 if(client->max_renew)
824 t = start + min(t - start, *client->max_renew);
825 if(server->max_renew)
826 t = start + min(t - start, *server->max_renew);
828 t = min(t, start + realm->max_renew);
830 ALLOC(et.renew_till);
832 et.flags.renewable = 1;
836 if (f.request_anonymous)
837 et.flags.anonymous = 1;
841 copy_HostAddresses(b->addresses, et.caddr);
845 krb5_data empty_string;
847 krb5_data_zero(&empty_string);
848 et.transited.tr_type = DOMAIN_X500_COMPRESS;
849 et.transited.contents = empty_string;
852 copy_EncryptionKey(&et.key, &ek.key);
854 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
855 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
856 * incapable of correctly decoding SEQUENCE OF's of zero length.
858 * To fix this, always send at least one no-op last_req
860 * If there's a pw_end or valid_end we will use that,
861 * otherwise just a dummy lr.
863 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
866 && (kdc_warn_pwexpire == 0
867 || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) {
868 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
869 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
872 if (client->valid_end) {
873 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
874 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
877 if (ek.last_req.len == 0) {
878 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
879 ek.last_req.val[ek.last_req.len].lr_value = 0;
883 if (client->valid_end || client->pw_end) {
884 ALLOC(ek.key_expiration);
885 if (client->valid_end) {
887 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
889 *ek.key_expiration = *client->valid_end;
891 *ek.key_expiration = *client->pw_end;
893 ek.key_expiration = NULL;
895 ek.authtime = et.authtime;
898 *ek.starttime = *et.starttime;
900 ek.endtime = et.endtime;
902 ALLOC(ek.renew_till);
903 *ek.renew_till = *et.renew_till;
905 copy_Realm(&rep.ticket.realm, &ek.srealm);
906 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
909 copy_HostAddresses(et.caddr, ek.caddr);
912 set_salt_padata (&rep.padata, ckey->salt);
913 ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key,
914 client->kvno, &ckey->key, &e_text, reply);
915 free_EncTicketPart(&et);
916 free_EncKDCRepPart(&ek);
920 krb5_mk_error(context,
932 krb5_free_principal(context, client_princ);
934 krb5_free_principal(context, server_princ);
944 static krb5_error_code
945 check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
947 KDCOptions f = b->kdc_options;
950 if(!tgt->flags.invalid || tgt->starttime == NULL){
951 kdc_log(0, "Bad request to validate ticket");
952 return KRB5KDC_ERR_BADOPTION;
954 if(*tgt->starttime > kdc_time){
955 kdc_log(0, "Early request to validate ticket");
956 return KRB5KRB_AP_ERR_TKT_NYV;
959 et->flags.invalid = 0;
960 }else if(tgt->flags.invalid){
961 kdc_log(0, "Ticket-granting ticket has INVALID flag set");
962 return KRB5KRB_AP_ERR_TKT_INVALID;
966 if(!tgt->flags.forwardable){
967 kdc_log(0, "Bad request for forwardable ticket");
968 return KRB5KDC_ERR_BADOPTION;
970 et->flags.forwardable = 1;
973 if(!tgt->flags.forwardable){
974 kdc_log(0, "Request to forward non-forwardable ticket");
975 return KRB5KDC_ERR_BADOPTION;
977 et->flags.forwarded = 1;
978 et->caddr = b->addresses;
980 if(tgt->flags.forwarded)
981 et->flags.forwarded = 1;
984 if(!tgt->flags.proxiable){
985 kdc_log(0, "Bad request for proxiable ticket");
986 return KRB5KDC_ERR_BADOPTION;
988 et->flags.proxiable = 1;
991 if(!tgt->flags.proxiable){
992 kdc_log(0, "Request to proxy non-proxiable ticket");
993 return KRB5KDC_ERR_BADOPTION;
996 et->caddr = b->addresses;
1001 if(f.allow_postdate){
1002 if(!tgt->flags.may_postdate){
1003 kdc_log(0, "Bad request for post-datable ticket");
1004 return KRB5KDC_ERR_BADOPTION;
1006 et->flags.may_postdate = 1;
1009 if(!tgt->flags.may_postdate){
1010 kdc_log(0, "Bad request for postdated ticket");
1011 return KRB5KDC_ERR_BADOPTION;
1014 *et->starttime = *b->from;
1015 et->flags.postdated = 1;
1016 et->flags.invalid = 1;
1017 }else if(b->from && *b->from > kdc_time + context->max_skew){
1018 kdc_log(0, "Ticket cannot be postdated");
1019 return KRB5KDC_ERR_CANNOT_POSTDATE;
1023 if(!tgt->flags.renewable){
1024 kdc_log(0, "Bad request for renewable ticket");
1025 return KRB5KDC_ERR_BADOPTION;
1027 et->flags.renewable = 1;
1028 ALLOC(et->renew_till);
1029 fix_time(&b->rtime);
1030 *et->renew_till = *b->rtime;
1034 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1035 kdc_log(0, "Request to renew non-renewable ticket");
1036 return KRB5KDC_ERR_BADOPTION;
1038 old_life = tgt->endtime;
1040 old_life -= *tgt->starttime;
1042 old_life -= tgt->authtime;
1043 et->endtime = *et->starttime + old_life;
1044 if (et->renew_till != NULL)
1045 et->endtime = min(*et->renew_till, et->endtime);
1048 /* checks for excess flags */
1049 if(f.request_anonymous && !allow_anonymous){
1050 kdc_log(0, "Request for anonymous ticket");
1051 return KRB5KDC_ERR_BADOPTION;
1056 static krb5_error_code
1057 fix_transited_encoding(TransitedEncoding *tr,
1058 const char *client_realm,
1059 const char *server_realm,
1060 const char *tgt_realm)
1062 krb5_error_code ret = 0;
1063 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){
1064 char **realms = NULL, **tmp;
1067 if(tr->tr_type && tr->contents.length != 0) {
1068 if(tr->tr_type != DOMAIN_X500_COMPRESS){
1069 kdc_log(0, "Unknown transited type: %u",
1071 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1073 ret = krb5_domain_x500_decode(context,
1080 krb5_warn(context, ret, "Decoding transited encoding");
1084 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1088 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1094 realms[num_realms] = strdup(tgt_realm);
1095 if(realms[num_realms] == NULL){
1100 free_TransitedEncoding(tr);
1101 tr->tr_type = DOMAIN_X500_COMPRESS;
1102 ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents);
1104 krb5_warn(context, ret, "Encoding transited encoding");
1106 for(i = 0; i < num_realms; i++)
1114 static krb5_error_code
1115 tgs_make_reply(KDC_REQ_BODY *b,
1117 EncTicketPart *adtkt,
1118 AuthorizationData *auth_data,
1121 krb5_principal client_principal,
1123 krb5_enctype cetype,
1124 const char **e_text,
1130 KDCOptions f = b->kdc_options;
1131 krb5_error_code ret;
1134 EncryptionKey *ekey;
1140 for(i = 0; i < b->etype.len; i++){
1141 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1144 if(adtkt->key.keytype == kt)
1147 if(i == b->etype.len)
1148 return KRB5KDC_ERR_ETYPE_NOSUPP;
1149 etype = b->etype.val[i];
1151 ret = find_keys(NULL, server, NULL, NULL, &skey, &etype,
1152 b->etype.val, b->etype.len);
1154 kdc_log(0, "Server has no support for etypes");
1160 memset(&rep, 0, sizeof(rep));
1161 memset(&et, 0, sizeof(et));
1162 memset(&ek, 0, sizeof(ek));
1165 rep.msg_type = krb_tgs_rep;
1167 et.authtime = tgt->authtime;
1169 et.endtime = min(tgt->endtime, *b->till);
1170 ALLOC(et.starttime);
1171 *et.starttime = kdc_time;
1173 ret = check_tgs_flags(b, tgt, &et);
1177 copy_TransitedEncoding(&tgt->transited, &et.transited);
1178 ret = fix_transited_encoding(&et.transited,
1179 *krb5_princ_realm(context, client_principal),
1180 *krb5_princ_realm(context, server->principal),
1181 *krb5_princ_realm(context, krbtgt->principal));
1183 free_TransitedEncoding(&et.transited);
1188 copy_Realm(krb5_princ_realm(context, server->principal),
1190 krb5_principal2principalname(&rep.ticket.sname, server->principal);
1191 copy_Realm(&tgt->crealm, &rep.crealm);
1192 if (f.request_anonymous)
1193 make_anonymous_principalname (&tgt->cname);
1195 copy_PrincipalName(&tgt->cname, &rep.cname);
1196 rep.ticket.tkt_vno = 5;
1198 ek.caddr = et.caddr;
1199 if(et.caddr == NULL)
1200 et.caddr = tgt->caddr;
1204 life = et.endtime - *et.starttime;
1205 if(client && client->max_life)
1206 life = min(life, *client->max_life);
1207 if(server->max_life)
1208 life = min(life, *server->max_life);
1209 et.endtime = *et.starttime + life;
1211 if(f.renewable_ok && tgt->flags.renewable &&
1212 et.renew_till == NULL && et.endtime < *b->till){
1213 et.flags.renewable = 1;
1214 ALLOC(et.renew_till);
1215 *et.renew_till = *b->till;
1219 renew = *et.renew_till - et.authtime;
1220 if(client && client->max_renew)
1221 renew = min(renew, *client->max_renew);
1222 if(server->max_renew)
1223 renew = min(renew, *server->max_renew);
1224 *et.renew_till = et.authtime + renew;
1228 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1229 *et.starttime = min(*et.starttime, *et.renew_till);
1230 et.endtime = min(et.endtime, *et.renew_till);
1233 *et.starttime = min(*et.starttime, et.endtime);
1235 if(*et.starttime == et.endtime){
1236 ret = KRB5KDC_ERR_NEVER_VALID;
1239 if(et.renew_till && et.endtime == *et.renew_till){
1240 free(et.renew_till);
1241 et.renew_till = NULL;
1242 et.flags.renewable = 0;
1245 et.flags.pre_authent = tgt->flags.pre_authent;
1246 et.flags.hw_authent = tgt->flags.hw_authent;
1247 et.flags.anonymous = tgt->flags.anonymous;
1249 /* XXX Check enc-authorization-data */
1250 et.authorization_data = auth_data;
1252 krb5_generate_random_keyblock(context, etype, &et.key);
1253 et.crealm = tgt->crealm;
1254 et.cname = tgt->cname;
1257 /* MIT must have at least one last_req */
1258 ek.last_req.len = 1;
1259 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1260 ek.nonce = b->nonce;
1261 ek.flags = et.flags;
1262 ek.authtime = et.authtime;
1263 ek.starttime = et.starttime;
1264 ek.endtime = et.endtime;
1265 ek.renew_till = et.renew_till;
1266 ek.srealm = rep.ticket.realm;
1267 ek.sname = rep.ticket.sname;
1269 /* It is somewhat unclear where the etype in the following
1270 encryption should come from. What we have is a session
1271 key in the passed tgt, and a list of preferred etypes
1272 *for the new ticket*. Should we pick the best possible
1273 etype, given the keytype in the tgt, or should we look
1274 at the etype list here as well? What if the tgt
1275 session key is DES3 and we want a ticket with a (say)
1276 CAST session key. Should the DES3 etype be added to the
1277 etype list, even if we don't want a session key with
1279 ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1280 0, &tgt->key, e_text, reply);
1283 free_TransitedEncoding(&et.transited);
1287 free(et.renew_till);
1288 free_LastReq(&ek.last_req);
1289 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1290 free_EncryptionKey(&et.key);
1294 static krb5_error_code
1295 tgs_check_authenticator(krb5_auth_context ac,
1297 const char **e_text,
1300 krb5_authenticator auth;
1304 krb5_error_code ret;
1307 krb5_auth_con_getauthenticator(context, ac, &auth);
1308 if(auth->cksum == NULL){
1309 kdc_log(0, "No authenticator in request");
1310 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1314 * according to RFC1510 it doesn't need to be keyed,
1315 * but according to the latest draft it needs to.
1319 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1322 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1323 kdc_log(0, "Bad checksum type in authenticator: %d",
1324 auth->cksum->cksumtype);
1325 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1329 /* XXX should not re-encode this */
1330 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1332 kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
1333 krb5_get_err_text(context, ret));
1336 if(buf_size != len) {
1338 kdc_log(0, "Internal error in ASN.1 encoder");
1339 *e_text = "KDC internal error";
1340 ret = KRB5KRB_ERR_GENERIC;
1343 ret = krb5_crypto_init(context, key, 0, &crypto);
1346 kdc_log(0, "krb5_crypto_init failed: %s",
1347 krb5_get_err_text(context, ret));
1350 ret = krb5_verify_checksum(context,
1352 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1357 krb5_crypto_destroy(context, crypto);
1359 kdc_log(0, "Failed to verify checksum: %s",
1360 krb5_get_err_text(context, ret));
1363 free_Authenticator(auth);
1369 * return the realm of a krbtgt-ticket or NULL
1373 get_krbtgt_realm(const PrincipalName *p)
1375 if(p->name_string.len == 2
1376 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1377 return p->name_string.val[1];
1385 const char *new_realm = krb5_config_get_string(context,
1391 return (Realm)new_realm;
1396 need_referral(krb5_principal server, krb5_realm **realms)
1398 if(server->name.name_type != KRB5_NT_SRV_INST ||
1399 server->name.name_string.len != 2)
1402 return krb5_get_host_realm_int(context, server->name.name_string.val[1],
1403 FALSE, realms) == 0;
1406 static krb5_error_code
1407 tgs_rep2(KDC_REQ_BODY *b,
1411 const struct sockaddr *from_addr,
1416 krb5_error_code ret;
1417 krb5_principal princ;
1418 krb5_auth_context ac = NULL;
1419 krb5_ticket *ticket = NULL;
1420 krb5_flags ap_req_options;
1421 krb5_flags verify_ap_req_flags;
1422 const char *e_text = NULL;
1425 hdb_entry *krbtgt = NULL;
1428 krb5_enctype cetype;
1429 krb5_principal cp = NULL;
1430 krb5_principal sp = NULL;
1431 AuthorizationData *auth_data = NULL;
1436 memset(&ap_req, 0, sizeof(ap_req));
1437 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1439 kdc_log(0, "Failed to decode AP-REQ: %s",
1440 krb5_get_err_text(context, ret));
1444 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1445 /* XXX check for ticket.sname == req.sname */
1446 kdc_log(0, "PA-DATA is not a ticket-granting ticket");
1447 ret = KRB5KDC_ERR_POLICY; /* ? */
1451 principalname2krb5_principal(&princ,
1452 ap_req.ticket.sname,
1453 ap_req.ticket.realm);
1455 ret = db_fetch(princ, &krbtgt);
1459 krb5_unparse_name(context, princ, &p);
1460 kdc_log(0, "Ticket-granting ticket not found in database: %s: %s",
1461 p, krb5_get_err_text(context, ret));
1463 ret = KRB5KRB_AP_ERR_NOT_US;
1467 if(ap_req.ticket.enc_part.kvno &&
1468 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1471 krb5_unparse_name (context, princ, &p);
1472 kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)",
1473 *ap_req.ticket.enc_part.kvno,
1477 ret = KRB5KRB_AP_ERR_BADKEYVER;
1481 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
1484 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1485 kdc_log(0, "No server key found for %s", str);
1487 ret = KRB5KRB_AP_ERR_BADKEYVER;
1491 if (b->kdc_options.validate)
1492 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1494 verify_ap_req_flags = 0;
1496 ret = krb5_verify_ap_req2(context,
1501 verify_ap_req_flags,
1504 KRB5_KU_TGS_REQ_AUTH);
1506 krb5_free_principal(context, princ);
1508 kdc_log(0, "Failed to verify AP-REQ: %s",
1509 krb5_get_err_text(context, ret));
1514 krb5_authenticator auth;
1516 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1518 *csec = malloc(sizeof(**csec));
1519 if (*csec == NULL) {
1520 krb5_free_authenticator(context, &auth);
1521 kdc_log(0, "malloc failed");
1524 **csec = auth->ctime;
1525 *cusec = malloc(sizeof(**cusec));
1526 if (*cusec == NULL) {
1527 krb5_free_authenticator(context, &auth);
1528 kdc_log(0, "malloc failed");
1531 **csec = auth->cusec;
1532 krb5_free_authenticator(context, &auth);
1536 cetype = ap_req.authenticator.etype;
1538 tgt = &ticket->ticket;
1540 ret = tgs_check_authenticator(ac, b, &e_text, &tgt->key);
1542 if (b->enc_authorization_data) {
1543 krb5_keyblock *subkey;
1545 ret = krb5_auth_con_getremotesubkey(context,
1549 krb5_auth_con_free(context, ac);
1550 kdc_log(0, "Failed to get remote subkey: %s",
1551 krb5_get_err_text(context, ret));
1555 ret = krb5_auth_con_getkey(context, ac, &subkey);
1557 krb5_auth_con_free(context, ac);
1558 kdc_log(0, "Failed to get session key: %s",
1559 krb5_get_err_text(context, ret));
1564 krb5_auth_con_free(context, ac);
1565 kdc_log(0, "Failed to get key for enc-authorization-data");
1566 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1569 ret = krb5_crypto_init(context, subkey, 0, &crypto);
1571 krb5_auth_con_free(context, ac);
1572 kdc_log(0, "krb5_crypto_init failed: %s",
1573 krb5_get_err_text(context, ret));
1576 ret = krb5_decrypt_EncryptedData (context,
1578 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
1579 b->enc_authorization_data,
1581 krb5_crypto_destroy(context, crypto);
1583 krb5_auth_con_free(context, ac);
1584 kdc_log(0, "Failed to decrypt enc-authorization-data");
1585 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1588 krb5_free_keyblock(context, subkey);
1590 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
1592 krb5_auth_con_free(context, ac);
1595 kdc_log(0, "Failed to decode authorization data");
1596 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1601 krb5_auth_con_free(context, ac);
1604 kdc_log(0, "Failed to verify authenticator: %s",
1605 krb5_get_err_text(context, ret));
1612 char *spn = NULL, *cpn = NULL;
1613 hdb_entry *server = NULL, *client = NULL;
1615 EncTicketPart adtkt;
1620 if(b->kdc_options.enc_tkt_in_skey){
1626 if(b->additional_tickets == NULL ||
1627 b->additional_tickets->len == 0){
1628 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1629 kdc_log(0, "No second ticket present in request");
1632 t = &b->additional_tickets->val[0];
1633 if(!get_krbtgt_realm(&t->sname)){
1634 kdc_log(0, "Additional ticket is not a ticket-granting ticket");
1635 ret = KRB5KDC_ERR_POLICY;
1638 principalname2krb5_principal(&p, t->sname, t->realm);
1639 ret = db_fetch(p, &uu);
1640 krb5_free_principal(context, p);
1642 if (ret == HDB_ERR_NOENTRY)
1643 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1646 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey);
1648 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1651 ret = krb5_decrypt_ticket(context, t, &tkey->key, &adtkt, 0);
1659 principalname2krb5_principal(&sp, *s, r);
1660 krb5_unparse_name(context, sp, &spn);
1661 principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
1662 krb5_unparse_name(context, cp, &cpn);
1663 unparse_flags (KDCOptions2int(b->kdc_options), KDCOptions_units,
1664 opt_str, sizeof(opt_str));
1666 kdc_log(0, "TGS-REQ %s from %s for %s [%s]",
1667 cpn, from, spn, opt_str);
1669 kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn);
1671 ret = db_fetch(sp, &server);
1674 Realm req_rlm, new_rlm;
1677 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1679 new_rlm = find_rpath(req_rlm);
1681 kdc_log(5, "krbtgt for realm %s not found, trying %s",
1683 krb5_free_principal(context, sp);
1685 krb5_make_principal(context, &sp, r,
1686 KRB5_TGS_NAME, new_rlm, NULL);
1687 krb5_unparse_name(context, sp, &spn);
1691 } else if(need_referral(sp, &realms)) {
1692 if (strcmp(realms[0], sp->realm) != 0) {
1693 kdc_log(5, "returning a referral to realm %s for "
1694 "server %s that was not found",
1696 krb5_free_principal(context, sp);
1698 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1700 krb5_unparse_name(context, sp, &spn);
1701 krb5_free_host_realm(context, realms);
1704 krb5_free_host_realm(context, realms);
1706 kdc_log(0, "Server not found in database: %s: %s", spn,
1707 krb5_get_err_text(context, ret));
1708 if (ret == HDB_ERR_NOENTRY)
1709 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1713 ret = db_fetch(cp, &client);
1715 kdc_log(1, "Client not found in database: %s: %s",
1716 cpn, krb5_get_err_text(context, ret));
1718 /* XXX check client only if same realm as krbtgt-instance */
1720 kdc_log(0, "Client not found in database: %s: %s",
1721 cpn, krb5_get_err_text(context, ret));
1722 if (ret == HDB_ERR_NOENTRY)
1723 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1728 ret = check_flags(client, cpn, server, spn, FALSE);
1732 if((b->kdc_options.validate || b->kdc_options.renew) &&
1733 !krb5_principal_compare(context,
1735 server->principal)){
1736 kdc_log(0, "Inconsistent request.");
1737 ret = KRB5KDC_ERR_SERVER_NOMATCH;
1741 /* check for valid set of addresses */
1742 if(!check_addresses(tgt->caddr, from_addr)) {
1743 ret = KRB5KRB_AP_ERR_BADADDR;
1744 kdc_log(0, "Request from wrong address");
1748 ret = tgs_make_reply(b,
1750 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
1771 krb5_mk_error(context,
1785 krb5_free_principal(context, cp);
1786 krb5_free_principal(context, sp);
1788 krb5_free_ticket(context, ticket);
1791 free_AP_REQ(&ap_req);
1793 free_AuthorizationData(auth_data);
1805 tgs_rep(KDC_REQ *req,
1808 struct sockaddr *from_addr)
1810 krb5_error_code ret;
1812 PA_DATA *tgs_req = NULL;
1813 time_t *csec = NULL;
1816 if(req->padata == NULL){
1817 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
1818 kdc_log(0, "TGS-REQ from %s without PA-DATA", from);
1822 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
1824 if(tgs_req == NULL){
1825 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
1827 kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from);
1830 ret = tgs_rep2(&req->req_body, tgs_req, data, from, from_addr,
1833 if(ret && data->data == NULL){
1834 krb5_mk_error(context,