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 endtime: %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;
333 ALLOC(ent->salttype);
335 if(key->salt->type == hdb_pw_salt)
336 *ent->salttype = 0; /* or 1? or NULL? */
337 else if(key->salt->type == hdb_afs3_salt)
340 kdc_log(context, config, 0, "unknown salt-type: %d",
342 return KRB5KRB_ERR_GENERIC;
344 /* according to `the specs', we can't send a salt if
345 we have AFS3 salted key, but that requires that you
346 *know* what cell you are using (e.g by assuming
347 that the cell is the same as the realm in lower
350 ALLOC(ent->salttype);
351 *ent->salttype = key->salt->type;
354 * We shouldn't sent salttype since its incompatible with the
355 * specification and its break windows clients. The afs
356 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
357 * implemented in Heimdal 0.7 and later.
359 ent->salttype = NULL;
361 krb5_copy_data(context, &key->salt->salt,
364 /* we return no salt type at all, as that should indicate
365 * the default salt type and make everybody happy. some
366 * systems (like w2k) dislike being told the salt type
369 ent->salttype = NULL;
375 static krb5_error_code
376 get_pa_etype_info(krb5_context context,
377 krb5_kdc_configuration *config,
378 METHOD_DATA *md, hdb_entry *client,
379 ENCTYPE *etypes, unsigned int etypes_len)
381 krb5_error_code ret = 0;
389 pa.len = client->keys.len;
390 if(pa.len > UINT_MAX/sizeof(*pa.val))
392 pa.val = malloc(pa.len * sizeof(*pa.val));
395 memset(pa.val, 0, pa.len * sizeof(*pa.val));
397 for(j = 0; j < etypes_len; j++) {
398 for (i = 0; i < n; i++)
399 if (pa.val[i].etype == etypes[j])
401 for(i = 0; i < client->keys.len; i++) {
402 if(client->keys.val[i].key.keytype == etypes[j]) {
403 if (krb5_enctype_valid(context, etypes[j]) != 0)
405 if((ret = make_etype_info_entry(context,
407 &client->keys.val[i])) != 0) {
408 free_ETYPE_INFO(&pa);
415 for(i = 0; i < client->keys.len; i++) {
416 for(j = 0; j < etypes_len; j++) {
417 if(client->keys.val[i].key.keytype == etypes[j])
420 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
422 if((ret = make_etype_info_entry(context,
424 &client->keys.val[i])) != 0) {
425 free_ETYPE_INFO(&pa);
433 ret = krb5_unparse_name(context, client->principal, &name);
435 name = "<unparse_name failed>";
436 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
443 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
444 free_ETYPE_INFO(&pa);
447 ret = realloc_method_data(md);
452 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
453 md->val[md->len - 1].padata_value.length = len;
454 md->val[md->len - 1].padata_value.data = buf;
462 extern int _krb5_AES_string_to_default_iterator;
464 static krb5_error_code
465 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
467 ent->etype = key->key.keytype;
470 if (ent->salt == NULL)
472 *ent->salt = malloc(key->salt->salt.length + 1);
473 if (*ent->salt == NULL) {
478 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
479 (*ent->salt)[key->salt->salt.length] = '\0';
483 ent->s2kparams = NULL;
485 switch (key->key.keytype) {
488 ALLOC(ent->s2kparams);
489 if (ent->s2kparams == NULL)
491 ent->s2kparams->length = 4;
492 ent->s2kparams->data = malloc(ent->s2kparams->length);
493 if (ent->s2kparams->data == NULL) {
494 free(ent->s2kparams);
495 ent->s2kparams = NULL;
498 _krb5_put_int(ent->s2kparams->data,
499 _krb5_AES_string_to_default_iterator,
500 ent->s2kparams->length);
509 * Return 1 if the client have only older enctypes, this is for
510 * determining if the server should send ETYPE_INFO2 or not.
514 only_older_enctype_p(const KDC_REQ *req)
518 for(i = 0; i < req->req_body.etype.len; i++) {
519 switch (req->req_body.etype.val[i]) {
520 case ETYPE_DES_CBC_CRC:
521 case ETYPE_DES_CBC_MD4:
522 case ETYPE_DES_CBC_MD5:
523 case ETYPE_DES3_CBC_SHA1:
524 case ETYPE_ARCFOUR_HMAC_MD5:
525 case ETYPE_ARCFOUR_HMAC_MD5_56:
538 static krb5_error_code
539 get_pa_etype_info2(krb5_context context,
540 krb5_kdc_configuration *config,
541 METHOD_DATA *md, hdb_entry *client,
542 ENCTYPE *etypes, unsigned int etypes_len)
544 krb5_error_code ret = 0;
551 pa.len = client->keys.len;
552 if(pa.len > UINT_MAX/sizeof(*pa.val))
554 pa.val = malloc(pa.len * sizeof(*pa.val));
557 memset(pa.val, 0, pa.len * sizeof(*pa.val));
559 for(j = 0; j < etypes_len; j++) {
560 for (i = 0; i < n; i++)
561 if (pa.val[i].etype == etypes[j])
563 for(i = 0; i < client->keys.len; i++) {
564 if(client->keys.val[i].key.keytype == etypes[j]) {
565 if (krb5_enctype_valid(context, etypes[j]) != 0)
567 if((ret = make_etype_info2_entry(&pa.val[n++],
568 &client->keys.val[i])) != 0) {
569 free_ETYPE_INFO2(&pa);
576 for(i = 0; i < client->keys.len; i++) {
577 for(j = 0; j < etypes_len; j++) {
578 if(client->keys.val[i].key.keytype == etypes[j])
581 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
583 if((ret = make_etype_info2_entry(&pa.val[n++],
584 &client->keys.val[i])) != 0) {
585 free_ETYPE_INFO2(&pa);
593 ret = krb5_unparse_name(context, client->principal, &name);
595 name = "<unparse_name failed>";
596 kdc_log(context, config, 0,
597 "internal error in get_pa_etype_info2(%s): %d != %d",
604 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
605 free_ETYPE_INFO2(&pa);
608 ret = realloc_method_data(md);
613 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
614 md->val[md->len - 1].padata_value.length = len;
615 md->val[md->len - 1].padata_value.data = buf;
620 * verify the flags on `client' and `server', returning 0
621 * if they are OK and generating an error messages and returning
622 * and error code otherwise.
626 _kdc_check_flags(krb5_context context,
627 krb5_kdc_configuration *config,
628 hdb_entry *client, const char *client_name,
629 hdb_entry *server, const char *server_name,
630 krb5_boolean is_as_req)
634 if (client->flags.invalid) {
635 kdc_log(context, config, 0,
636 "Client (%s) has invalid bit set", client_name);
637 return KRB5KDC_ERR_POLICY;
640 if(!client->flags.client){
641 kdc_log(context, config, 0,
642 "Principal may not act as client -- %s", client_name);
643 return KRB5KDC_ERR_POLICY;
646 if (client->valid_start && *client->valid_start > kdc_time) {
647 kdc_log(context, config, 0,
648 "Client not yet valid -- %s", client_name);
649 return KRB5KDC_ERR_CLIENT_NOTYET;
652 if (client->valid_end && *client->valid_end < kdc_time) {
653 kdc_log(context, config, 0,
654 "Client expired -- %s", client_name);
655 return KRB5KDC_ERR_NAME_EXP;
658 if (client->pw_end && *client->pw_end < kdc_time
659 && !server->flags.change_pw) {
660 kdc_log(context, config, 0,
661 "Client's key has expired -- %s", client_name);
662 return KRB5KDC_ERR_KEY_EXPIRED;
668 if (server != NULL) {
669 if (server->flags.invalid) {
670 kdc_log(context, config, 0,
671 "Server has invalid flag set -- %s", server_name);
672 return KRB5KDC_ERR_POLICY;
675 if(!server->flags.server){
676 kdc_log(context, config, 0,
677 "Principal may not act as server -- %s", server_name);
678 return KRB5KDC_ERR_POLICY;
681 if(!is_as_req && server->flags.initial) {
682 kdc_log(context, config, 0,
683 "AS-REQ is required for server -- %s", server_name);
684 return KRB5KDC_ERR_POLICY;
687 if (server->valid_start && *server->valid_start > kdc_time) {
688 kdc_log(context, config, 0,
689 "Server not yet valid -- %s", server_name);
690 return KRB5KDC_ERR_SERVICE_NOTYET;
693 if (server->valid_end && *server->valid_end < kdc_time) {
694 kdc_log(context, config, 0,
695 "Server expired -- %s", server_name);
696 return KRB5KDC_ERR_SERVICE_EXP;
699 if (server->pw_end && *server->pw_end < kdc_time) {
700 kdc_log(context, config, 0,
701 "Server's key has expired -- %s", server_name);
702 return KRB5KDC_ERR_KEY_EXPIRED;
709 * Return TRUE if `from' is part of `addresses' taking into consideration
710 * the configuration variables that tells us how strict we should be about
715 check_addresses(krb5_context context,
716 krb5_kdc_configuration *config,
717 HostAddresses *addresses, const struct sockaddr *from)
723 if(config->check_ticket_addresses == 0)
726 if(addresses == NULL)
727 return config->allow_null_ticket_addresses;
729 ret = krb5_sockaddr2address (context, from, &addr);
733 result = krb5_address_search(context, &addr, addresses);
734 krb5_free_address (context, &addr);
739 _kdc_as_rep(krb5_context context,
740 krb5_kdc_configuration *config,
742 const krb5_data *req_buffer,
745 struct sockaddr *from_addr)
747 KDC_REQ_BODY *b = &req->req_body;
749 KDCOptions f = b->kdc_options;
750 hdb_entry *client = NULL, *server = NULL;
751 krb5_enctype cetype, setype;
754 krb5_principal client_princ = NULL, server_princ = NULL;
755 char *client_name = NULL, *server_name = NULL;
756 krb5_error_code ret = 0;
757 const char *e_text = NULL;
760 EncryptionKey *reply_key;
762 pk_client_params *pkp = NULL;
765 memset(&rep, 0, sizeof(rep));
767 if(b->sname == NULL){
768 ret = KRB5KRB_ERR_GENERIC;
769 e_text = "No server in request";
771 _krb5_principalname2krb5_principal (&server_princ,
772 *(b->sname), b->realm);
773 ret = krb5_unparse_name(context, server_princ, &server_name);
776 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
780 if(b->cname == NULL){
781 ret = KRB5KRB_ERR_GENERIC;
782 e_text = "No client in request";
784 _krb5_principalname2krb5_principal (&client_princ,
785 *(b->cname), b->realm);
786 ret = krb5_unparse_name(context, client_princ, &client_name);
789 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
793 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
794 client_name, from, server_name);
796 ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
798 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
799 krb5_get_err_text(context, ret));
800 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
804 ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
806 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
807 krb5_get_err_text(context, ret));
808 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
812 ret = _kdc_check_flags(context, config,
819 memset(&et, 0, sizeof(et));
820 memset(&ek, 0, sizeof(ek));
828 kdc_log(context, config, 5,
829 "Looking for PKINIT pa-data -- %s", client_name);
831 e_text = "No PKINIT PA found";
834 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
838 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
843 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
847 char *client_cert = NULL;
849 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
851 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
852 kdc_log(context, config, 5,
853 "Failed to decode PKINIT PA-DATA -- %s",
857 if (ret == 0 && pkp == NULL)
860 ret = _kdc_pk_check_client(context,
867 e_text = "PKINIT certificate not allowed to "
868 "impersonate principal";
869 _kdc_pk_free_client_param(context, pkp);
874 et.flags.pre_authent = 1;
875 kdc_log(context, config, 2,
876 "PKINIT pre-authentication succeeded -- %s using %s",
877 client_name, client_cert);
884 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
888 e_text = "No ENC-TS found";
889 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
893 EncryptedData enc_data;
899 ret = decode_EncryptedData(pa->padata_value.data,
900 pa->padata_value.length,
904 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
905 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
910 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
913 e_text = "No key matches pa-data";
914 ret = KRB5KDC_ERR_PREAUTH_FAILED;
915 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
918 kdc_log(context, config, 5,
919 "No client key matching pa-data (%d) -- %s",
920 enc_data.etype, client_name);
922 kdc_log(context, config, 5,
923 "No client key matching pa-data (%s) -- %s",
927 free_EncryptedData(&enc_data);
932 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
934 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
935 krb5_get_err_text(context, ret));
936 free_EncryptedData(&enc_data);
940 ret = krb5_decrypt_EncryptedData (context,
942 KRB5_KU_PA_ENC_TIMESTAMP,
945 krb5_crypto_destroy(context, crypto);
947 krb5_error_code ret2;
948 ret2 = krb5_enctype_to_string(context,
949 pa_key->key.keytype, &str);
952 kdc_log(context, config, 5,
953 "Failed to decrypt PA-DATA -- %s "
954 "(enctype %s) error %s",
956 str ? str : "unknown enctype",
957 krb5_get_err_text(context, ret));
960 if(hdb_next_enctype2key(context, client,
961 enc_data.etype, &pa_key) == 0)
963 e_text = "Failed to decrypt PA-DATA";
965 free_EncryptedData(&enc_data);
966 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
969 free_EncryptedData(&enc_data);
970 ret = decode_PA_ENC_TS_ENC(ts_data.data,
974 krb5_data_free(&ts_data);
976 e_text = "Failed to decode PA-ENC-TS-ENC";
977 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
978 kdc_log(context, config,
979 5, "Failed to decode PA-ENC-TS_ENC -- %s",
983 free_PA_ENC_TS_ENC(&p);
984 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
985 ret = KRB5KRB_AP_ERR_SKEW;
986 e_text = "Too large time skew";
987 kdc_log(context, config, 0,
988 "Too large time skew -- %s", client_name);
991 et.flags.pre_authent = 1;
993 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
997 kdc_log(context, config, 2,
998 "ENC-TS Pre-authentication succeeded -- %s using %s",
999 client_name, str ? str : "unknown enctype");
1006 if(found_pa == 0 && config->require_preauth)
1008 /* We come here if we found a pa-enc-timestamp, but if there
1009 was some problem with it, other than too large skew */
1010 if(found_pa && et.flags.pre_authent == 0){
1011 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1015 }else if (config->require_preauth
1016 || client->flags.require_preauth
1017 || server->flags.require_preauth) {
1018 METHOD_DATA method_data;
1025 method_data.len = 0;
1026 method_data.val = NULL;
1028 ret = realloc_method_data(&method_data);
1029 pa = &method_data.val[method_data.len-1];
1030 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
1031 pa->padata_value.length = 0;
1032 pa->padata_value.data = NULL;
1035 ret = realloc_method_data(&method_data);
1036 pa = &method_data.val[method_data.len-1];
1037 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
1038 pa->padata_value.length = 0;
1039 pa->padata_value.data = NULL;
1041 ret = realloc_method_data(&method_data);
1042 pa = &method_data.val[method_data.len-1];
1043 pa->padata_type = KRB5_PADATA_PK_AS_REQ_19;
1044 pa->padata_value.length = 0;
1045 pa->padata_value.data = NULL;
1049 if (only_older_enctype_p(req))
1050 ret = get_pa_etype_info(context, config, &method_data, client,
1051 b->etype.val, b->etype.len);
1053 ret = get_pa_etype_info2(context, config, &method_data, client,
1054 b->etype.val, b->etype.len);
1057 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1058 free_METHOD_DATA(&method_data);
1059 foo_data.data = buf;
1060 foo_data.length = len;
1062 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1063 krb5_mk_error(context,
1065 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1073 kdc_log(context, config, 0,
1074 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1080 ret = find_keys(context, config,
1081 client, server, &ckey, &cetype, &skey, &setype,
1082 b->etype.val, b->etype.len);
1084 kdc_log(context, config, 0, "Server/client has no support for etypes");
1089 struct rk_strpool *p = NULL;
1093 for (i = 0; i < b->etype.len; i++) {
1094 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1096 p = rk_strpoolprintf(p, "%s", str);
1099 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1100 if (p && i + 1 < b->etype.len)
1101 p = rk_strpoolprintf(p, ", ");
1103 kdc_log(context, config, 0, "out of meory");
1107 str = rk_strpoolcollect(p);
1108 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1115 ret = krb5_enctype_to_string(context, cetype, &cet);
1117 ret = krb5_enctype_to_string(context, setype, &set);
1119 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1125 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1130 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1133 kdc_log(context, config, 2, "Requested flags: %s", str);
1137 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1138 || (f.request_anonymous && !config->allow_anonymous)) {
1139 ret = KRB5KDC_ERR_BADOPTION;
1140 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1145 rep.msg_type = krb_as_rep;
1146 copy_Realm(&client->principal->realm, &rep.crealm);
1147 if (f.request_anonymous)
1148 make_anonymous_principalname (&rep.cname);
1150 _krb5_principal2principalname(&rep.cname,
1152 rep.ticket.tkt_vno = 5;
1153 copy_Realm(&server->principal->realm, &rep.ticket.realm);
1154 _krb5_principal2principalname(&rep.ticket.sname,
1157 et.flags.initial = 1;
1158 if(client->flags.forwardable && server->flags.forwardable)
1159 et.flags.forwardable = f.forwardable;
1160 else if (f.forwardable) {
1161 ret = KRB5KDC_ERR_POLICY;
1162 kdc_log(context, config, 0,
1163 "Ticket may not be forwardable -- %s", client_name);
1166 if(client->flags.proxiable && server->flags.proxiable)
1167 et.flags.proxiable = f.proxiable;
1168 else if (f.proxiable) {
1169 ret = KRB5KDC_ERR_POLICY;
1170 kdc_log(context, config, 0,
1171 "Ticket may not be proxiable -- %s", client_name);
1174 if(client->flags.postdate && server->flags.postdate)
1175 et.flags.may_postdate = f.allow_postdate;
1176 else if (f.allow_postdate){
1177 ret = KRB5KDC_ERR_POLICY;
1178 kdc_log(context, config, 0,
1179 "Ticket may not be postdatable -- %s", client_name);
1183 /* check for valid set of addresses */
1184 if(!check_addresses(context, config, b->addresses, from_addr)) {
1185 ret = KRB5KRB_AP_ERR_BADADDR;
1186 kdc_log(context, config, 0,
1187 "Bad address list requested -- %s", client_name);
1191 krb5_generate_random_keyblock(context, setype, &et.key);
1192 copy_PrincipalName(&rep.cname, &et.cname);
1193 copy_Realm(&rep.crealm, &et.crealm);
1199 start = et.authtime = kdc_time;
1201 if(f.postdated && req->req_body.from){
1202 ALLOC(et.starttime);
1203 start = *et.starttime = *req->req_body.from;
1204 et.flags.invalid = 1;
1205 et.flags.postdated = 1; /* XXX ??? */
1210 /* be careful not overflowing */
1212 if(client->max_life)
1213 t = start + min(t - start, *client->max_life);
1214 if(server->max_life)
1215 t = start + min(t - start, *server->max_life);
1217 t = min(t, start + realm->max_life);
1220 if(f.renewable_ok && et.endtime < *b->till){
1222 if(b->rtime == NULL){
1226 if(*b->rtime < *b->till)
1227 *b->rtime = *b->till;
1229 if(f.renewable && b->rtime){
1233 if(client->max_renew)
1234 t = start + min(t - start, *client->max_renew);
1235 if(server->max_renew)
1236 t = start + min(t - start, *server->max_renew);
1238 t = min(t, start + realm->max_renew);
1240 ALLOC(et.renew_till);
1242 et.flags.renewable = 1;
1246 if (f.request_anonymous)
1247 et.flags.anonymous = 1;
1251 copy_HostAddresses(b->addresses, et.caddr);
1254 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1255 krb5_data_zero(&et.transited.contents);
1257 copy_EncryptionKey(&et.key, &ek.key);
1259 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1260 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1261 * incapable of correctly decoding SEQUENCE OF's of zero length.
1263 * To fix this, always send at least one no-op last_req
1265 * If there's a pw_end or valid_end we will use that,
1266 * otherwise just a dummy lr.
1268 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1269 ek.last_req.len = 0;
1271 && (config->kdc_warn_pwexpire == 0
1272 || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) {
1273 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1274 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
1277 if (client->valid_end) {
1278 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1279 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
1282 if (ek.last_req.len == 0) {
1283 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1284 ek.last_req.val[ek.last_req.len].lr_value = 0;
1287 ek.nonce = b->nonce;
1288 if (client->valid_end || client->pw_end) {
1289 ALLOC(ek.key_expiration);
1290 if (client->valid_end) {
1292 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1294 *ek.key_expiration = *client->valid_end;
1296 *ek.key_expiration = *client->pw_end;
1298 ek.key_expiration = NULL;
1299 ek.flags = et.flags;
1300 ek.authtime = et.authtime;
1302 ALLOC(ek.starttime);
1303 *ek.starttime = *et.starttime;
1305 ek.endtime = et.endtime;
1306 if (et.renew_till) {
1307 ALLOC(ek.renew_till);
1308 *ek.renew_till = *et.renew_till;
1310 copy_Realm(&rep.ticket.realm, &ek.srealm);
1311 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1314 copy_HostAddresses(et.caddr, ek.caddr);
1318 rep.padata->len = 0;
1319 rep.padata->val = NULL;
1321 reply_key = &ckey->key;
1324 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1326 &reply_key, rep.padata);
1332 set_salt_padata (rep.padata, ckey->salt);
1334 if (rep.padata->len == 0) {
1339 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1340 et.endtime, et.renew_till);
1342 ret = encode_reply(context, config,
1343 &rep, &et, &ek, setype, server->kvno, &skey->key,
1344 client->kvno, reply_key, &e_text, reply);
1345 free_EncTicketPart(&et);
1346 free_EncKDCRepPart(&ek);
1350 krb5_mk_error(context,
1364 _kdc_pk_free_client_param(context, pkp);
1367 krb5_free_principal(context, client_princ);
1370 krb5_free_principal(context, server_princ);
1373 _kdc_free_ent(context, client);
1375 _kdc_free_ent(context, server);
1380 static krb5_error_code
1381 check_tgs_flags(krb5_context context,
1382 krb5_kdc_configuration *config,
1383 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1385 KDCOptions f = b->kdc_options;
1388 if(!tgt->flags.invalid || tgt->starttime == NULL){
1389 kdc_log(context, config, 0,
1390 "Bad request to validate ticket");
1391 return KRB5KDC_ERR_BADOPTION;
1393 if(*tgt->starttime > kdc_time){
1394 kdc_log(context, config, 0,
1395 "Early request to validate ticket");
1396 return KRB5KRB_AP_ERR_TKT_NYV;
1399 et->flags.invalid = 0;
1400 }else if(tgt->flags.invalid){
1401 kdc_log(context, config, 0,
1402 "Ticket-granting ticket has INVALID flag set");
1403 return KRB5KRB_AP_ERR_TKT_INVALID;
1407 if(!tgt->flags.forwardable){
1408 kdc_log(context, config, 0,
1409 "Bad request for forwardable ticket");
1410 return KRB5KDC_ERR_BADOPTION;
1412 et->flags.forwardable = 1;
1415 if(!tgt->flags.forwardable){
1416 kdc_log(context, config, 0,
1417 "Request to forward non-forwardable ticket");
1418 return KRB5KDC_ERR_BADOPTION;
1420 et->flags.forwarded = 1;
1421 et->caddr = b->addresses;
1423 if(tgt->flags.forwarded)
1424 et->flags.forwarded = 1;
1427 if(!tgt->flags.proxiable){
1428 kdc_log(context, config, 0,
1429 "Bad request for proxiable ticket");
1430 return KRB5KDC_ERR_BADOPTION;
1432 et->flags.proxiable = 1;
1435 if(!tgt->flags.proxiable){
1436 kdc_log(context, config, 0,
1437 "Request to proxy non-proxiable ticket");
1438 return KRB5KDC_ERR_BADOPTION;
1440 et->flags.proxy = 1;
1441 et->caddr = b->addresses;
1443 if(tgt->flags.proxy)
1444 et->flags.proxy = 1;
1446 if(f.allow_postdate){
1447 if(!tgt->flags.may_postdate){
1448 kdc_log(context, config, 0,
1449 "Bad request for post-datable ticket");
1450 return KRB5KDC_ERR_BADOPTION;
1452 et->flags.may_postdate = 1;
1455 if(!tgt->flags.may_postdate){
1456 kdc_log(context, config, 0,
1457 "Bad request for postdated ticket");
1458 return KRB5KDC_ERR_BADOPTION;
1461 *et->starttime = *b->from;
1462 et->flags.postdated = 1;
1463 et->flags.invalid = 1;
1464 }else if(b->from && *b->from > kdc_time + context->max_skew){
1465 kdc_log(context, config, 0, "Ticket cannot be postdated");
1466 return KRB5KDC_ERR_CANNOT_POSTDATE;
1470 if(!tgt->flags.renewable){
1471 kdc_log(context, config, 0,
1472 "Bad request for renewable ticket");
1473 return KRB5KDC_ERR_BADOPTION;
1475 et->flags.renewable = 1;
1476 ALLOC(et->renew_till);
1477 fix_time(&b->rtime);
1478 *et->renew_till = *b->rtime;
1482 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1483 kdc_log(context, config, 0,
1484 "Request to renew non-renewable ticket");
1485 return KRB5KDC_ERR_BADOPTION;
1487 old_life = tgt->endtime;
1489 old_life -= *tgt->starttime;
1491 old_life -= tgt->authtime;
1492 et->endtime = *et->starttime + old_life;
1493 if (et->renew_till != NULL)
1494 et->endtime = min(*et->renew_till, et->endtime);
1497 /* checks for excess flags */
1498 if(f.request_anonymous && !config->allow_anonymous){
1499 kdc_log(context, config, 0,
1500 "Request for anonymous ticket");
1501 return KRB5KDC_ERR_BADOPTION;
1506 static krb5_error_code
1507 fix_transited_encoding(krb5_context context,
1508 krb5_kdc_configuration *config,
1509 krb5_boolean check_policy,
1510 TransitedEncoding *tr,
1512 const char *client_realm,
1513 const char *server_realm,
1514 const char *tgt_realm)
1516 krb5_error_code ret = 0;
1517 char **realms, **tmp;
1521 switch (tr->tr_type) {
1522 case DOMAIN_X500_COMPRESS:
1526 * Allow empty content of type 0 because that is was Microsoft
1527 * generates in their TGT.
1529 if (tr->contents.length == 0)
1531 kdc_log(context, config, 0,
1532 "Transited type 0 with non empty content");
1533 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1535 kdc_log(context, config, 0,
1536 "Unknown transited type: %u", tr->tr_type);
1537 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1540 ret = krb5_domain_x500_decode(context,
1547 krb5_warn(context, ret,
1548 "Decoding transited encoding");
1551 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1552 /* not us, so add the previous realm to transited set */
1553 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1557 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1563 realms[num_realms] = strdup(tgt_realm);
1564 if(realms[num_realms] == NULL){
1570 if(num_realms == 0) {
1571 if(strcmp(client_realm, server_realm))
1572 kdc_log(context, config, 0,
1573 "cross-realm %s -> %s", client_realm, server_realm);
1577 for(i = 0; i < num_realms; i++)
1578 l += strlen(realms[i]) + 2;
1582 for(i = 0; i < num_realms; i++) {
1584 strlcat(rs, ", ", l);
1585 strlcat(rs, realms[i], l);
1587 kdc_log(context, config, 0,
1588 "cross-realm %s -> %s via [%s]",
1589 client_realm, server_realm, rs);
1594 ret = krb5_check_transited(context, client_realm,
1596 realms, num_realms, NULL);
1598 krb5_warn(context, ret, "cross-realm %s -> %s",
1599 client_realm, server_realm);
1602 et->flags.transited_policy_checked = 1;
1604 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1605 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1607 krb5_warn(context, ret, "Encoding transited encoding");
1609 for(i = 0; i < num_realms; i++)
1616 static krb5_error_code
1617 tgs_make_reply(krb5_context context,
1618 krb5_kdc_configuration *config,
1621 EncTicketPart *adtkt,
1622 AuthorizationData *auth_data,
1623 krb5_ticket *tgs_ticket,
1626 krb5_principal client_principal,
1628 EncryptionKey *tgtkey,
1629 krb5_enctype cetype,
1630 const char **e_text,
1636 KDCOptions f = b->kdc_options;
1637 krb5_error_code ret;
1640 EncryptionKey *ekey;
1646 for(i = 0; i < b->etype.len; i++){
1647 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1650 if(adtkt->key.keytype == kt)
1653 if(i == b->etype.len)
1654 return KRB5KDC_ERR_ETYPE_NOSUPP;
1655 etype = b->etype.val[i];
1657 ret = find_keys(context, config,
1658 NULL, server, NULL, NULL, &skey, &etype,
1659 b->etype.val, b->etype.len);
1661 kdc_log(context, config, 0, "Server has no support for etypes");
1667 memset(&rep, 0, sizeof(rep));
1668 memset(&et, 0, sizeof(et));
1669 memset(&ek, 0, sizeof(ek));
1672 rep.msg_type = krb_tgs_rep;
1674 et.authtime = tgt->authtime;
1676 et.endtime = min(tgt->endtime, *b->till);
1677 ALLOC(et.starttime);
1678 *et.starttime = kdc_time;
1680 ret = check_tgs_flags(context, config, b, tgt, &et);
1684 /* We should check the transited encoding if:
1685 1) the request doesn't ask not to be checked
1686 2) globally enforcing a check
1687 3) principal requires checking
1688 4) we allow non-check per-principal, but principal isn't marked as allowing this
1689 5) we don't globally allow this
1692 #define GLOBAL_FORCE_TRANSITED_CHECK \
1693 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1694 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1695 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1696 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1697 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1699 /* these will consult the database in future release */
1700 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1701 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1703 ret = fix_transited_encoding(context, config,
1704 !f.disable_transited_check ||
1705 GLOBAL_FORCE_TRANSITED_CHECK ||
1706 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1707 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1708 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1709 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1710 &tgt->transited, &et,
1711 *krb5_princ_realm(context, client_principal),
1712 *krb5_princ_realm(context, server->principal),
1713 *krb5_princ_realm(context, krbtgt->principal));
1717 copy_Realm(krb5_princ_realm(context, server->principal),
1719 _krb5_principal2principalname(&rep.ticket.sname, server->principal);
1720 copy_Realm(&tgt->crealm, &rep.crealm);
1721 if (f.request_anonymous)
1722 make_anonymous_principalname (&tgt->cname);
1724 copy_PrincipalName(&tgt->cname, &rep.cname);
1725 rep.ticket.tkt_vno = 5;
1727 ek.caddr = et.caddr;
1728 if(et.caddr == NULL)
1729 et.caddr = tgt->caddr;
1733 life = et.endtime - *et.starttime;
1734 if(client && client->max_life)
1735 life = min(life, *client->max_life);
1736 if(server->max_life)
1737 life = min(life, *server->max_life);
1738 et.endtime = *et.starttime + life;
1740 if(f.renewable_ok && tgt->flags.renewable &&
1741 et.renew_till == NULL && et.endtime < *b->till){
1742 et.flags.renewable = 1;
1743 ALLOC(et.renew_till);
1744 *et.renew_till = *b->till;
1748 renew = *et.renew_till - et.authtime;
1749 if(client && client->max_renew)
1750 renew = min(renew, *client->max_renew);
1751 if(server->max_renew)
1752 renew = min(renew, *server->max_renew);
1753 *et.renew_till = et.authtime + renew;
1757 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1758 *et.starttime = min(*et.starttime, *et.renew_till);
1759 et.endtime = min(et.endtime, *et.renew_till);
1762 *et.starttime = min(*et.starttime, et.endtime);
1764 if(*et.starttime == et.endtime){
1765 ret = KRB5KDC_ERR_NEVER_VALID;
1768 if(et.renew_till && et.endtime == *et.renew_till){
1769 free(et.renew_till);
1770 et.renew_till = NULL;
1771 et.flags.renewable = 0;
1774 et.flags.pre_authent = tgt->flags.pre_authent;
1775 et.flags.hw_authent = tgt->flags.hw_authent;
1776 et.flags.anonymous = tgt->flags.anonymous;
1777 et.flags.ok_as_delegate = server->flags.ok_as_delegate;
1779 #ifdef _SAMBA_BUILD_
1788 AD_IF_RELEVANT *if_relevant;
1790 if_relevant->len = 1;
1791 if_relevant->val = malloc(sizeof(*if_relevant->val));
1792 if_relevant->val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
1793 if_relevant->val[0].ad_data.data = NULL;
1794 if_relevant->val[0].ad_data.length = 0;
1796 /* Get PAC from Samba */
1797 ret = samba_get_pac(context, config,
1801 tgs_ticket->ticket.authtime,
1804 free_AuthorizationData(if_relevant);
1808 /* pac.data will be freed with this */
1809 if_relevant->val[0].ad_data.data = pac.data;
1810 if_relevant->val[0].ad_data.length = pac.length;
1812 ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1817 auth_data->val = malloc(sizeof(*auth_data->val));
1818 auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1819 auth_data->val[0].ad_data.length = len;
1820 auth_data->val[0].ad_data.data = buf;
1827 /* XXX Check enc-authorization-data */
1828 et.authorization_data = auth_data;
1830 krb5_generate_random_keyblock(context, etype, &et.key);
1831 et.crealm = tgt->crealm;
1832 et.cname = tgt->cname;
1835 /* MIT must have at least one last_req */
1836 ek.last_req.len = 1;
1837 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1838 ek.nonce = b->nonce;
1839 ek.flags = et.flags;
1840 ek.authtime = et.authtime;
1841 ek.starttime = et.starttime;
1842 ek.endtime = et.endtime;
1843 ek.renew_till = et.renew_till;
1844 ek.srealm = rep.ticket.realm;
1845 ek.sname = rep.ticket.sname;
1847 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1848 et.endtime, et.renew_till);
1850 /* It is somewhat unclear where the etype in the following
1851 encryption should come from. What we have is a session
1852 key in the passed tgt, and a list of preferred etypes
1853 *for the new ticket*. Should we pick the best possible
1854 etype, given the keytype in the tgt, or should we look
1855 at the etype list here as well? What if the tgt
1856 session key is DES3 and we want a ticket with a (say)
1857 CAST session key. Should the DES3 etype be added to the
1858 etype list, even if we don't want a session key with
1860 ret = encode_reply(context, config,
1861 &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1862 0, &tgt->key, e_text, reply);
1865 free_TransitedEncoding(&et.transited);
1869 free(et.renew_till);
1870 free_LastReq(&ek.last_req);
1871 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1872 free_EncryptionKey(&et.key);
1876 static krb5_error_code
1877 tgs_check_authenticator(krb5_context context,
1878 krb5_kdc_configuration *config,
1879 krb5_auth_context ac,
1881 const char **e_text,
1884 krb5_authenticator auth;
1888 krb5_error_code ret;
1891 krb5_auth_con_getauthenticator(context, ac, &auth);
1892 if(auth->cksum == NULL){
1893 kdc_log(context, config, 0, "No authenticator in request");
1894 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1898 * according to RFC1510 it doesn't need to be keyed,
1899 * but according to the latest draft it needs to.
1903 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1906 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1907 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1908 auth->cksum->cksumtype);
1909 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1913 /* XXX should not re-encode this */
1914 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1916 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
1917 krb5_get_err_text(context, ret));
1920 if(buf_size != len) {
1922 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1923 *e_text = "KDC internal error";
1924 ret = KRB5KRB_ERR_GENERIC;
1927 ret = krb5_crypto_init(context, key, 0, &crypto);
1930 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1931 krb5_get_err_text(context, ret));
1934 ret = krb5_verify_checksum(context,
1936 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1941 krb5_crypto_destroy(context, crypto);
1943 kdc_log(context, config, 0,
1944 "Failed to verify authenticator checksum: %s",
1945 krb5_get_err_text(context, ret));
1948 free_Authenticator(auth);
1954 * return the realm of a krbtgt-ticket or NULL
1958 get_krbtgt_realm(const PrincipalName *p)
1960 if(p->name_string.len == 2
1961 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1962 return p->name_string.val[1];
1968 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1970 const char *new_realm = krb5_config_get_string(context,
1981 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1983 if(server->name.name_type != KRB5_NT_SRV_INST ||
1984 server->name.name_string.len != 2)
1987 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1988 FALSE, realms) == 0;
1991 static krb5_error_code
1992 tgs_rep2(krb5_context context,
1993 krb5_kdc_configuration *config,
1998 const struct sockaddr *from_addr,
2003 krb5_error_code ret;
2004 krb5_principal princ;
2005 krb5_auth_context ac = NULL;
2006 krb5_ticket *ticket = NULL;
2007 krb5_flags ap_req_options;
2008 krb5_flags verify_ap_req_flags;
2009 const char *e_text = NULL;
2012 hdb_entry *krbtgt = NULL;
2015 krb5_enctype cetype;
2016 krb5_principal cp = NULL;
2017 krb5_principal sp = NULL;
2018 AuthorizationData *auth_data = NULL;
2023 memset(&ap_req, 0, sizeof(ap_req));
2024 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2026 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
2027 krb5_get_err_text(context, ret));
2031 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2032 /* XXX check for ticket.sname == req.sname */
2033 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2034 ret = KRB5KDC_ERR_POLICY; /* ? */
2038 _krb5_principalname2krb5_principal(&princ,
2039 ap_req.ticket.sname,
2040 ap_req.ticket.realm);
2042 ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
2046 ret = krb5_unparse_name(context, princ, &p);
2048 p = "<unparse_name failed>";
2049 krb5_free_principal(context, princ);
2050 kdc_log(context, config, 0,
2051 "Ticket-granting ticket not found in database: %s: %s",
2052 p, krb5_get_err_text(context, ret));
2055 ret = KRB5KRB_AP_ERR_NOT_US;
2059 if(ap_req.ticket.enc_part.kvno &&
2060 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
2063 ret = krb5_unparse_name (context, princ, &p);
2064 krb5_free_principal(context, princ);
2066 p = "<unparse_name failed>";
2067 kdc_log(context, config, 0,
2068 "Ticket kvno = %d, DB kvno = %d (%s)",
2069 *ap_req.ticket.enc_part.kvno,
2074 ret = KRB5KRB_AP_ERR_BADKEYVER;
2078 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2081 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2082 kdc_log(context, config, 0,
2083 "No server key found for %s", str);
2085 ret = KRB5KRB_AP_ERR_BADKEYVER;
2089 if (b->kdc_options.validate)
2090 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2092 verify_ap_req_flags = 0;
2094 ret = krb5_verify_ap_req2(context,
2099 verify_ap_req_flags,
2102 KRB5_KU_TGS_REQ_AUTH);
2104 krb5_free_principal(context, princ);
2106 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2107 krb5_get_err_text(context, ret));
2112 krb5_authenticator auth;
2114 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2116 *csec = malloc(sizeof(**csec));
2117 if (*csec == NULL) {
2118 krb5_free_authenticator(context, &auth);
2119 kdc_log(context, config, 0, "malloc failed");
2122 **csec = auth->ctime;
2123 *cusec = malloc(sizeof(**cusec));
2124 if (*cusec == NULL) {
2125 krb5_free_authenticator(context, &auth);
2126 kdc_log(context, config, 0, "malloc failed");
2129 **csec = auth->cusec;
2130 krb5_free_authenticator(context, &auth);
2134 cetype = ap_req.authenticator.etype;
2136 tgt = &ticket->ticket;
2138 ret = tgs_check_authenticator(context, config,
2139 ac, b, &e_text, &tgt->key);
2141 krb5_auth_con_free(context, ac);
2145 if (b->enc_authorization_data) {
2146 krb5_keyblock *subkey;
2148 ret = krb5_auth_con_getremotesubkey(context,
2152 krb5_auth_con_free(context, ac);
2153 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2154 krb5_get_err_text(context, ret));
2158 ret = krb5_auth_con_getkey(context, ac, &subkey);
2160 krb5_auth_con_free(context, ac);
2161 kdc_log(context, config, 0, "Failed to get session key: %s",
2162 krb5_get_err_text(context, ret));
2167 krb5_auth_con_free(context, ac);
2168 kdc_log(context, config, 0,
2169 "Failed to get key for enc-authorization-data");
2170 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2173 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2175 krb5_auth_con_free(context, ac);
2176 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2177 krb5_get_err_text(context, ret));
2180 ret = krb5_decrypt_EncryptedData (context,
2182 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2183 b->enc_authorization_data,
2185 krb5_crypto_destroy(context, crypto);
2187 krb5_auth_con_free(context, ac);
2188 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2189 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2192 krb5_free_keyblock(context, subkey);
2194 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2196 krb5_auth_con_free(context, ac);
2199 kdc_log(context, config, 0, "Failed to decode authorization data");
2200 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2205 krb5_auth_con_free(context, ac);
2210 char *spn = NULL, *cpn = NULL;
2211 hdb_entry *server = NULL, *client = NULL;
2213 EncTicketPart adtkt;
2218 if(b->kdc_options.enc_tkt_in_skey){
2224 if(b->additional_tickets == NULL ||
2225 b->additional_tickets->len == 0){
2226 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2227 kdc_log(context, config, 0,
2228 "No second ticket present in request");
2231 t = &b->additional_tickets->val[0];
2232 if(!get_krbtgt_realm(&t->sname)){
2233 kdc_log(context, config, 0,
2234 "Additional ticket is not a ticket-granting ticket");
2235 ret = KRB5KDC_ERR_POLICY;
2238 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2239 ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2240 krb5_free_principal(context, p);
2242 if (ret == HDB_ERR_NOENTRY)
2243 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2246 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2248 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2251 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2259 _krb5_principalname2krb5_principal(&sp, *s, r);
2260 ret = krb5_unparse_name(context, sp, &spn);
2263 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2264 ret = krb5_unparse_name(context, cp, &cpn);
2267 unparse_flags (KDCOptions2int(b->kdc_options),
2268 asn1_KDCOptions_units(),
2269 opt_str, sizeof(opt_str));
2271 kdc_log(context, config, 0,
2272 "TGS-REQ %s from %s for %s [%s]",
2273 cpn, from, spn, opt_str);
2275 kdc_log(context, config, 0,
2276 "TGS-REQ %s from %s for %s", cpn, from, spn);
2278 ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2281 const char *new_rlm;
2285 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2287 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2289 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2291 krb5_free_principal(context, sp);
2293 krb5_make_principal(context, &sp, r,
2294 KRB5_TGS_NAME, new_rlm, NULL);
2295 ret = krb5_unparse_name(context, sp, &spn);
2301 } else if(need_referral(context, sp, &realms)) {
2302 if (strcmp(realms[0], sp->realm) != 0) {
2303 kdc_log(context, config, 5,
2304 "Returning a referral to realm %s for "
2305 "server %s that was not found",
2307 krb5_free_principal(context, sp);
2309 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2311 ret = krb5_unparse_name(context, sp, &spn);
2314 krb5_free_host_realm(context, realms);
2317 krb5_free_host_realm(context, realms);
2319 kdc_log(context, config, 0,
2320 "Server not found in database: %s: %s", spn,
2321 krb5_get_err_text(context, ret));
2322 if (ret == HDB_ERR_NOENTRY)
2323 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2327 ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2329 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2330 cpn, krb5_get_err_text(context, ret));
2332 /* XXX check client only if same realm as krbtgt-instance */
2334 kdc_log(context, config, 0,
2335 "Client not found in database: %s: %s",
2336 cpn, krb5_get_err_text(context, ret));
2337 if (ret == HDB_ERR_NOENTRY)
2338 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2343 if(strcmp(krb5_principal_get_realm(context, sp),
2344 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2346 ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2347 kdc_log(context, config, 0,
2348 "Request with wrong krbtgt: %s",
2349 (ret == 0) ? tpn : "<unknown>");
2352 ret = KRB5KRB_AP_ERR_NOT_US;
2357 ret = _kdc_check_flags(context, config,
2364 if((b->kdc_options.validate || b->kdc_options.renew) &&
2365 !krb5_principal_compare(context,
2367 server->principal)){
2368 kdc_log(context, config, 0, "Inconsistent request.");
2369 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2373 /* check for valid set of addresses */
2374 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2375 ret = KRB5KRB_AP_ERR_BADADDR;
2376 kdc_log(context, config, 0, "Request from wrong address");
2380 ret = tgs_make_reply(context, config,
2383 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2400 _kdc_free_ent(context, server);
2402 _kdc_free_ent(context, client);
2406 krb5_mk_error(context,
2420 krb5_free_principal(context, cp);
2421 krb5_free_principal(context, sp);
2423 krb5_free_ticket(context, ticket);
2424 free_AP_REQ(&ap_req);
2426 free_AuthorizationData(auth_data);
2431 _kdc_free_ent(context, krbtgt);
2438 _kdc_tgs_rep(krb5_context context,
2439 krb5_kdc_configuration *config,
2443 struct sockaddr *from_addr)
2445 krb5_error_code ret;
2447 PA_DATA *tgs_req = NULL;
2448 time_t *csec = NULL;
2451 if(req->padata == NULL){
2452 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2453 kdc_log(context, config, 0,
2454 "TGS-REQ from %s without PA-DATA", from);
2458 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2460 if(tgs_req == NULL){
2461 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2463 kdc_log(context, config, 0,
2464 "TGS-REQ from %s without PA-TGS-REQ", from);
2467 ret = tgs_rep2(context, config,
2468 &req->req_body, tgs_req, data, from, from_addr,
2471 if(ret && data->data == NULL){
2472 krb5_mk_error(context,