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 #include "kdc/pac-glue.h"
39 RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
41 #define MAX_TIME ((time_t)((1U << 31) - 1))
50 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
54 realloc_method_data(METHOD_DATA *md)
57 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
66 set_salt_padata (METHOD_DATA *md, Salt *salt)
69 realloc_method_data(md);
70 md->val[md->len - 1].padata_type = salt->type;
71 copy_octet_string(&salt->salt,
72 &md->val[md->len - 1].padata_value);
77 find_padata(KDC_REQ *req, int *start, int type)
79 while(*start < req->padata->len){
81 if(req->padata->val[*start - 1].padata_type == type)
82 return &req->padata->val[*start - 1];
88 * return the first appropriate key of `princ' in `ret_key'. Look for
89 * all the etypes in (`etypes', `len'), stopping as soon as we find
90 * one, but preferring one that has default salt
93 static krb5_error_code
94 find_etype(krb5_context context, hdb_entry *princ,
95 krb5_enctype *etypes, unsigned len,
96 Key **ret_key, krb5_enctype *ret_etype)
99 krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
101 for(i = 0; ret != 0 && i < len ; i++) {
104 if (krb5_enctype_valid(context, etypes[i]) != 0)
107 while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
108 if (key->key.keyvalue.length == 0) {
109 ret = KRB5KDC_ERR_NULL_KEY;
113 *ret_etype = etypes[i];
115 if (key->salt == NULL)
122 static krb5_error_code
123 find_keys(krb5_context context,
124 krb5_kdc_configuration *config,
128 krb5_enctype *cetype,
130 krb5_enctype *setype,
131 krb5_enctype *etypes,
134 char unparse_name[] = "krb5_unparse_name failed";
139 /* find client key */
140 ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
142 if (krb5_unparse_name(context, client->principal, &name) != 0)
144 kdc_log(context, config, 0,
145 "Client (%s) has no support for etypes", name);
146 if (name != unparse_name)
153 /* find server key */
154 ret = find_etype(context, server, etypes, num_etypes, skey, setype);
156 if (krb5_unparse_name(context, server->principal, &name) != 0)
158 kdc_log(context, config, 0,
159 "Server (%s) has no support for etypes", name);
160 if (name != unparse_name)
168 static krb5_error_code
169 make_anonymous_principalname (PrincipalName *pn)
171 pn->name_type = KRB5_NT_PRINCIPAL;
172 pn->name_string.len = 1;
173 pn->name_string.val = malloc(sizeof(*pn->name_string.val));
174 if (pn->name_string.val == NULL)
176 pn->name_string.val[0] = strdup("anonymous");
177 if (pn->name_string.val[0] == NULL) {
178 free(pn->name_string.val);
179 pn->name_string.val = NULL;
186 log_timestamp(krb5_context context,
187 krb5_kdc_configuration *config,
189 KerberosTime authtime, KerberosTime *starttime,
190 KerberosTime endtime, KerberosTime *renew_till)
192 char authtime_str[100], starttime_str[100],
193 endtime_str[100], renewtime_str[100];
195 krb5_format_time(context, authtime,
196 authtime_str, sizeof(authtime_str), TRUE);
198 krb5_format_time(context, *starttime,
199 starttime_str, sizeof(starttime_str), TRUE);
201 strlcpy(starttime_str, "unset", sizeof(starttime_str));
202 krb5_format_time(context, endtime,
203 endtime_str, sizeof(endtime_str), TRUE);
205 krb5_format_time(context, *renew_till,
206 renewtime_str, sizeof(renewtime_str), TRUE);
208 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
210 kdc_log(context, config, 5,
211 "%s authtime: %s starttime: %s endtype: %s renew till: %s",
212 type, authtime_str, starttime_str, endtime_str, renewtime_str);
215 static krb5_error_code
216 encode_reply(krb5_context context,
217 krb5_kdc_configuration *config,
218 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
220 int skvno, EncryptionKey *skey,
221 int ckvno, EncryptionKey *ckey,
231 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
233 kdc_log(context, config, 0, "Failed to encode ticket: %s",
234 krb5_get_err_text(context, ret));
237 if(buf_size != len) {
239 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
240 *e_text = "KDC internal error";
241 return KRB5KRB_ERR_GENERIC;
244 ret = krb5_crypto_init(context, skey, etype, &crypto);
247 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
248 krb5_get_err_text(context, ret));
252 ret = krb5_encrypt_EncryptedData(context,
258 &rep->ticket.enc_part);
260 krb5_crypto_destroy(context, crypto);
262 kdc_log(context, config, 0, "Failed to encrypt data: %s",
263 krb5_get_err_text(context, ret));
267 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
268 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
270 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
272 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
273 krb5_get_err_text(context, ret));
276 if(buf_size != len) {
278 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
279 *e_text = "KDC internal error";
280 return KRB5KRB_ERR_GENERIC;
282 ret = krb5_crypto_init(context, ckey, 0, &crypto);
285 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
286 krb5_get_err_text(context, ret));
289 if(rep->msg_type == krb_as_rep) {
290 krb5_encrypt_EncryptedData(context,
292 KRB5_KU_AS_REP_ENC_PART,
298 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
300 krb5_encrypt_EncryptedData(context,
302 KRB5_KU_TGS_REP_ENC_PART_SESSION,
308 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
310 krb5_crypto_destroy(context, crypto);
312 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
313 krb5_get_err_text(context, ret));
316 if(buf_size != len) {
318 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
319 *e_text = "KDC internal error";
320 return KRB5KRB_ERR_GENERIC;
323 reply->length = buf_size;
327 static krb5_error_code
328 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
330 ent->etype = key->key.keytype;
332 ALLOC(ent->salttype);
334 if(key->salt->type == hdb_pw_salt)
335 *ent->salttype = 0; /* or 1? or NULL? */
336 else if(key->salt->type == hdb_afs3_salt)
339 kdc_log(context, config, 0, "unknown salt-type: %d",
341 return KRB5KRB_ERR_GENERIC;
343 /* according to `the specs', we can't send a salt if
344 we have AFS3 salted key, but that requires that you
345 *know* what cell you are using (e.g by assuming
346 that the cell is the same as the realm in lower
349 *ent->salttype = key->salt->type;
351 krb5_copy_data(context, &key->salt->salt,
354 /* we return no salt type at all, as that should indicate
355 * the default salt type and make everybody happy. some
356 * systems (like w2k) dislike being told the salt type
359 ent->salttype = NULL;
365 static krb5_error_code
366 get_pa_etype_info(krb5_context context,
367 krb5_kdc_configuration *config,
368 METHOD_DATA *md, hdb_entry *client,
369 ENCTYPE *etypes, unsigned int etypes_len)
371 krb5_error_code ret = 0;
379 pa.len = client->keys.len;
380 if(pa.len > UINT_MAX/sizeof(*pa.val))
382 pa.val = malloc(pa.len * sizeof(*pa.val));
385 memset(pa.val, 0, pa.len * sizeof(*pa.val));
387 for(j = 0; j < etypes_len; j++) {
388 for (i = 0; i < n; i++)
389 if (pa.val[i].etype == etypes[j])
391 for(i = 0; i < client->keys.len; i++) {
392 if(client->keys.val[i].key.keytype == etypes[j]) {
393 if (krb5_enctype_valid(context, etypes[j]) != 0)
395 if((ret = make_etype_info_entry(context,
397 &client->keys.val[i])) != 0) {
398 free_ETYPE_INFO(&pa);
405 for(i = 0; i < client->keys.len; i++) {
406 for(j = 0; j < etypes_len; j++) {
407 if(client->keys.val[i].key.keytype == etypes[j])
410 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
412 if((ret = make_etype_info_entry(context,
414 &client->keys.val[i])) != 0) {
415 free_ETYPE_INFO(&pa);
423 ret = krb5_unparse_name(context, client->principal, &name);
425 name = "<unparse_name failed>";
426 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
433 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
434 free_ETYPE_INFO(&pa);
437 ret = realloc_method_data(md);
442 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
443 md->val[md->len - 1].padata_value.length = len;
444 md->val[md->len - 1].padata_value.data = buf;
452 extern int _krb5_AES_string_to_default_iterator;
454 static krb5_error_code
455 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
457 ent->etype = key->key.keytype;
460 if (ent->salt == NULL)
462 *ent->salt = malloc(key->salt->salt.length + 1);
463 if (*ent->salt == NULL) {
468 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
469 (*ent->salt)[key->salt->salt.length] = '\0';
473 ent->s2kparams = NULL;
475 switch (key->key.keytype) {
478 ALLOC(ent->s2kparams);
479 if (ent->s2kparams == NULL)
481 ent->s2kparams->length = 4;
482 ent->s2kparams->data = malloc(ent->s2kparams->length);
483 if (ent->s2kparams->data == NULL) {
484 free(ent->s2kparams);
485 ent->s2kparams = NULL;
488 _krb5_put_int(ent->s2kparams->data,
489 _krb5_AES_string_to_default_iterator,
490 ent->s2kparams->length);
499 * Return 1 if the client have only older enctypes, this is for
500 * determining if the server should send ETYPE_INFO2 or not.
504 only_older_enctype_p(const KDC_REQ *req)
508 for(i = 0; i < req->req_body.etype.len; i++) {
509 switch (req->req_body.etype.val[i]) {
510 case ETYPE_DES_CBC_CRC:
511 case ETYPE_DES_CBC_MD4:
512 case ETYPE_DES_CBC_MD5:
513 case ETYPE_DES3_CBC_SHA1:
514 case ETYPE_ARCFOUR_HMAC_MD5:
515 case ETYPE_ARCFOUR_HMAC_MD5_56:
528 static krb5_error_code
529 get_pa_etype_info2(krb5_context context,
530 krb5_kdc_configuration *config,
531 METHOD_DATA *md, hdb_entry *client,
532 ENCTYPE *etypes, unsigned int etypes_len)
534 krb5_error_code ret = 0;
541 pa.len = client->keys.len;
542 if(pa.len > UINT_MAX/sizeof(*pa.val))
544 pa.val = malloc(pa.len * sizeof(*pa.val));
547 memset(pa.val, 0, pa.len * sizeof(*pa.val));
549 for(j = 0; j < etypes_len; j++) {
550 for (i = 0; i < n; i++)
551 if (pa.val[i].etype == etypes[j])
553 for(i = 0; i < client->keys.len; i++) {
554 if(client->keys.val[i].key.keytype == etypes[j]) {
555 if (krb5_enctype_valid(context, etypes[j]) != 0)
557 if((ret = make_etype_info2_entry(&pa.val[n++],
558 &client->keys.val[i])) != 0) {
559 free_ETYPE_INFO2(&pa);
566 for(i = 0; i < client->keys.len; i++) {
567 for(j = 0; j < etypes_len; j++) {
568 if(client->keys.val[i].key.keytype == etypes[j])
571 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
573 if((ret = make_etype_info2_entry(&pa.val[n++],
574 &client->keys.val[i])) != 0) {
575 free_ETYPE_INFO2(&pa);
583 ret = krb5_unparse_name(context, client->principal, &name);
585 name = "<unparse_name failed>";
586 kdc_log(context, config, 0,
587 "internal error in get_pa_etype_info2(%s): %d != %d",
594 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
595 free_ETYPE_INFO2(&pa);
598 ret = realloc_method_data(md);
603 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
604 md->val[md->len - 1].padata_value.length = len;
605 md->val[md->len - 1].padata_value.data = buf;
610 * verify the flags on `client' and `server', returning 0
611 * if they are OK and generating an error messages and returning
612 * and error code otherwise.
616 _kdc_check_flags(krb5_context context,
617 krb5_kdc_configuration *config,
618 hdb_entry *client, const char *client_name,
619 hdb_entry *server, const char *server_name,
620 krb5_boolean is_as_req)
624 if (client->flags.invalid) {
625 kdc_log(context, config, 0,
626 "Client (%s) has invalid bit set", client_name);
627 return KRB5KDC_ERR_POLICY;
630 if(!client->flags.client){
631 kdc_log(context, config, 0,
632 "Principal may not act as client -- %s", client_name);
633 return KRB5KDC_ERR_POLICY;
636 if (client->valid_start && *client->valid_start > kdc_time) {
637 kdc_log(context, config, 0,
638 "Client not yet valid -- %s", client_name);
639 return KRB5KDC_ERR_CLIENT_NOTYET;
642 if (client->valid_end && *client->valid_end < kdc_time) {
643 kdc_log(context, config, 0,
644 "Client expired -- %s", client_name);
645 return KRB5KDC_ERR_NAME_EXP;
648 if (client->pw_end && *client->pw_end < kdc_time
649 && !server->flags.change_pw) {
650 kdc_log(context, config, 0,
651 "Client's key has expired -- %s", client_name);
652 return KRB5KDC_ERR_KEY_EXPIRED;
658 if (server != NULL) {
659 if (server->flags.invalid) {
660 kdc_log(context, config, 0,
661 "Server has invalid flag set -- %s", server_name);
662 return KRB5KDC_ERR_POLICY;
665 if(!server->flags.server){
666 kdc_log(context, config, 0,
667 "Principal may not act as server -- %s", server_name);
668 return KRB5KDC_ERR_POLICY;
671 if(!is_as_req && server->flags.initial) {
672 kdc_log(context, config, 0,
673 "AS-REQ is required for server -- %s", server_name);
674 return KRB5KDC_ERR_POLICY;
677 if (server->valid_start && *server->valid_start > kdc_time) {
678 kdc_log(context, config, 0,
679 "Server not yet valid -- %s", server_name);
680 return KRB5KDC_ERR_SERVICE_NOTYET;
683 if (server->valid_end && *server->valid_end < kdc_time) {
684 kdc_log(context, config, 0,
685 "Server expired -- %s", server_name);
686 return KRB5KDC_ERR_SERVICE_EXP;
689 if (server->pw_end && *server->pw_end < kdc_time) {
690 kdc_log(context, config, 0,
691 "Server's key has expired -- %s", server_name);
692 return KRB5KDC_ERR_KEY_EXPIRED;
699 * Return TRUE if `from' is part of `addresses' taking into consideration
700 * the configuration variables that tells us how strict we should be about
705 check_addresses(krb5_context context,
706 krb5_kdc_configuration *config,
707 HostAddresses *addresses, const struct sockaddr *from)
713 if(config->check_ticket_addresses == 0)
716 if(addresses == NULL)
717 return config->allow_null_ticket_addresses;
719 ret = krb5_sockaddr2address (context, from, &addr);
723 result = krb5_address_search(context, &addr, addresses);
724 krb5_free_address (context, &addr);
729 _kdc_as_rep(krb5_context context,
730 krb5_kdc_configuration *config,
732 const krb5_data *req_buffer,
735 struct sockaddr *from_addr)
737 KDC_REQ_BODY *b = &req->req_body;
739 KDCOptions f = b->kdc_options;
740 hdb_entry *client = NULL, *server = NULL;
741 krb5_enctype cetype, setype;
744 krb5_principal client_princ = NULL, server_princ = NULL;
745 char *client_name = NULL, *server_name = NULL;
746 krb5_error_code ret = 0;
747 const char *e_text = NULL;
750 EncryptionKey *reply_key;
752 pk_client_params *pkp = NULL;
755 memset(&rep, 0, sizeof(rep));
757 if(b->sname == NULL){
758 ret = KRB5KRB_ERR_GENERIC;
759 e_text = "No server in request";
761 _krb5_principalname2krb5_principal (&server_princ,
762 *(b->sname), b->realm);
763 ret = krb5_unparse_name(context, server_princ, &server_name);
766 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
770 if(b->cname == NULL){
771 ret = KRB5KRB_ERR_GENERIC;
772 e_text = "No client in request";
774 _krb5_principalname2krb5_principal (&client_princ,
775 *(b->cname), b->realm);
776 ret = krb5_unparse_name(context, client_princ, &client_name);
779 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
783 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
784 client_name, from, server_name);
786 ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
788 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
789 krb5_get_err_text(context, ret));
790 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
794 ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
796 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
797 krb5_get_err_text(context, ret));
798 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
802 ret = _kdc_check_flags(context, config,
809 memset(&et, 0, sizeof(et));
810 memset(&ek, 0, sizeof(ek));
818 kdc_log(context, config, 5,
819 "Looking for PKINIT pa-data -- %s", client_name);
821 e_text = "No PKINIT PA found";
824 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
828 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
833 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
837 char *client_cert = NULL;
839 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
841 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
842 kdc_log(context, config, 5,
843 "Failed to decode PKINIT PA-DATA -- %s",
847 if (ret == 0 && pkp == NULL)
850 ret = _kdc_pk_check_client(context,
857 e_text = "PKINIT certificate not allowed to "
858 "impersonate principal";
859 _kdc_pk_free_client_param(context, pkp);
864 et.flags.pre_authent = 1;
865 kdc_log(context, config, 2,
866 "PKINIT pre-authentication succeeded -- %s using %s",
867 client_name, client_cert);
874 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
878 e_text = "No ENC-TS found";
879 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
883 EncryptedData enc_data;
889 ret = decode_EncryptedData(pa->padata_value.data,
890 pa->padata_value.length,
894 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
895 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
900 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
903 e_text = "No key matches pa-data";
904 ret = KRB5KDC_ERR_PREAUTH_FAILED;
905 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
908 kdc_log(context, config, 5,
909 "No client key matching pa-data (%d) -- %s",
910 enc_data.etype, client_name);
912 kdc_log(context, config, 5,
913 "No client key matching pa-data (%s) -- %s",
917 free_EncryptedData(&enc_data);
922 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
924 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
925 krb5_get_err_text(context, ret));
926 free_EncryptedData(&enc_data);
930 ret = krb5_decrypt_EncryptedData (context,
932 KRB5_KU_PA_ENC_TIMESTAMP,
935 krb5_crypto_destroy(context, crypto);
937 krb5_error_code ret2;
938 ret2 = krb5_enctype_to_string(context,
939 pa_key->key.keytype, &str);
942 kdc_log(context, config, 5,
943 "Failed to decrypt PA-DATA -- %s "
944 "(enctype %s) error %s",
946 str ? str : "unknown enctype",
947 krb5_get_err_text(context, ret));
950 if(hdb_next_enctype2key(context, client,
951 enc_data.etype, &pa_key) == 0)
953 e_text = "Failed to decrypt PA-DATA";
955 free_EncryptedData(&enc_data);
956 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
959 free_EncryptedData(&enc_data);
960 ret = decode_PA_ENC_TS_ENC(ts_data.data,
964 krb5_data_free(&ts_data);
966 e_text = "Failed to decode PA-ENC-TS-ENC";
967 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
968 kdc_log(context, config,
969 5, "Failed to decode PA-ENC-TS_ENC -- %s",
973 free_PA_ENC_TS_ENC(&p);
974 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
975 ret = KRB5KDC_ERR_PREAUTH_FAILED;
976 e_text = "Too large time skew";
977 kdc_log(context, config, 0,
978 "Too large time skew -- %s", client_name);
981 et.flags.pre_authent = 1;
983 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
987 kdc_log(context, config, 2,
988 "ENC-TS Pre-authentication succeeded -- %s using %s",
989 client_name, str ? str : "unknown enctype");
996 if(found_pa == 0 && config->require_preauth)
998 /* We come here if we found a pa-enc-timestamp, but if there
999 was some problem with it, other than too large skew */
1000 if(found_pa && et.flags.pre_authent == 0){
1001 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1005 }else if (config->require_preauth
1006 || client->flags.require_preauth
1007 || server->flags.require_preauth) {
1008 METHOD_DATA method_data;
1015 method_data.len = 0;
1016 method_data.val = NULL;
1018 ret = realloc_method_data(&method_data);
1019 pa = &method_data.val[method_data.len-1];
1020 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
1021 pa->padata_value.length = 0;
1022 pa->padata_value.data = NULL;
1025 ret = realloc_method_data(&method_data);
1026 pa = &method_data.val[method_data.len-1];
1027 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
1028 pa->padata_value.length = 0;
1029 pa->padata_value.data = NULL;
1031 ret = realloc_method_data(&method_data);
1032 pa = &method_data.val[method_data.len-1];
1033 pa->padata_type = KRB5_PADATA_PK_AS_REQ_19;
1034 pa->padata_value.length = 0;
1035 pa->padata_value.data = NULL;
1039 if (only_older_enctype_p(req))
1040 ret = get_pa_etype_info(context, config, &method_data, client,
1041 b->etype.val, b->etype.len);
1043 ret = get_pa_etype_info2(context, config, &method_data, client,
1044 b->etype.val, b->etype.len);
1047 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1048 free_METHOD_DATA(&method_data);
1049 foo_data.data = buf;
1050 foo_data.length = len;
1052 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1053 krb5_mk_error(context,
1055 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1063 kdc_log(context, config, 0,
1064 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1070 ret = find_keys(context, config,
1071 client, server, &ckey, &cetype, &skey, &setype,
1072 b->etype.val, b->etype.len);
1074 kdc_log(context, config, 0, "Server/client has no support for etypes");
1079 struct rk_strpool *p = NULL;
1083 for (i = 0; i < b->etype.len; i++) {
1084 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1086 p = rk_strpoolprintf(p, "%s", str);
1089 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1090 if (p && i + 1 < b->etype.len)
1091 p = rk_strpoolprintf(p, ", ");
1093 kdc_log(context, config, 0, "out of meory");
1097 str = rk_strpoolcollect(p);
1098 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1105 ret = krb5_enctype_to_string(context, cetype, &cet);
1107 ret = krb5_enctype_to_string(context, setype, &set);
1109 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1115 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1120 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1123 kdc_log(context, config, 2, "Requested flags: %s", str);
1127 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1128 || (f.request_anonymous && !config->allow_anonymous)) {
1129 ret = KRB5KDC_ERR_BADOPTION;
1130 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1135 rep.msg_type = krb_as_rep;
1136 copy_Realm(&client->principal->realm, &rep.crealm);
1137 if (f.request_anonymous)
1138 make_anonymous_principalname (&rep.cname);
1140 _krb5_principal2principalname(&rep.cname,
1142 rep.ticket.tkt_vno = 5;
1143 copy_Realm(&server->principal->realm, &rep.ticket.realm);
1144 _krb5_principal2principalname(&rep.ticket.sname,
1147 et.flags.initial = 1;
1148 if(client->flags.forwardable && server->flags.forwardable)
1149 et.flags.forwardable = f.forwardable;
1150 else if (f.forwardable) {
1151 ret = KRB5KDC_ERR_POLICY;
1152 kdc_log(context, config, 0,
1153 "Ticket may not be forwardable -- %s", client_name);
1156 if(client->flags.proxiable && server->flags.proxiable)
1157 et.flags.proxiable = f.proxiable;
1158 else if (f.proxiable) {
1159 ret = KRB5KDC_ERR_POLICY;
1160 kdc_log(context, config, 0,
1161 "Ticket may not be proxiable -- %s", client_name);
1164 if(client->flags.postdate && server->flags.postdate)
1165 et.flags.may_postdate = f.allow_postdate;
1166 else if (f.allow_postdate){
1167 ret = KRB5KDC_ERR_POLICY;
1168 kdc_log(context, config, 0,
1169 "Ticket may not be postdatable -- %s", client_name);
1173 /* check for valid set of addresses */
1174 if(!check_addresses(context, config, b->addresses, from_addr)) {
1175 ret = KRB5KRB_AP_ERR_BADADDR;
1176 kdc_log(context, config, 0,
1177 "Bad address list requested -- %s", client_name);
1181 krb5_generate_random_keyblock(context, setype, &et.key);
1182 copy_PrincipalName(&rep.cname, &et.cname);
1183 copy_Realm(&rep.crealm, &et.crealm);
1189 start = et.authtime = kdc_time;
1191 if(f.postdated && req->req_body.from){
1192 ALLOC(et.starttime);
1193 start = *et.starttime = *req->req_body.from;
1194 et.flags.invalid = 1;
1195 et.flags.postdated = 1; /* XXX ??? */
1200 /* be careful not overflowing */
1202 if(client->max_life)
1203 t = start + min(t - start, *client->max_life);
1204 if(server->max_life)
1205 t = start + min(t - start, *server->max_life);
1207 t = min(t, start + realm->max_life);
1210 if(f.renewable_ok && et.endtime < *b->till){
1212 if(b->rtime == NULL){
1216 if(*b->rtime < *b->till)
1217 *b->rtime = *b->till;
1219 if(f.renewable && b->rtime){
1223 if(client->max_renew)
1224 t = start + min(t - start, *client->max_renew);
1225 if(server->max_renew)
1226 t = start + min(t - start, *server->max_renew);
1228 t = min(t, start + realm->max_renew);
1230 ALLOC(et.renew_till);
1232 et.flags.renewable = 1;
1236 if (f.request_anonymous)
1237 et.flags.anonymous = 1;
1241 copy_HostAddresses(b->addresses, et.caddr);
1244 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1245 krb5_data_zero(&et.transited.contents);
1247 copy_EncryptionKey(&et.key, &ek.key);
1249 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1250 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1251 * incapable of correctly decoding SEQUENCE OF's of zero length.
1253 * To fix this, always send at least one no-op last_req
1255 * If there's a pw_end or valid_end we will use that,
1256 * otherwise just a dummy lr.
1258 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1259 ek.last_req.len = 0;
1261 && (config->kdc_warn_pwexpire == 0
1262 || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) {
1263 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1264 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
1267 if (client->valid_end) {
1268 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1269 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
1272 if (ek.last_req.len == 0) {
1273 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1274 ek.last_req.val[ek.last_req.len].lr_value = 0;
1277 ek.nonce = b->nonce;
1278 if (client->valid_end || client->pw_end) {
1279 ALLOC(ek.key_expiration);
1280 if (client->valid_end) {
1282 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1284 *ek.key_expiration = *client->valid_end;
1286 *ek.key_expiration = *client->pw_end;
1288 ek.key_expiration = NULL;
1289 ek.flags = et.flags;
1290 ek.authtime = et.authtime;
1292 ALLOC(ek.starttime);
1293 *ek.starttime = *et.starttime;
1295 ek.endtime = et.endtime;
1296 if (et.renew_till) {
1297 ALLOC(ek.renew_till);
1298 *ek.renew_till = *et.renew_till;
1300 copy_Realm(&rep.ticket.realm, &ek.srealm);
1301 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1304 copy_HostAddresses(et.caddr, ek.caddr);
1308 rep.padata->len = 0;
1309 rep.padata->val = NULL;
1311 reply_key = &ckey->key;
1314 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1316 &reply_key, rep.padata);
1322 set_salt_padata (rep.padata, ckey->salt);
1324 if (rep.padata->len == 0) {
1329 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1330 et.endtime, et.renew_till);
1332 ret = encode_reply(context, config,
1333 &rep, &et, &ek, setype, server->kvno, &skey->key,
1334 client->kvno, reply_key, &e_text, reply);
1335 free_EncTicketPart(&et);
1336 free_EncKDCRepPart(&ek);
1340 krb5_mk_error(context,
1354 _kdc_pk_free_client_param(context, pkp);
1357 krb5_free_principal(context, client_princ);
1360 krb5_free_principal(context, server_princ);
1363 _kdc_free_ent(context, client);
1365 _kdc_free_ent(context, server);
1370 static krb5_error_code
1371 check_tgs_flags(krb5_context context,
1372 krb5_kdc_configuration *config,
1373 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1375 KDCOptions f = b->kdc_options;
1378 if(!tgt->flags.invalid || tgt->starttime == NULL){
1379 kdc_log(context, config, 0,
1380 "Bad request to validate ticket");
1381 return KRB5KDC_ERR_BADOPTION;
1383 if(*tgt->starttime > kdc_time){
1384 kdc_log(context, config, 0,
1385 "Early request to validate ticket");
1386 return KRB5KRB_AP_ERR_TKT_NYV;
1389 et->flags.invalid = 0;
1390 }else if(tgt->flags.invalid){
1391 kdc_log(context, config, 0,
1392 "Ticket-granting ticket has INVALID flag set");
1393 return KRB5KRB_AP_ERR_TKT_INVALID;
1397 if(!tgt->flags.forwardable){
1398 kdc_log(context, config, 0,
1399 "Bad request for forwardable ticket");
1400 return KRB5KDC_ERR_BADOPTION;
1402 et->flags.forwardable = 1;
1405 if(!tgt->flags.forwardable){
1406 kdc_log(context, config, 0,
1407 "Request to forward non-forwardable ticket");
1408 return KRB5KDC_ERR_BADOPTION;
1410 et->flags.forwarded = 1;
1411 et->caddr = b->addresses;
1413 if(tgt->flags.forwarded)
1414 et->flags.forwarded = 1;
1417 if(!tgt->flags.proxiable){
1418 kdc_log(context, config, 0,
1419 "Bad request for proxiable ticket");
1420 return KRB5KDC_ERR_BADOPTION;
1422 et->flags.proxiable = 1;
1425 if(!tgt->flags.proxiable){
1426 kdc_log(context, config, 0,
1427 "Request to proxy non-proxiable ticket");
1428 return KRB5KDC_ERR_BADOPTION;
1430 et->flags.proxy = 1;
1431 et->caddr = b->addresses;
1433 if(tgt->flags.proxy)
1434 et->flags.proxy = 1;
1436 if(f.allow_postdate){
1437 if(!tgt->flags.may_postdate){
1438 kdc_log(context, config, 0,
1439 "Bad request for post-datable ticket");
1440 return KRB5KDC_ERR_BADOPTION;
1442 et->flags.may_postdate = 1;
1445 if(!tgt->flags.may_postdate){
1446 kdc_log(context, config, 0,
1447 "Bad request for postdated ticket");
1448 return KRB5KDC_ERR_BADOPTION;
1451 *et->starttime = *b->from;
1452 et->flags.postdated = 1;
1453 et->flags.invalid = 1;
1454 }else if(b->from && *b->from > kdc_time + context->max_skew){
1455 kdc_log(context, config, 0, "Ticket cannot be postdated");
1456 return KRB5KDC_ERR_CANNOT_POSTDATE;
1460 if(!tgt->flags.renewable){
1461 kdc_log(context, config, 0,
1462 "Bad request for renewable ticket");
1463 return KRB5KDC_ERR_BADOPTION;
1465 et->flags.renewable = 1;
1466 ALLOC(et->renew_till);
1467 fix_time(&b->rtime);
1468 *et->renew_till = *b->rtime;
1472 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1473 kdc_log(context, config, 0,
1474 "Request to renew non-renewable ticket");
1475 return KRB5KDC_ERR_BADOPTION;
1477 old_life = tgt->endtime;
1479 old_life -= *tgt->starttime;
1481 old_life -= tgt->authtime;
1482 et->endtime = *et->starttime + old_life;
1483 if (et->renew_till != NULL)
1484 et->endtime = min(*et->renew_till, et->endtime);
1487 /* checks for excess flags */
1488 if(f.request_anonymous && !config->allow_anonymous){
1489 kdc_log(context, config, 0,
1490 "Request for anonymous ticket");
1491 return KRB5KDC_ERR_BADOPTION;
1496 static krb5_error_code
1497 fix_transited_encoding(krb5_context context,
1498 krb5_kdc_configuration *config,
1499 krb5_boolean check_policy,
1500 TransitedEncoding *tr,
1502 const char *client_realm,
1503 const char *server_realm,
1504 const char *tgt_realm)
1506 krb5_error_code ret = 0;
1507 char **realms, **tmp;
1511 if(tr->tr_type != DOMAIN_X500_COMPRESS) {
1512 kdc_log(context, config, 0,
1513 "Unknown transited type: %u", tr->tr_type);
1514 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1517 ret = krb5_domain_x500_decode(context,
1524 krb5_warn(context, ret,
1525 "Decoding transited encoding");
1528 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1529 /* not us, so add the previous realm to transited set */
1530 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1534 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1540 realms[num_realms] = strdup(tgt_realm);
1541 if(realms[num_realms] == NULL){
1547 if(num_realms == 0) {
1548 if(strcmp(client_realm, server_realm))
1549 kdc_log(context, config, 0,
1550 "cross-realm %s -> %s", client_realm, server_realm);
1554 for(i = 0; i < num_realms; i++)
1555 l += strlen(realms[i]) + 2;
1559 for(i = 0; i < num_realms; i++) {
1561 strlcat(rs, ", ", l);
1562 strlcat(rs, realms[i], l);
1564 kdc_log(context, config, 0,
1565 "cross-realm %s -> %s via [%s]",
1566 client_realm, server_realm, rs);
1571 ret = krb5_check_transited(context, client_realm,
1573 realms, num_realms, NULL);
1575 krb5_warn(context, ret, "cross-realm %s -> %s",
1576 client_realm, server_realm);
1579 et->flags.transited_policy_checked = 1;
1581 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1582 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1584 krb5_warn(context, ret, "Encoding transited encoding");
1586 for(i = 0; i < num_realms; i++)
1593 static krb5_error_code
1594 tgs_make_reply(krb5_context context,
1595 krb5_kdc_configuration *config,
1598 EncTicketPart *adtkt,
1599 AuthorizationData *auth_data,
1602 krb5_principal client_principal,
1604 EncryptionKey *tgtkey,
1605 krb5_enctype cetype,
1606 const char **e_text,
1612 KDCOptions f = b->kdc_options;
1613 krb5_error_code ret;
1616 EncryptionKey *ekey;
1622 for(i = 0; i < b->etype.len; i++){
1623 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1626 if(adtkt->key.keytype == kt)
1629 if(i == b->etype.len)
1630 return KRB5KDC_ERR_ETYPE_NOSUPP;
1631 etype = b->etype.val[i];
1633 ret = find_keys(context, config,
1634 NULL, server, NULL, NULL, &skey, &etype,
1635 b->etype.val, b->etype.len);
1637 kdc_log(context, config, 0, "Server has no support for etypes");
1643 memset(&rep, 0, sizeof(rep));
1644 memset(&et, 0, sizeof(et));
1645 memset(&ek, 0, sizeof(ek));
1648 rep.msg_type = krb_tgs_rep;
1650 et.authtime = tgt->authtime;
1652 et.endtime = min(tgt->endtime, *b->till);
1653 ALLOC(et.starttime);
1654 *et.starttime = kdc_time;
1656 ret = check_tgs_flags(context, config, b, tgt, &et);
1660 /* We should check the transited encoding if:
1661 1) the request doesn't ask not to be checked
1662 2) globally enforcing a check
1663 3) principal requires checking
1664 4) we allow non-check per-principal, but principal isn't marked as allowing this
1665 5) we don't globally allow this
1668 #define GLOBAL_FORCE_TRANSITED_CHECK \
1669 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1670 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1671 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1672 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1673 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1675 /* these will consult the database in future release */
1676 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1677 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1679 ret = fix_transited_encoding(context, config,
1680 !f.disable_transited_check ||
1681 GLOBAL_FORCE_TRANSITED_CHECK ||
1682 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1683 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1684 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1685 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1686 &tgt->transited, &et,
1687 *krb5_princ_realm(context, client_principal),
1688 *krb5_princ_realm(context, server->principal),
1689 *krb5_princ_realm(context, krbtgt->principal));
1693 copy_Realm(krb5_princ_realm(context, server->principal),
1695 _krb5_principal2principalname(&rep.ticket.sname, server->principal);
1696 copy_Realm(&tgt->crealm, &rep.crealm);
1697 if (f.request_anonymous)
1698 make_anonymous_principalname (&tgt->cname);
1700 copy_PrincipalName(&tgt->cname, &rep.cname);
1701 rep.ticket.tkt_vno = 5;
1703 ek.caddr = et.caddr;
1704 if(et.caddr == NULL)
1705 et.caddr = tgt->caddr;
1709 life = et.endtime - *et.starttime;
1710 if(client && client->max_life)
1711 life = min(life, *client->max_life);
1712 if(server->max_life)
1713 life = min(life, *server->max_life);
1714 et.endtime = *et.starttime + life;
1716 if(f.renewable_ok && tgt->flags.renewable &&
1717 et.renew_till == NULL && et.endtime < *b->till){
1718 et.flags.renewable = 1;
1719 ALLOC(et.renew_till);
1720 *et.renew_till = *b->till;
1724 renew = *et.renew_till - et.authtime;
1725 if(client && client->max_renew)
1726 renew = min(renew, *client->max_renew);
1727 if(server->max_renew)
1728 renew = min(renew, *server->max_renew);
1729 *et.renew_till = et.authtime + renew;
1733 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1734 *et.starttime = min(*et.starttime, *et.renew_till);
1735 et.endtime = min(et.endtime, *et.renew_till);
1738 *et.starttime = min(*et.starttime, et.endtime);
1740 if(*et.starttime == et.endtime){
1741 ret = KRB5KDC_ERR_NEVER_VALID;
1744 if(et.renew_till && et.endtime == *et.renew_till){
1745 free(et.renew_till);
1746 et.renew_till = NULL;
1747 et.flags.renewable = 0;
1750 et.flags.pre_authent = tgt->flags.pre_authent;
1751 et.flags.hw_authent = tgt->flags.hw_authent;
1752 et.flags.anonymous = tgt->flags.anonymous;
1753 et.flags.ok_as_delegate = server->flags.ok_as_delegate;
1755 #ifdef _SAMBA_BUILD_
1764 AD_IF_RELEVANT *if_relevant;
1766 if_relevant->len = 1;
1767 if_relevant->val = malloc(sizeof(*if_relevant->val));
1768 if_relevant->val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
1769 if_relevant->val[0].ad_data.data = NULL;
1770 if_relevant->val[0].ad_data.length = 0;
1772 /* Get PAC from Samba */
1773 ret = samba_get_pac(context, config,
1779 free_AuthorizationData(if_relevant);
1783 /* pac.data will be freed with this */
1784 if_relevant->val[0].ad_data.data = pac.data;
1785 if_relevant->val[0].ad_data.length = pac.length;
1787 ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1792 auth_data->val = malloc(sizeof(*auth_data->val));
1793 auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1794 auth_data->val[0].ad_data.length = len;
1795 auth_data->val[0].ad_data.data = buf;
1802 /* XXX Check enc-authorization-data */
1803 et.authorization_data = auth_data;
1805 krb5_generate_random_keyblock(context, etype, &et.key);
1806 et.crealm = tgt->crealm;
1807 et.cname = tgt->cname;
1810 /* MIT must have at least one last_req */
1811 ek.last_req.len = 1;
1812 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1813 ek.nonce = b->nonce;
1814 ek.flags = et.flags;
1815 ek.authtime = et.authtime;
1816 ek.starttime = et.starttime;
1817 ek.endtime = et.endtime;
1818 ek.renew_till = et.renew_till;
1819 ek.srealm = rep.ticket.realm;
1820 ek.sname = rep.ticket.sname;
1822 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1823 et.endtime, et.renew_till);
1825 /* It is somewhat unclear where the etype in the following
1826 encryption should come from. What we have is a session
1827 key in the passed tgt, and a list of preferred etypes
1828 *for the new ticket*. Should we pick the best possible
1829 etype, given the keytype in the tgt, or should we look
1830 at the etype list here as well? What if the tgt
1831 session key is DES3 and we want a ticket with a (say)
1832 CAST session key. Should the DES3 etype be added to the
1833 etype list, even if we don't want a session key with
1835 ret = encode_reply(context, config,
1836 &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1837 0, &tgt->key, e_text, reply);
1840 free_TransitedEncoding(&et.transited);
1844 free(et.renew_till);
1845 free_LastReq(&ek.last_req);
1846 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1847 free_EncryptionKey(&et.key);
1851 static krb5_error_code
1852 tgs_check_authenticator(krb5_context context,
1853 krb5_kdc_configuration *config,
1854 krb5_auth_context ac,
1856 const char **e_text,
1859 krb5_authenticator auth;
1863 krb5_error_code ret;
1866 krb5_auth_con_getauthenticator(context, ac, &auth);
1867 if(auth->cksum == NULL){
1868 kdc_log(context, config, 0, "No authenticator in request");
1869 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1873 * according to RFC1510 it doesn't need to be keyed,
1874 * but according to the latest draft it needs to.
1878 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1881 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1882 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1883 auth->cksum->cksumtype);
1884 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1888 /* XXX should not re-encode this */
1889 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1891 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
1892 krb5_get_err_text(context, ret));
1895 if(buf_size != len) {
1897 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1898 *e_text = "KDC internal error";
1899 ret = KRB5KRB_ERR_GENERIC;
1902 ret = krb5_crypto_init(context, key, 0, &crypto);
1905 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1906 krb5_get_err_text(context, ret));
1909 ret = krb5_verify_checksum(context,
1911 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1916 krb5_crypto_destroy(context, crypto);
1918 kdc_log(context, config, 0,
1919 "Failed to verify authenticator checksum: %s",
1920 krb5_get_err_text(context, ret));
1923 free_Authenticator(auth);
1929 * return the realm of a krbtgt-ticket or NULL
1933 get_krbtgt_realm(const PrincipalName *p)
1935 if(p->name_string.len == 2
1936 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1937 return p->name_string.val[1];
1943 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1945 const char *new_realm = krb5_config_get_string(context,
1956 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1958 if(server->name.name_type != KRB5_NT_SRV_INST ||
1959 server->name.name_string.len != 2)
1962 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1963 FALSE, realms) == 0;
1966 static krb5_error_code
1967 tgs_rep2(krb5_context context,
1968 krb5_kdc_configuration *config,
1973 const struct sockaddr *from_addr,
1978 krb5_error_code ret;
1979 krb5_principal princ;
1980 krb5_auth_context ac = NULL;
1981 krb5_ticket *ticket = NULL;
1982 krb5_flags ap_req_options;
1983 krb5_flags verify_ap_req_flags;
1984 const char *e_text = NULL;
1987 hdb_entry *krbtgt = NULL;
1990 krb5_enctype cetype;
1991 krb5_principal cp = NULL;
1992 krb5_principal sp = NULL;
1993 AuthorizationData *auth_data = NULL;
1998 memset(&ap_req, 0, sizeof(ap_req));
1999 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2001 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
2002 krb5_get_err_text(context, ret));
2006 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2007 /* XXX check for ticket.sname == req.sname */
2008 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2009 ret = KRB5KDC_ERR_POLICY; /* ? */
2013 _krb5_principalname2krb5_principal(&princ,
2014 ap_req.ticket.sname,
2015 ap_req.ticket.realm);
2017 ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
2021 ret = krb5_unparse_name(context, princ, &p);
2023 p = "<unparse_name failed>";
2024 krb5_free_principal(context, princ);
2025 kdc_log(context, config, 0,
2026 "Ticket-granting ticket not found in database: %s: %s",
2027 p, krb5_get_err_text(context, ret));
2030 ret = KRB5KRB_AP_ERR_NOT_US;
2034 if(ap_req.ticket.enc_part.kvno &&
2035 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
2038 ret = krb5_unparse_name (context, princ, &p);
2039 krb5_free_principal(context, princ);
2041 p = "<unparse_name failed>";
2042 kdc_log(context, config, 0,
2043 "Ticket kvno = %d, DB kvno = %d (%s)",
2044 *ap_req.ticket.enc_part.kvno,
2049 ret = KRB5KRB_AP_ERR_BADKEYVER;
2053 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2056 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2057 kdc_log(context, config, 0,
2058 "No server key found for %s", str);
2060 ret = KRB5KRB_AP_ERR_BADKEYVER;
2064 if (b->kdc_options.validate)
2065 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2067 verify_ap_req_flags = 0;
2069 ret = krb5_verify_ap_req2(context,
2074 verify_ap_req_flags,
2077 KRB5_KU_TGS_REQ_AUTH);
2079 krb5_free_principal(context, princ);
2081 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2082 krb5_get_err_text(context, ret));
2087 krb5_authenticator auth;
2089 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2091 *csec = malloc(sizeof(**csec));
2092 if (*csec == NULL) {
2093 krb5_free_authenticator(context, &auth);
2094 kdc_log(context, config, 0, "malloc failed");
2097 **csec = auth->ctime;
2098 *cusec = malloc(sizeof(**cusec));
2099 if (*cusec == NULL) {
2100 krb5_free_authenticator(context, &auth);
2101 kdc_log(context, config, 0, "malloc failed");
2104 **csec = auth->cusec;
2105 krb5_free_authenticator(context, &auth);
2109 cetype = ap_req.authenticator.etype;
2111 tgt = &ticket->ticket;
2113 ret = tgs_check_authenticator(context, config,
2114 ac, b, &e_text, &tgt->key);
2116 krb5_auth_con_free(context, ac);
2120 if (b->enc_authorization_data) {
2121 krb5_keyblock *subkey;
2123 ret = krb5_auth_con_getremotesubkey(context,
2127 krb5_auth_con_free(context, ac);
2128 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2129 krb5_get_err_text(context, ret));
2133 ret = krb5_auth_con_getkey(context, ac, &subkey);
2135 krb5_auth_con_free(context, ac);
2136 kdc_log(context, config, 0, "Failed to get session key: %s",
2137 krb5_get_err_text(context, ret));
2142 krb5_auth_con_free(context, ac);
2143 kdc_log(context, config, 0,
2144 "Failed to get key for enc-authorization-data");
2145 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2148 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2150 krb5_auth_con_free(context, ac);
2151 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2152 krb5_get_err_text(context, ret));
2155 ret = krb5_decrypt_EncryptedData (context,
2157 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2158 b->enc_authorization_data,
2160 krb5_crypto_destroy(context, crypto);
2162 krb5_auth_con_free(context, ac);
2163 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2164 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2167 krb5_free_keyblock(context, subkey);
2169 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2171 krb5_auth_con_free(context, ac);
2174 kdc_log(context, config, 0, "Failed to decode authorization data");
2175 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2180 krb5_auth_con_free(context, ac);
2185 char *spn = NULL, *cpn = NULL;
2186 hdb_entry *server = NULL, *client = NULL;
2188 EncTicketPart adtkt;
2193 if(b->kdc_options.enc_tkt_in_skey){
2199 if(b->additional_tickets == NULL ||
2200 b->additional_tickets->len == 0){
2201 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2202 kdc_log(context, config, 0,
2203 "No second ticket present in request");
2206 t = &b->additional_tickets->val[0];
2207 if(!get_krbtgt_realm(&t->sname)){
2208 kdc_log(context, config, 0,
2209 "Additional ticket is not a ticket-granting ticket");
2210 ret = KRB5KDC_ERR_POLICY;
2213 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2214 ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2215 krb5_free_principal(context, p);
2217 if (ret == HDB_ERR_NOENTRY)
2218 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2221 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2223 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2226 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2234 _krb5_principalname2krb5_principal(&sp, *s, r);
2235 ret = krb5_unparse_name(context, sp, &spn);
2238 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2239 ret = krb5_unparse_name(context, cp, &cpn);
2242 unparse_flags (KDCOptions2int(b->kdc_options),
2243 asn1_KDCOptions_units(),
2244 opt_str, sizeof(opt_str));
2246 kdc_log(context, config, 0,
2247 "TGS-REQ %s from %s for %s [%s]",
2248 cpn, from, spn, opt_str);
2250 kdc_log(context, config, 0,
2251 "TGS-REQ %s from %s for %s", cpn, from, spn);
2253 ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2256 const char *new_rlm;
2260 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2262 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2264 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2266 krb5_free_principal(context, sp);
2268 krb5_make_principal(context, &sp, r,
2269 KRB5_TGS_NAME, new_rlm, NULL);
2270 ret = krb5_unparse_name(context, sp, &spn);
2276 } else if(need_referral(context, sp, &realms)) {
2277 if (strcmp(realms[0], sp->realm) != 0) {
2278 kdc_log(context, config, 5,
2279 "Returning a referral to realm %s for "
2280 "server %s that was not found",
2282 krb5_free_principal(context, sp);
2284 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2286 ret = krb5_unparse_name(context, sp, &spn);
2289 krb5_free_host_realm(context, realms);
2292 krb5_free_host_realm(context, realms);
2294 kdc_log(context, config, 0,
2295 "Server not found in database: %s: %s", spn,
2296 krb5_get_err_text(context, ret));
2297 if (ret == HDB_ERR_NOENTRY)
2298 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2302 ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2304 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2305 cpn, krb5_get_err_text(context, ret));
2307 /* XXX check client only if same realm as krbtgt-instance */
2309 kdc_log(context, config, 0,
2310 "Client not found in database: %s: %s",
2311 cpn, krb5_get_err_text(context, ret));
2312 if (ret == HDB_ERR_NOENTRY)
2313 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2318 if(strcmp(krb5_principal_get_realm(context, sp),
2319 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2321 ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2322 kdc_log(context, config, 0,
2323 "Request with wrong krbtgt: %s",
2324 (ret == 0) ? tpn : "<unknown>");
2327 ret = KRB5KRB_AP_ERR_NOT_US;
2332 ret = _kdc_check_flags(context, config,
2339 if((b->kdc_options.validate || b->kdc_options.renew) &&
2340 !krb5_principal_compare(context,
2342 server->principal)){
2343 kdc_log(context, config, 0, "Inconsistent request.");
2344 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2348 /* check for valid set of addresses */
2349 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2350 ret = KRB5KRB_AP_ERR_BADADDR;
2351 kdc_log(context, config, 0, "Request from wrong address");
2355 ret = tgs_make_reply(context, config,
2358 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2374 _kdc_free_ent(context, server);
2376 _kdc_free_ent(context, client);
2380 krb5_mk_error(context,
2394 krb5_free_principal(context, cp);
2395 krb5_free_principal(context, sp);
2397 krb5_free_ticket(context, ticket);
2398 free_AP_REQ(&ap_req);
2400 free_AuthorizationData(auth_data);
2405 _kdc_free_ent(context, krbtgt);
2412 _kdc_tgs_rep(krb5_context context,
2413 krb5_kdc_configuration *config,
2417 struct sockaddr *from_addr)
2419 krb5_error_code ret;
2421 PA_DATA *tgs_req = NULL;
2422 time_t *csec = NULL;
2425 if(req->padata == NULL){
2426 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2427 kdc_log(context, config, 0,
2428 "TGS-REQ from %s without PA-DATA", from);
2432 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2434 if(tgs_req == NULL){
2435 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2437 kdc_log(context, config, 0,
2438 "TGS-REQ from %s without PA-TGS-REQ", from);
2441 ret = tgs_rep2(context, config,
2442 &req->req_body, tgs_req, data, from, from_addr,
2445 if(ret && data->data == NULL){
2446 krb5_mk_error(context,