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 atime[100], stime[100], etime[100], rtime[100];
194 krb5_format_time(context, authtime, atime, sizeof(atime), TRUE);
196 krb5_format_time(context, *starttime, stime, sizeof(stime), TRUE);
198 strlcpy(stime, "unset", sizeof(stime));
199 krb5_format_time(context, endtime, etime, sizeof(etime), TRUE);
201 krb5_format_time(context, *renew_till, rtime, sizeof(rtime), TRUE);
203 strlcpy(rtime, "unset", sizeof(rtime));
205 kdc_log(context, config, 5,
206 "%s authtime: %s starttime: %s endtype: %s renew till: %s",
207 type, atime, stime, etime, rtime);
210 static krb5_error_code
211 encode_reply(krb5_context context,
212 krb5_kdc_configuration *config,
213 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
215 int skvno, EncryptionKey *skey,
216 int ckvno, EncryptionKey *ckey,
226 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
228 kdc_log(context, config, 0, "Failed to encode ticket: %s",
229 krb5_get_err_text(context, ret));
232 if(buf_size != len) {
234 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
235 *e_text = "KDC internal error";
236 return KRB5KRB_ERR_GENERIC;
239 ret = krb5_crypto_init(context, skey, etype, &crypto);
242 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
243 krb5_get_err_text(context, ret));
247 ret = krb5_encrypt_EncryptedData(context,
253 &rep->ticket.enc_part);
255 krb5_crypto_destroy(context, crypto);
257 kdc_log(context, config, 0, "Failed to encrypt data: %s",
258 krb5_get_err_text(context, ret));
262 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
263 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
265 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
267 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
268 krb5_get_err_text(context, ret));
271 if(buf_size != len) {
273 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
274 *e_text = "KDC internal error";
275 return KRB5KRB_ERR_GENERIC;
277 ret = krb5_crypto_init(context, ckey, 0, &crypto);
280 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
281 krb5_get_err_text(context, ret));
284 if(rep->msg_type == krb_as_rep) {
285 krb5_encrypt_EncryptedData(context,
287 KRB5_KU_AS_REP_ENC_PART,
293 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
295 krb5_encrypt_EncryptedData(context,
297 KRB5_KU_TGS_REP_ENC_PART_SESSION,
303 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
305 krb5_crypto_destroy(context, crypto);
307 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
308 krb5_get_err_text(context, ret));
311 if(buf_size != len) {
313 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
314 *e_text = "KDC internal error";
315 return KRB5KRB_ERR_GENERIC;
318 reply->length = buf_size;
322 static krb5_error_code
323 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
325 ent->etype = key->key.keytype;
327 ALLOC(ent->salttype);
329 if(key->salt->type == hdb_pw_salt)
330 *ent->salttype = 0; /* or 1? or NULL? */
331 else if(key->salt->type == hdb_afs3_salt)
334 kdc_log(context, config, 0, "unknown salt-type: %d",
336 return KRB5KRB_ERR_GENERIC;
338 /* according to `the specs', we can't send a salt if
339 we have AFS3 salted key, but that requires that you
340 *know* what cell you are using (e.g by assuming
341 that the cell is the same as the realm in lower
344 *ent->salttype = key->salt->type;
346 krb5_copy_data(context, &key->salt->salt,
349 /* we return no salt type at all, as that should indicate
350 * the default salt type and make everybody happy. some
351 * systems (like w2k) dislike being told the salt type
354 ent->salttype = NULL;
360 static krb5_error_code
361 get_pa_etype_info(krb5_context context,
362 krb5_kdc_configuration *config,
363 METHOD_DATA *md, hdb_entry *client,
364 ENCTYPE *etypes, unsigned int etypes_len)
366 krb5_error_code ret = 0;
374 pa.len = client->keys.len;
375 if(pa.len > UINT_MAX/sizeof(*pa.val))
377 pa.val = malloc(pa.len * sizeof(*pa.val));
380 memset(pa.val, 0, pa.len * sizeof(*pa.val));
382 for(j = 0; j < etypes_len; j++) {
383 for (i = 0; i < n; i++)
384 if (pa.val[i].etype == etypes[j])
386 for(i = 0; i < client->keys.len; i++) {
387 if(client->keys.val[i].key.keytype == etypes[j]) {
388 if (krb5_enctype_valid(context, etypes[j]) != 0)
390 if((ret = make_etype_info_entry(context,
392 &client->keys.val[i])) != 0) {
393 free_ETYPE_INFO(&pa);
400 for(i = 0; i < client->keys.len; i++) {
401 for(j = 0; j < etypes_len; j++) {
402 if(client->keys.val[i].key.keytype == etypes[j])
405 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
407 if((ret = make_etype_info_entry(context,
409 &client->keys.val[i])) != 0) {
410 free_ETYPE_INFO(&pa);
418 ret = krb5_unparse_name(context, client->principal, &name);
420 name = "<unparse_name failed>";
421 kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
428 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
429 free_ETYPE_INFO(&pa);
432 ret = realloc_method_data(md);
437 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
438 md->val[md->len - 1].padata_value.length = len;
439 md->val[md->len - 1].padata_value.data = buf;
447 extern int _krb5_AES_string_to_default_iterator;
449 static krb5_error_code
450 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
452 ent->etype = key->key.keytype;
455 if (ent->salt == NULL)
457 *ent->salt = malloc(key->salt->salt.length + 1);
458 if (*ent->salt == NULL) {
463 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
464 (*ent->salt)[key->salt->salt.length] = '\0';
468 ent->s2kparams = NULL;
470 switch (key->key.keytype) {
473 ALLOC(ent->s2kparams);
474 if (ent->s2kparams == NULL)
476 ent->s2kparams->length = 4;
477 ent->s2kparams->data = malloc(ent->s2kparams->length);
478 if (ent->s2kparams->data == NULL) {
479 free(ent->s2kparams);
480 ent->s2kparams = NULL;
483 _krb5_put_int(ent->s2kparams->data,
484 _krb5_AES_string_to_default_iterator,
485 ent->s2kparams->length);
494 * Return 1 if the client have only older enctypes, this is for
495 * determining if the server should send ETYPE_INFO2 or not.
499 only_older_enctype_p(const KDC_REQ *req)
503 for(i = 0; i < req->req_body.etype.len; i++) {
504 switch (req->req_body.etype.val[i]) {
505 case ETYPE_DES_CBC_CRC:
506 case ETYPE_DES_CBC_MD4:
507 case ETYPE_DES_CBC_MD5:
508 case ETYPE_DES3_CBC_SHA1:
509 case ETYPE_ARCFOUR_HMAC_MD5:
510 case ETYPE_ARCFOUR_HMAC_MD5_56:
523 static krb5_error_code
524 get_pa_etype_info2(krb5_context context,
525 krb5_kdc_configuration *config,
526 METHOD_DATA *md, hdb_entry *client,
527 ENCTYPE *etypes, unsigned int etypes_len)
529 krb5_error_code ret = 0;
536 pa.len = client->keys.len;
537 if(pa.len > UINT_MAX/sizeof(*pa.val))
539 pa.val = malloc(pa.len * sizeof(*pa.val));
542 memset(pa.val, 0, pa.len * sizeof(*pa.val));
544 for(j = 0; j < etypes_len; j++) {
545 for (i = 0; i < n; i++)
546 if (pa.val[i].etype == etypes[j])
548 for(i = 0; i < client->keys.len; i++) {
549 if(client->keys.val[i].key.keytype == etypes[j]) {
550 if (krb5_enctype_valid(context, etypes[j]) != 0)
552 if((ret = make_etype_info2_entry(&pa.val[n++],
553 &client->keys.val[i])) != 0) {
554 free_ETYPE_INFO2(&pa);
561 for(i = 0; i < client->keys.len; i++) {
562 for(j = 0; j < etypes_len; j++) {
563 if(client->keys.val[i].key.keytype == etypes[j])
566 if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
568 if((ret = make_etype_info2_entry(&pa.val[n++],
569 &client->keys.val[i])) != 0) {
570 free_ETYPE_INFO2(&pa);
578 ret = krb5_unparse_name(context, client->principal, &name);
580 name = "<unparse_name failed>";
581 kdc_log(context, config, 0, "internal error in get_pa_etype_info2(%s): %d != %d",
588 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
589 free_ETYPE_INFO2(&pa);
592 ret = realloc_method_data(md);
597 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
598 md->val[md->len - 1].padata_value.length = len;
599 md->val[md->len - 1].padata_value.data = buf;
604 * verify the flags on `client' and `server', returning 0
605 * if they are OK and generating an error messages and returning
606 * and error code otherwise.
610 _kdc_check_flags(krb5_context context,
611 krb5_kdc_configuration *config,
612 hdb_entry *client, const char *client_name,
613 hdb_entry *server, const char *server_name,
614 krb5_boolean is_as_req)
618 if (client->flags.invalid) {
619 kdc_log(context, config, 0,
620 "Client (%s) has invalid bit set", client_name);
621 return KRB5KDC_ERR_POLICY;
624 if(!client->flags.client){
625 kdc_log(context, config, 0,
626 "Principal may not act as client -- %s",
628 return KRB5KDC_ERR_POLICY;
631 if (client->valid_start && *client->valid_start > kdc_time) {
632 kdc_log(context, config, 0, "Client not yet valid -- %s", client_name);
633 return KRB5KDC_ERR_CLIENT_NOTYET;
636 if (client->valid_end && *client->valid_end < kdc_time) {
637 kdc_log(context, config, 0, "Client expired -- %s", client_name);
638 return KRB5KDC_ERR_NAME_EXP;
641 if (client->pw_end && *client->pw_end < kdc_time
642 && !server->flags.change_pw) {
643 kdc_log(context, config, 0, "Client's key has expired -- %s", client_name);
644 return KRB5KDC_ERR_KEY_EXPIRED;
650 if (server != NULL) {
651 if (server->flags.invalid) {
652 kdc_log(context, config, 0, "Server has invalid flag set -- %s", server_name);
653 return KRB5KDC_ERR_POLICY;
656 if(!server->flags.server){
657 kdc_log(context, config, 0, "Principal may not act as server -- %s",
659 return KRB5KDC_ERR_POLICY;
662 if(!is_as_req && server->flags.initial) {
663 kdc_log(context, config, 0, "AS-REQ is required for server -- %s", server_name);
664 return KRB5KDC_ERR_POLICY;
667 if (server->valid_start && *server->valid_start > kdc_time) {
668 kdc_log(context, config, 0, "Server not yet valid -- %s", server_name);
669 return KRB5KDC_ERR_SERVICE_NOTYET;
672 if (server->valid_end && *server->valid_end < kdc_time) {
673 kdc_log(context, config, 0, "Server expired -- %s", server_name);
674 return KRB5KDC_ERR_SERVICE_EXP;
677 if (server->pw_end && *server->pw_end < kdc_time) {
678 kdc_log(context, config, 0, "Server's key has expired -- %s", server_name);
679 return KRB5KDC_ERR_KEY_EXPIRED;
686 * Return TRUE if `from' is part of `addresses' taking into consideration
687 * the configuration variables that tells us how strict we should be about
692 check_addresses(krb5_context context,
693 krb5_kdc_configuration *config,
694 HostAddresses *addresses, const struct sockaddr *from)
700 if(config->check_ticket_addresses == 0)
703 if(addresses == NULL)
704 return config->allow_null_ticket_addresses;
706 ret = krb5_sockaddr2address (context, from, &addr);
710 result = krb5_address_search(context, &addr, addresses);
711 krb5_free_address (context, &addr);
716 _kdc_as_rep(krb5_context context,
717 krb5_kdc_configuration *config,
721 struct sockaddr *from_addr)
723 KDC_REQ_BODY *b = &req->req_body;
725 KDCOptions f = b->kdc_options;
726 hdb_entry *client = NULL, *server = NULL;
727 krb5_enctype cetype, setype;
730 krb5_principal client_princ = NULL, server_princ = NULL;
731 char *client_name = NULL, *server_name = NULL;
732 krb5_error_code ret = 0;
733 const char *e_text = NULL;
736 EncryptionKey *reply_key;
738 pk_client_params *pkp = NULL;
741 memset(&rep, 0, sizeof(rep));
743 if(b->sname == NULL){
744 ret = KRB5KRB_ERR_GENERIC;
745 e_text = "No server in request";
747 _krb5_principalname2krb5_principal (&server_princ,
748 *(b->sname), b->realm);
749 ret = krb5_unparse_name(context, server_princ, &server_name);
752 kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
756 if(b->cname == NULL){
757 ret = KRB5KRB_ERR_GENERIC;
758 e_text = "No client in request";
760 _krb5_principalname2krb5_principal (&client_princ,
761 *(b->cname), b->realm);
762 ret = krb5_unparse_name(context, client_princ, &client_name);
765 kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
769 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
770 client_name, from, server_name);
772 ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
774 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
775 krb5_get_err_text(context, ret));
776 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
780 ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
782 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
783 krb5_get_err_text(context, ret));
784 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
788 ret = _kdc_check_flags(context, config,
795 memset(&et, 0, sizeof(et));
796 memset(&ek, 0, sizeof(ek));
804 kdc_log(context, config, 5,
805 "Looking for PKINIT pa-data -- %s", client_name);
807 e_text = "No PKINIT PA found";
810 if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
814 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
819 if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
823 char *client_cert = NULL;
825 ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
827 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
828 kdc_log(context, config, 5,
829 "Failed to decode PKINIT PA-DATA -- %s",
833 if (ret == 0 && pkp == NULL)
836 ret = _kdc_pk_check_client(context,
843 e_text = "PKINIT certificate not allowed to "
844 "impersonate principal";
845 _kdc_pk_free_client_param(context, pkp);
850 et.flags.pre_authent = 1;
851 kdc_log(context, config, 2,
852 "PKINIT pre-authentication succeeded -- %s using %s",
853 client_name, client_cert);
860 kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
864 e_text = "No ENC-TS found";
865 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
869 EncryptedData enc_data;
874 ret = decode_EncryptedData(pa->padata_value.data,
875 pa->padata_value.length,
879 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
880 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
885 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
888 e_text = "No key matches pa-data";
889 ret = KRB5KDC_ERR_PREAUTH_FAILED;
890 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
893 kdc_log(context, config, 5,
894 "No client key matching pa-data (%d) -- %s",
895 enc_data.etype, client_name);
897 kdc_log(context, config, 5,
898 "No client key matching pa-data (%s) -- %s",
902 free_EncryptedData(&enc_data);
907 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
909 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
910 krb5_get_err_text(context, ret));
911 free_EncryptedData(&enc_data);
915 ret = krb5_decrypt_EncryptedData (context,
917 KRB5_KU_PA_ENC_TIMESTAMP,
920 krb5_crypto_destroy(context, crypto);
922 if(hdb_next_enctype2key(context, client,
923 enc_data.etype, &pa_key) == 0)
925 free_EncryptedData(&enc_data);
926 e_text = "Failed to decrypt PA-DATA";
927 kdc_log(context, config,
928 5, "Failed to decrypt PA-DATA -- %s",
930 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
933 free_EncryptedData(&enc_data);
934 ret = decode_PA_ENC_TS_ENC(ts_data.data,
938 krb5_data_free(&ts_data);
940 e_text = "Failed to decode PA-ENC-TS-ENC";
941 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
942 kdc_log(context, config,
943 5, "Failed to decode PA-ENC-TS_ENC -- %s",
947 free_PA_ENC_TS_ENC(&p);
948 if (abs(kdc_time - p.patimestamp) > context->max_skew) {
949 ret = KRB5KDC_ERR_PREAUTH_FAILED;
950 e_text = "Too large time skew";
951 kdc_log(context, config, 0,
952 "Too large time skew -- %s", client_name);
955 et.flags.pre_authent = 1;
956 kdc_log(context, config, 2,
957 "ENC-TS Pre-authentication succeeded -- %s",
964 if(found_pa == 0 && config->require_preauth)
966 /* We come here if we found a pa-enc-timestamp, but if there
967 was some problem with it, other than too large skew */
968 if(found_pa && et.flags.pre_authent == 0){
969 kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
973 }else if (config->require_preauth
974 || client->flags.require_preauth
975 || server->flags.require_preauth) {
976 METHOD_DATA method_data;
984 method_data.val = NULL;
986 ret = realloc_method_data(&method_data);
987 pa = &method_data.val[method_data.len-1];
988 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
989 pa->padata_value.length = 0;
990 pa->padata_value.data = NULL;
993 ret = realloc_method_data(&method_data);
994 pa = &method_data.val[method_data.len-1];
995 pa->padata_type = KRB5_PADATA_PK_AS_REQ;
996 pa->padata_value.length = 0;
997 pa->padata_value.data = NULL;
999 ret = realloc_method_data(&method_data);
1000 pa = &method_data.val[method_data.len-1];
1001 pa->padata_type = KRB5_PADATA_PK_AS_REQ_19;
1002 pa->padata_value.length = 0;
1003 pa->padata_value.data = NULL;
1007 if (only_older_enctype_p(req))
1008 ret = get_pa_etype_info(context, config, &method_data, client,
1009 b->etype.val, b->etype.len);
1011 ret = get_pa_etype_info2(context, config, &method_data, client,
1012 b->etype.val, b->etype.len);
1015 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1016 free_METHOD_DATA(&method_data);
1017 foo_data.data = buf;
1018 foo_data.length = len;
1020 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1021 krb5_mk_error(context,
1023 "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1031 kdc_log(context, config, 0,
1032 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1038 ret = find_keys(context, config,
1039 client, server, &ckey, &cetype, &skey, &setype,
1040 b->etype.val, b->etype.len);
1042 kdc_log(context, config, 0, "Server/client has no support for etypes");
1047 struct rk_strpool *p = NULL;
1051 for (i = 0; i < b->etype.len; i++) {
1052 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1054 p = rk_strpoolprintf(p, "%s", str);
1057 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1058 if (p && i + 1 < b->etype.len)
1059 p = rk_strpoolprintf(p, ", ");
1061 kdc_log(context, config, 0, "out of meory");
1065 str = rk_strpoolcollect(p);
1066 kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1073 ret = krb5_enctype_to_string(context, cetype, &cet);
1075 ret = krb5_enctype_to_string(context, setype, &set);
1077 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1083 kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1088 unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1091 kdc_log(context, config, 2, "Requested flags: %s", str);
1095 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1096 || (f.request_anonymous && !config->allow_anonymous)) {
1097 ret = KRB5KDC_ERR_BADOPTION;
1098 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1103 rep.msg_type = krb_as_rep;
1104 copy_Realm(&client->principal->realm, &rep.crealm);
1105 if (f.request_anonymous)
1106 make_anonymous_principalname (&rep.cname);
1108 _krb5_principal2principalname(&rep.cname,
1110 rep.ticket.tkt_vno = 5;
1111 copy_Realm(&server->principal->realm, &rep.ticket.realm);
1112 _krb5_principal2principalname(&rep.ticket.sname,
1115 et.flags.initial = 1;
1116 if(client->flags.forwardable && server->flags.forwardable)
1117 et.flags.forwardable = f.forwardable;
1118 else if (f.forwardable) {
1119 ret = KRB5KDC_ERR_POLICY;
1120 kdc_log(context, config, 0,
1121 "Ticket may not be forwardable -- %s", client_name);
1124 if(client->flags.proxiable && server->flags.proxiable)
1125 et.flags.proxiable = f.proxiable;
1126 else if (f.proxiable) {
1127 ret = KRB5KDC_ERR_POLICY;
1128 kdc_log(context, config, 0,
1129 "Ticket may not be proxiable -- %s", client_name);
1132 if(client->flags.postdate && server->flags.postdate)
1133 et.flags.may_postdate = f.allow_postdate;
1134 else if (f.allow_postdate){
1135 ret = KRB5KDC_ERR_POLICY;
1136 kdc_log(context, config, 0,
1137 "Ticket may not be postdatable -- %s", client_name);
1141 /* check for valid set of addresses */
1142 if(!check_addresses(context, config, b->addresses, from_addr)) {
1143 ret = KRB5KRB_AP_ERR_BADADDR;
1144 kdc_log(context, config, 0,
1145 "Bad address list requested -- %s", client_name);
1149 krb5_generate_random_keyblock(context, setype, &et.key);
1150 copy_PrincipalName(&rep.cname, &et.cname);
1151 copy_Realm(&rep.crealm, &et.crealm);
1157 start = et.authtime = kdc_time;
1159 if(f.postdated && req->req_body.from){
1160 ALLOC(et.starttime);
1161 start = *et.starttime = *req->req_body.from;
1162 et.flags.invalid = 1;
1163 et.flags.postdated = 1; /* XXX ??? */
1168 /* be careful not overflowing */
1170 if(client->max_life)
1171 t = start + min(t - start, *client->max_life);
1172 if(server->max_life)
1173 t = start + min(t - start, *server->max_life);
1175 t = min(t, start + realm->max_life);
1178 if(f.renewable_ok && et.endtime < *b->till){
1180 if(b->rtime == NULL){
1184 if(*b->rtime < *b->till)
1185 *b->rtime = *b->till;
1187 if(f.renewable && b->rtime){
1191 if(client->max_renew)
1192 t = start + min(t - start, *client->max_renew);
1193 if(server->max_renew)
1194 t = start + min(t - start, *server->max_renew);
1196 t = min(t, start + realm->max_renew);
1198 ALLOC(et.renew_till);
1200 et.flags.renewable = 1;
1204 if (f.request_anonymous)
1205 et.flags.anonymous = 1;
1209 copy_HostAddresses(b->addresses, et.caddr);
1212 et.transited.tr_type = DOMAIN_X500_COMPRESS;
1213 krb5_data_zero(&et.transited.contents);
1215 copy_EncryptionKey(&et.key, &ek.key);
1217 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1218 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1219 * incapable of correctly decoding SEQUENCE OF's of zero length.
1221 * To fix this, always send at least one no-op last_req
1223 * If there's a pw_end or valid_end we will use that,
1224 * otherwise just a dummy lr.
1226 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1227 ek.last_req.len = 0;
1229 && (config->kdc_warn_pwexpire == 0
1230 || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) {
1231 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
1232 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
1235 if (client->valid_end) {
1236 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
1237 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
1240 if (ek.last_req.len == 0) {
1241 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
1242 ek.last_req.val[ek.last_req.len].lr_value = 0;
1245 ek.nonce = b->nonce;
1246 if (client->valid_end || client->pw_end) {
1247 ALLOC(ek.key_expiration);
1248 if (client->valid_end) {
1250 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1252 *ek.key_expiration = *client->valid_end;
1254 *ek.key_expiration = *client->pw_end;
1256 ek.key_expiration = NULL;
1257 ek.flags = et.flags;
1258 ek.authtime = et.authtime;
1260 ALLOC(ek.starttime);
1261 *ek.starttime = *et.starttime;
1263 ek.endtime = et.endtime;
1264 if (et.renew_till) {
1265 ALLOC(ek.renew_till);
1266 *ek.renew_till = *et.renew_till;
1268 copy_Realm(&rep.ticket.realm, &ek.srealm);
1269 copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1272 copy_HostAddresses(et.caddr, ek.caddr);
1276 rep.padata->len = 0;
1277 rep.padata->val = NULL;
1279 reply_key = &ckey->key;
1282 ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, req,
1283 &reply_key, rep.padata);
1289 set_salt_padata (rep.padata, ckey->salt);
1291 if (rep.padata->len == 0) {
1296 log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1297 et.endtime, et.renew_till);
1299 ret = encode_reply(context, config,
1300 &rep, &et, &ek, setype, server->kvno, &skey->key,
1301 client->kvno, reply_key, &e_text, reply);
1302 free_EncTicketPart(&et);
1303 free_EncKDCRepPart(&ek);
1307 krb5_mk_error(context,
1321 _kdc_pk_free_client_param(context, pkp);
1324 krb5_free_principal(context, client_princ);
1327 krb5_free_principal(context, server_princ);
1330 _kdc_free_ent(context, client);
1332 _kdc_free_ent(context, server);
1337 static krb5_error_code
1338 check_tgs_flags(krb5_context context,
1339 krb5_kdc_configuration *config,
1340 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1342 KDCOptions f = b->kdc_options;
1345 if(!tgt->flags.invalid || tgt->starttime == NULL){
1346 kdc_log(context, config, 0, "Bad request to validate ticket");
1347 return KRB5KDC_ERR_BADOPTION;
1349 if(*tgt->starttime > kdc_time){
1350 kdc_log(context, config, 0, "Early request to validate ticket");
1351 return KRB5KRB_AP_ERR_TKT_NYV;
1354 et->flags.invalid = 0;
1355 }else if(tgt->flags.invalid){
1356 kdc_log(context, config, 0, "Ticket-granting ticket has INVALID flag set");
1357 return KRB5KRB_AP_ERR_TKT_INVALID;
1361 if(!tgt->flags.forwardable){
1362 kdc_log(context, config, 0, "Bad request for forwardable ticket");
1363 return KRB5KDC_ERR_BADOPTION;
1365 et->flags.forwardable = 1;
1368 if(!tgt->flags.forwardable){
1369 kdc_log(context, config, 0, "Request to forward non-forwardable ticket");
1370 return KRB5KDC_ERR_BADOPTION;
1372 et->flags.forwarded = 1;
1373 et->caddr = b->addresses;
1375 if(tgt->flags.forwarded)
1376 et->flags.forwarded = 1;
1379 if(!tgt->flags.proxiable){
1380 kdc_log(context, config, 0,
1381 "Bad request for proxiable ticket");
1382 return KRB5KDC_ERR_BADOPTION;
1384 et->flags.proxiable = 1;
1387 if(!tgt->flags.proxiable){
1388 kdc_log(context, config, 0,
1389 "Request to proxy non-proxiable ticket");
1390 return KRB5KDC_ERR_BADOPTION;
1392 et->flags.proxy = 1;
1393 et->caddr = b->addresses;
1395 if(tgt->flags.proxy)
1396 et->flags.proxy = 1;
1398 if(f.allow_postdate){
1399 if(!tgt->flags.may_postdate){
1400 kdc_log(context, config, 0,
1401 "Bad request for post-datable ticket");
1402 return KRB5KDC_ERR_BADOPTION;
1404 et->flags.may_postdate = 1;
1407 if(!tgt->flags.may_postdate){
1408 kdc_log(context, config, 0,
1409 "Bad request for postdated ticket");
1410 return KRB5KDC_ERR_BADOPTION;
1413 *et->starttime = *b->from;
1414 et->flags.postdated = 1;
1415 et->flags.invalid = 1;
1416 }else if(b->from && *b->from > kdc_time + context->max_skew){
1417 kdc_log(context, config, 0, "Ticket cannot be postdated");
1418 return KRB5KDC_ERR_CANNOT_POSTDATE;
1422 if(!tgt->flags.renewable){
1423 kdc_log(context, config, 0,
1424 "Bad request for renewable ticket");
1425 return KRB5KDC_ERR_BADOPTION;
1427 et->flags.renewable = 1;
1428 ALLOC(et->renew_till);
1429 fix_time(&b->rtime);
1430 *et->renew_till = *b->rtime;
1434 if(!tgt->flags.renewable || tgt->renew_till == NULL){
1435 kdc_log(context, config, 0,
1436 "Request to renew non-renewable ticket");
1437 return KRB5KDC_ERR_BADOPTION;
1439 old_life = tgt->endtime;
1441 old_life -= *tgt->starttime;
1443 old_life -= tgt->authtime;
1444 et->endtime = *et->starttime + old_life;
1445 if (et->renew_till != NULL)
1446 et->endtime = min(*et->renew_till, et->endtime);
1449 /* checks for excess flags */
1450 if(f.request_anonymous && !config->allow_anonymous){
1451 kdc_log(context, config, 0,
1452 "Request for anonymous ticket");
1453 return KRB5KDC_ERR_BADOPTION;
1458 static krb5_error_code
1459 fix_transited_encoding(krb5_context context,
1460 krb5_kdc_configuration *config,
1461 krb5_boolean check_policy,
1462 TransitedEncoding *tr,
1464 const char *client_realm,
1465 const char *server_realm,
1466 const char *tgt_realm)
1468 krb5_error_code ret = 0;
1469 char **realms, **tmp;
1473 if(tr->tr_type != DOMAIN_X500_COMPRESS) {
1474 kdc_log(context, config, 0,
1475 "Unknown transited type: %u", tr->tr_type);
1476 return KRB5KDC_ERR_TRTYPE_NOSUPP;
1479 ret = krb5_domain_x500_decode(context,
1486 krb5_warn(context, ret,
1487 "Decoding transited encoding");
1490 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1491 /* not us, so add the previous realm to transited set */
1492 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1496 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1502 realms[num_realms] = strdup(tgt_realm);
1503 if(realms[num_realms] == NULL){
1509 if(num_realms == 0) {
1510 if(strcmp(client_realm, server_realm))
1511 kdc_log(context, config, 0,
1512 "cross-realm %s -> %s", client_realm, server_realm);
1516 for(i = 0; i < num_realms; i++)
1517 l += strlen(realms[i]) + 2;
1521 for(i = 0; i < num_realms; i++) {
1523 strlcat(rs, ", ", l);
1524 strlcat(rs, realms[i], l);
1526 kdc_log(context, config, 0,
1527 "cross-realm %s -> %s via [%s]",
1528 client_realm, server_realm, rs);
1533 ret = krb5_check_transited(context, client_realm,
1535 realms, num_realms, NULL);
1537 krb5_warn(context, ret, "cross-realm %s -> %s",
1538 client_realm, server_realm);
1541 et->flags.transited_policy_checked = 1;
1543 et->transited.tr_type = DOMAIN_X500_COMPRESS;
1544 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1546 krb5_warn(context, ret, "Encoding transited encoding");
1548 for(i = 0; i < num_realms; i++)
1555 static krb5_error_code
1556 tgs_make_reply(krb5_context context,
1557 krb5_kdc_configuration *config,
1560 EncTicketPart *adtkt,
1561 AuthorizationData *auth_data,
1564 krb5_principal client_principal,
1566 EncryptionKey *tgtkey,
1567 krb5_enctype cetype,
1568 const char **e_text,
1574 KDCOptions f = b->kdc_options;
1575 krb5_error_code ret;
1578 EncryptionKey *ekey;
1584 for(i = 0; i < b->etype.len; i++){
1585 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1588 if(adtkt->key.keytype == kt)
1591 if(i == b->etype.len)
1592 return KRB5KDC_ERR_ETYPE_NOSUPP;
1593 etype = b->etype.val[i];
1595 ret = find_keys(context, config,
1596 NULL, server, NULL, NULL, &skey, &etype,
1597 b->etype.val, b->etype.len);
1599 kdc_log(context, config, 0, "Server has no support for etypes");
1605 memset(&rep, 0, sizeof(rep));
1606 memset(&et, 0, sizeof(et));
1607 memset(&ek, 0, sizeof(ek));
1610 rep.msg_type = krb_tgs_rep;
1612 et.authtime = tgt->authtime;
1614 et.endtime = min(tgt->endtime, *b->till);
1615 ALLOC(et.starttime);
1616 *et.starttime = kdc_time;
1618 ret = check_tgs_flags(context, config, b, tgt, &et);
1622 /* We should check the transited encoding if:
1623 1) the request doesn't ask not to be checked
1624 2) globally enforcing a check
1625 3) principal requires checking
1626 4) we allow non-check per-principal, but principal isn't marked as allowing this
1627 5) we don't globally allow this
1630 #define GLOBAL_FORCE_TRANSITED_CHECK \
1631 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1632 #define GLOBAL_ALLOW_PER_PRINCIPAL \
1633 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1634 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
1635 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1637 /* these will consult the database in future release */
1638 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
1639 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
1641 ret = fix_transited_encoding(context, config,
1642 !f.disable_transited_check ||
1643 GLOBAL_FORCE_TRANSITED_CHECK ||
1644 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1645 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1646 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1647 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1648 &tgt->transited, &et,
1649 *krb5_princ_realm(context, client_principal),
1650 *krb5_princ_realm(context, server->principal),
1651 *krb5_princ_realm(context, krbtgt->principal));
1655 copy_Realm(krb5_princ_realm(context, server->principal),
1657 _krb5_principal2principalname(&rep.ticket.sname, server->principal);
1658 copy_Realm(&tgt->crealm, &rep.crealm);
1659 if (f.request_anonymous)
1660 make_anonymous_principalname (&tgt->cname);
1662 copy_PrincipalName(&tgt->cname, &rep.cname);
1663 rep.ticket.tkt_vno = 5;
1665 ek.caddr = et.caddr;
1666 if(et.caddr == NULL)
1667 et.caddr = tgt->caddr;
1671 life = et.endtime - *et.starttime;
1672 if(client && client->max_life)
1673 life = min(life, *client->max_life);
1674 if(server->max_life)
1675 life = min(life, *server->max_life);
1676 et.endtime = *et.starttime + life;
1678 if(f.renewable_ok && tgt->flags.renewable &&
1679 et.renew_till == NULL && et.endtime < *b->till){
1680 et.flags.renewable = 1;
1681 ALLOC(et.renew_till);
1682 *et.renew_till = *b->till;
1686 renew = *et.renew_till - et.authtime;
1687 if(client && client->max_renew)
1688 renew = min(renew, *client->max_renew);
1689 if(server->max_renew)
1690 renew = min(renew, *server->max_renew);
1691 *et.renew_till = et.authtime + renew;
1695 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1696 *et.starttime = min(*et.starttime, *et.renew_till);
1697 et.endtime = min(et.endtime, *et.renew_till);
1700 *et.starttime = min(*et.starttime, et.endtime);
1702 if(*et.starttime == et.endtime){
1703 ret = KRB5KDC_ERR_NEVER_VALID;
1706 if(et.renew_till && et.endtime == *et.renew_till){
1707 free(et.renew_till);
1708 et.renew_till = NULL;
1709 et.flags.renewable = 0;
1712 et.flags.pre_authent = tgt->flags.pre_authent;
1713 et.flags.hw_authent = tgt->flags.hw_authent;
1714 et.flags.anonymous = tgt->flags.anonymous;
1715 et.flags.ok_as_delegate = server->flags.ok_as_delegate;
1717 #ifdef _SAMBA_BUILD_
1726 AD_IF_RELEVANT *if_relevant;
1728 if_relevant->len = 1;
1729 if_relevant->val = malloc(sizeof(*if_relevant->val));
1730 if_relevant->val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
1731 if_relevant->val[0].ad_data.data = NULL;
1732 if_relevant->val[0].ad_data.length = 0;
1734 /* Get PAC from Samba */
1735 ret = samba_get_pac(context, config,
1741 free_AuthorizationData(if_relevant);
1745 /* pac.data will be freed with this */
1746 if_relevant->val[0].ad_data.data = pac.data;
1747 if_relevant->val[0].ad_data.length = pac.length;
1749 ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1754 auth_data->val = malloc(sizeof(*auth_data->val));
1755 auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1756 auth_data->val[0].ad_data.length = len;
1757 auth_data->val[0].ad_data.data = buf;
1764 /* XXX Check enc-authorization-data */
1765 et.authorization_data = auth_data;
1767 krb5_generate_random_keyblock(context, etype, &et.key);
1768 et.crealm = tgt->crealm;
1769 et.cname = tgt->cname;
1772 /* MIT must have at least one last_req */
1773 ek.last_req.len = 1;
1774 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1775 ek.nonce = b->nonce;
1776 ek.flags = et.flags;
1777 ek.authtime = et.authtime;
1778 ek.starttime = et.starttime;
1779 ek.endtime = et.endtime;
1780 ek.renew_till = et.renew_till;
1781 ek.srealm = rep.ticket.realm;
1782 ek.sname = rep.ticket.sname;
1784 log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
1785 et.endtime, et.renew_till);
1787 /* It is somewhat unclear where the etype in the following
1788 encryption should come from. What we have is a session
1789 key in the passed tgt, and a list of preferred etypes
1790 *for the new ticket*. Should we pick the best possible
1791 etype, given the keytype in the tgt, or should we look
1792 at the etype list here as well? What if the tgt
1793 session key is DES3 and we want a ticket with a (say)
1794 CAST session key. Should the DES3 etype be added to the
1795 etype list, even if we don't want a session key with
1797 ret = encode_reply(context, config,
1798 &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1799 0, &tgt->key, e_text, reply);
1802 free_TransitedEncoding(&et.transited);
1806 free(et.renew_till);
1807 free_LastReq(&ek.last_req);
1808 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1809 free_EncryptionKey(&et.key);
1813 static krb5_error_code
1814 tgs_check_authenticator(krb5_context context,
1815 krb5_kdc_configuration *config,
1816 krb5_auth_context ac,
1818 const char **e_text,
1821 krb5_authenticator auth;
1825 krb5_error_code ret;
1828 krb5_auth_con_getauthenticator(context, ac, &auth);
1829 if(auth->cksum == NULL){
1830 kdc_log(context, config, 0, "No authenticator in request");
1831 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1835 * according to RFC1510 it doesn't need to be keyed,
1836 * but according to the latest draft it needs to.
1840 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1843 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1844 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
1845 auth->cksum->cksumtype);
1846 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1850 /* XXX should not re-encode this */
1851 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1853 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
1854 krb5_get_err_text(context, ret));
1857 if(buf_size != len) {
1859 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1860 *e_text = "KDC internal error";
1861 ret = KRB5KRB_ERR_GENERIC;
1864 ret = krb5_crypto_init(context, key, 0, &crypto);
1867 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1868 krb5_get_err_text(context, ret));
1871 ret = krb5_verify_checksum(context,
1873 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1878 krb5_crypto_destroy(context, crypto);
1880 kdc_log(context, config, 0, "Failed to verify checksum: %s",
1881 krb5_get_err_text(context, ret));
1884 free_Authenticator(auth);
1890 * return the realm of a krbtgt-ticket or NULL
1894 get_krbtgt_realm(const PrincipalName *p)
1896 if(p->name_string.len == 2
1897 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1898 return p->name_string.val[1];
1904 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1906 const char *new_realm = krb5_config_get_string(context,
1917 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1919 if(server->name.name_type != KRB5_NT_SRV_INST ||
1920 server->name.name_string.len != 2)
1923 return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1924 FALSE, realms) == 0;
1927 static krb5_error_code
1928 tgs_rep2(krb5_context context,
1929 krb5_kdc_configuration *config,
1934 const struct sockaddr *from_addr,
1939 krb5_error_code ret;
1940 krb5_principal princ;
1941 krb5_auth_context ac = NULL;
1942 krb5_ticket *ticket = NULL;
1943 krb5_flags ap_req_options;
1944 krb5_flags verify_ap_req_flags;
1945 const char *e_text = NULL;
1948 hdb_entry *krbtgt = NULL;
1951 krb5_enctype cetype;
1952 krb5_principal cp = NULL;
1953 krb5_principal sp = NULL;
1954 AuthorizationData *auth_data = NULL;
1959 memset(&ap_req, 0, sizeof(ap_req));
1960 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1962 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
1963 krb5_get_err_text(context, ret));
1967 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1968 /* XXX check for ticket.sname == req.sname */
1969 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1970 ret = KRB5KDC_ERR_POLICY; /* ? */
1974 _krb5_principalname2krb5_principal(&princ,
1975 ap_req.ticket.sname,
1976 ap_req.ticket.realm);
1978 ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
1982 ret = krb5_unparse_name(context, princ, &p);
1984 p = "<unparse_name failed>";
1985 krb5_free_principal(context, princ);
1986 kdc_log(context, config, 0,
1987 "Ticket-granting ticket not found in database: %s: %s",
1988 p, krb5_get_err_text(context, ret));
1991 ret = KRB5KRB_AP_ERR_NOT_US;
1995 if(ap_req.ticket.enc_part.kvno &&
1996 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1999 ret = krb5_unparse_name (context, princ, &p);
2000 krb5_free_principal(context, princ);
2002 p = "<unparse_name failed>";
2003 kdc_log(context, config, 0,
2004 "Ticket kvno = %d, DB kvno = %d (%s)",
2005 *ap_req.ticket.enc_part.kvno,
2010 ret = KRB5KRB_AP_ERR_BADKEYVER;
2014 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2017 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2018 kdc_log(context, config, 0,
2019 "No server key found for %s", str);
2021 ret = KRB5KRB_AP_ERR_BADKEYVER;
2025 if (b->kdc_options.validate)
2026 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2028 verify_ap_req_flags = 0;
2030 ret = krb5_verify_ap_req2(context,
2035 verify_ap_req_flags,
2038 KRB5_KU_TGS_REQ_AUTH);
2040 krb5_free_principal(context, princ);
2042 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
2043 krb5_get_err_text(context, ret));
2048 krb5_authenticator auth;
2050 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2052 *csec = malloc(sizeof(**csec));
2053 if (*csec == NULL) {
2054 krb5_free_authenticator(context, &auth);
2055 kdc_log(context, config, 0, "malloc failed");
2058 **csec = auth->ctime;
2059 *cusec = malloc(sizeof(**cusec));
2060 if (*cusec == NULL) {
2061 krb5_free_authenticator(context, &auth);
2062 kdc_log(context, config, 0, "malloc failed");
2065 **csec = auth->cusec;
2066 krb5_free_authenticator(context, &auth);
2070 cetype = ap_req.authenticator.etype;
2072 tgt = &ticket->ticket;
2074 ret = tgs_check_authenticator(context, config,
2075 ac, b, &e_text, &tgt->key);
2077 if (b->enc_authorization_data) {
2078 krb5_keyblock *subkey;
2080 ret = krb5_auth_con_getremotesubkey(context,
2084 krb5_auth_con_free(context, ac);
2085 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
2086 krb5_get_err_text(context, ret));
2090 ret = krb5_auth_con_getkey(context, ac, &subkey);
2092 krb5_auth_con_free(context, ac);
2093 kdc_log(context, config, 0, "Failed to get session key: %s",
2094 krb5_get_err_text(context, ret));
2099 krb5_auth_con_free(context, ac);
2100 kdc_log(context, config, 0,
2101 "Failed to get key for enc-authorization-data");
2102 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2105 ret = krb5_crypto_init(context, subkey, 0, &crypto);
2107 krb5_auth_con_free(context, ac);
2108 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2109 krb5_get_err_text(context, ret));
2112 ret = krb5_decrypt_EncryptedData (context,
2114 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2115 b->enc_authorization_data,
2117 krb5_crypto_destroy(context, crypto);
2119 krb5_auth_con_free(context, ac);
2120 kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2121 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2124 krb5_free_keyblock(context, subkey);
2126 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2128 krb5_auth_con_free(context, ac);
2131 kdc_log(context, config, 0, "Failed to decode authorization data");
2132 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2137 krb5_auth_con_free(context, ac);
2140 kdc_log(context, config, 0, "Failed to verify authenticator: %s",
2141 krb5_get_err_text(context, ret));
2148 char *spn = NULL, *cpn = NULL;
2149 hdb_entry *server = NULL, *client = NULL;
2151 EncTicketPart adtkt;
2156 if(b->kdc_options.enc_tkt_in_skey){
2162 if(b->additional_tickets == NULL ||
2163 b->additional_tickets->len == 0){
2164 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2165 kdc_log(context, config, 0,
2166 "No second ticket present in request");
2169 t = &b->additional_tickets->val[0];
2170 if(!get_krbtgt_realm(&t->sname)){
2171 kdc_log(context, config, 0,
2172 "Additional ticket is not a ticket-granting ticket");
2173 ret = KRB5KDC_ERR_POLICY;
2176 _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2177 ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2178 krb5_free_principal(context, p);
2180 if (ret == HDB_ERR_NOENTRY)
2181 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2184 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2186 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2189 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2197 _krb5_principalname2krb5_principal(&sp, *s, r);
2198 ret = krb5_unparse_name(context, sp, &spn);
2201 _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2202 ret = krb5_unparse_name(context, cp, &cpn);
2205 unparse_flags (KDCOptions2int(b->kdc_options),
2206 asn1_KDCOptions_units(),
2207 opt_str, sizeof(opt_str));
2209 kdc_log(context, config, 0,
2210 "TGS-REQ %s from %s for %s [%s]",
2211 cpn, from, spn, opt_str);
2213 kdc_log(context, config, 0,
2214 "TGS-REQ %s from %s for %s", cpn, from, spn);
2216 ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2219 const char *new_rlm;
2223 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2225 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2227 kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s",
2229 krb5_free_principal(context, sp);
2231 krb5_make_principal(context, &sp, r,
2232 KRB5_TGS_NAME, new_rlm, NULL);
2233 ret = krb5_unparse_name(context, sp, &spn);
2239 } else if(need_referral(context, sp, &realms)) {
2240 if (strcmp(realms[0], sp->realm) != 0) {
2241 kdc_log(context, config, 5,
2242 "Returning a referral to realm %s for "
2243 "server %s that was not found",
2245 krb5_free_principal(context, sp);
2247 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2249 ret = krb5_unparse_name(context, sp, &spn);
2252 krb5_free_host_realm(context, realms);
2255 krb5_free_host_realm(context, realms);
2257 kdc_log(context, config, 0,
2258 "Server not found in database: %s: %s", spn,
2259 krb5_get_err_text(context, ret));
2260 if (ret == HDB_ERR_NOENTRY)
2261 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2265 ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2267 kdc_log(context, config, 1, "Client not found in database: %s: %s",
2268 cpn, krb5_get_err_text(context, ret));
2270 /* XXX check client only if same realm as krbtgt-instance */
2272 kdc_log(context, config, 0,
2273 "Client not found in database: %s: %s",
2274 cpn, krb5_get_err_text(context, ret));
2275 if (ret == HDB_ERR_NOENTRY)
2276 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2281 if(strcmp(krb5_principal_get_realm(context, sp),
2282 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2284 ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2285 kdc_log(context, config, 0,
2286 "Request with wrong krbtgt: %s",
2287 (ret == 0) ? tpn : "<unknown>");
2290 ret = KRB5KRB_AP_ERR_NOT_US;
2295 ret = _kdc_check_flags(context, config,
2302 if((b->kdc_options.validate || b->kdc_options.renew) &&
2303 !krb5_principal_compare(context,
2305 server->principal)){
2306 kdc_log(context, config, 0, "Inconsistent request.");
2307 ret = KRB5KDC_ERR_SERVER_NOMATCH;
2311 /* check for valid set of addresses */
2312 if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2313 ret = KRB5KRB_AP_ERR_BADADDR;
2314 kdc_log(context, config, 0, "Request from wrong address");
2318 ret = tgs_make_reply(context, config,
2321 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
2337 _kdc_free_ent(context, server);
2339 _kdc_free_ent(context, client);
2343 krb5_mk_error(context,
2357 krb5_free_principal(context, cp);
2358 krb5_free_principal(context, sp);
2360 krb5_free_ticket(context, ticket);
2361 free_AP_REQ(&ap_req);
2363 free_AuthorizationData(auth_data);
2368 _kdc_free_ent(context, krbtgt);
2375 _kdc_tgs_rep(krb5_context context,
2376 krb5_kdc_configuration *config,
2380 struct sockaddr *from_addr)
2382 krb5_error_code ret;
2384 PA_DATA *tgs_req = NULL;
2385 time_t *csec = NULL;
2388 if(req->padata == NULL){
2389 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2390 kdc_log(context, config, 0,
2391 "TGS-REQ from %s without PA-DATA", from);
2395 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2397 if(tgs_req == NULL){
2398 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2400 kdc_log(context, config, 0,
2401 "TGS-REQ from %s without PA-TGS-REQ", from);
2404 ret = tgs_rep2(context, config,
2405 &req->req_body, tgs_req, data, from, from_addr,
2408 if(ret && data->data == NULL){
2409 krb5_mk_error(context,