r8302: import mini HEIMDAL into the tree
[samba.git] / source4 / heimdal / kdc / kerberos5.c
1 /*
2  * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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 
31  * SUCH DAMAGE. 
32  */
33
34 #include "kdc_locl.h"
35 #ifdef _SAMBA_BUILD_
36 #include "kdc/pac-glue.h"
37 #endif
38
39 RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
40
41 #define MAX_TIME ((time_t)((1U << 31) - 1))
42
43 static void
44 fix_time(time_t **t)
45 {
46     if(*t == NULL){
47         ALLOC(*t);
48         **t = MAX_TIME;
49     }
50     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
51 }
52
53 static int
54 realloc_method_data(METHOD_DATA *md)
55 {
56     PA_DATA *pa;
57     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
58     if(pa == NULL)
59         return ENOMEM;
60     md->val = pa;
61     md->len++;
62     return 0;
63 }
64
65 static void
66 set_salt_padata (METHOD_DATA *md, Salt *salt)
67 {
68     if (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);
73     }
74 }
75
76 static PA_DATA*
77 find_padata(KDC_REQ *req, int *start, int type)
78 {
79     while(*start < req->padata->len){
80         (*start)++;
81         if(req->padata->val[*start - 1].padata_type == type)
82             return &req->padata->val[*start - 1];
83     }
84     return NULL;
85 }
86
87 /*
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
91  */
92
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)
97 {
98     int i;
99     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
100
101     for(i = 0; ret != 0 && i < len ; i++) {
102         Key *key = NULL;
103
104         if (krb5_enctype_valid(context, etypes[i]) != 0)
105             continue;
106
107         while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
108             if (key->key.keyvalue.length == 0) {
109                 ret = KRB5KDC_ERR_NULL_KEY;
110                 continue;
111             }
112             *ret_key   = key;
113             *ret_etype = etypes[i];
114             ret = 0;
115             if (key->salt == NULL)
116                 return ret;
117         }
118     }
119     return ret;
120 }
121
122 static krb5_error_code
123 find_keys(krb5_context context, 
124           krb5_kdc_configuration *config,
125           hdb_entry *client,
126           hdb_entry *server, 
127           Key **ckey,
128           krb5_enctype *cetype,
129           Key **skey,
130           krb5_enctype *setype, 
131           krb5_enctype *etypes,
132           unsigned num_etypes)
133 {
134     char unparse_name[] = "krb5_unparse_name failed";
135     krb5_error_code ret;
136     char *name;
137
138     if(client){
139         /* find client key */
140         ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
141         if (ret) {
142             if (krb5_unparse_name(context, client->principal, &name) != 0)
143                 name = unparse_name;
144             kdc_log(context, config, 0, 
145                     "Client (%s) has no support for etypes", name);
146             if (name != unparse_name)
147                 free(name);
148             return ret;
149         }
150     }
151
152     if(server){
153         /* find server key */
154         ret = find_etype(context, server, etypes, num_etypes, skey, setype);
155         if (ret) {
156             if (krb5_unparse_name(context, server->principal, &name) != 0)
157                 name = unparse_name;
158             kdc_log(context, config, 0, 
159                     "Server (%s) has no support for etypes", name);
160             if (name != unparse_name)
161                 free(name);
162             return ret;
163         }
164     }
165     return 0;
166 }
167
168 static krb5_error_code
169 make_anonymous_principalname (PrincipalName *pn)
170 {
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)
175         return ENOMEM;
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;
180         return ENOMEM;
181     }
182     return 0;
183 }
184
185 static void
186 log_timestamp(krb5_context context, 
187               krb5_kdc_configuration *config,
188               const char *type,
189               KerberosTime authtime, KerberosTime *starttime, 
190               KerberosTime endtime, KerberosTime *renew_till)
191 {
192     char atime[100], stime[100], etime[100], rtime[100];
193     
194     krb5_format_time(context, authtime, atime, sizeof(atime), TRUE); 
195     if (starttime)
196         krb5_format_time(context, *starttime, stime, sizeof(stime), TRUE); 
197     else
198         strlcpy(stime, "unset", sizeof(stime));
199     krb5_format_time(context, endtime, etime, sizeof(etime), TRUE); 
200     if (renew_till)
201         krb5_format_time(context, *renew_till, rtime, sizeof(rtime), TRUE); 
202     else
203         strlcpy(rtime, "unset", sizeof(rtime));
204     
205     kdc_log(context, config, 5,
206             "%s authtime: %s starttime: %s endtype: %s renew till: %s",
207             type, atime, stime, etime, rtime);
208 }
209
210 static krb5_error_code
211 encode_reply(krb5_context context,
212              krb5_kdc_configuration *config,
213              KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, 
214              krb5_enctype etype, 
215              int skvno, EncryptionKey *skey,
216              int ckvno, EncryptionKey *ckey,
217              const char **e_text,
218              krb5_data *reply)
219 {
220     unsigned char *buf;
221     size_t buf_size;
222     size_t len;
223     krb5_error_code ret;
224     krb5_crypto crypto;
225
226     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
227     if(ret) {
228         kdc_log(context, config, 0, "Failed to encode ticket: %s", 
229                 krb5_get_err_text(context, ret));
230         return ret;
231     }
232     if(buf_size != len) {
233         free(buf);
234         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
235         *e_text = "KDC internal error";
236         return KRB5KRB_ERR_GENERIC;
237     }
238
239     ret = krb5_crypto_init(context, skey, etype, &crypto);
240     if (ret) {
241         free(buf);
242         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
243                 krb5_get_err_text(context, ret));
244         return ret;
245     }
246
247     ret = krb5_encrypt_EncryptedData(context, 
248                                      crypto,
249                                      KRB5_KU_TICKET,
250                                      buf,
251                                      len,
252                                      skvno,
253                                      &rep->ticket.enc_part);
254     free(buf);
255     krb5_crypto_destroy(context, crypto);
256     if(ret) {
257         kdc_log(context, config, 0, "Failed to encrypt data: %s",
258                 krb5_get_err_text(context, ret));
259         return ret;
260     }
261     
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);
264     else
265         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
266     if(ret) {
267         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
268                 krb5_get_err_text(context, ret));
269         return ret;
270     }
271     if(buf_size != len) {
272         free(buf);
273         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
274         *e_text = "KDC internal error";
275         return KRB5KRB_ERR_GENERIC;
276     }
277     ret = krb5_crypto_init(context, ckey, 0, &crypto);
278     if (ret) {
279         free(buf);
280         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
281                 krb5_get_err_text(context, ret));
282         return ret;
283     }
284     if(rep->msg_type == krb_as_rep) {
285         krb5_encrypt_EncryptedData(context,
286                                    crypto,
287                                    KRB5_KU_AS_REP_ENC_PART,
288                                    buf,
289                                    len,
290                                    ckvno,
291                                    &rep->enc_part);
292         free(buf);
293         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
294     } else {
295         krb5_encrypt_EncryptedData(context,
296                                    crypto,
297                                    KRB5_KU_TGS_REP_ENC_PART_SESSION,
298                                    buf,
299                                    len,
300                                    ckvno,
301                                    &rep->enc_part);
302         free(buf);
303         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
304     }
305     krb5_crypto_destroy(context, crypto);
306     if(ret) {
307         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
308                 krb5_get_err_text(context, ret));
309         return ret;
310     }
311     if(buf_size != len) {
312         free(buf);
313         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
314         *e_text = "KDC internal error";
315         return KRB5KRB_ERR_GENERIC;
316     }
317     reply->data = buf;
318     reply->length = buf_size;
319     return 0;
320 }
321
322 static krb5_error_code
323 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
324 {
325     ent->etype = key->key.keytype;
326     if(key->salt){
327         ALLOC(ent->salttype);
328 #if 0
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)
332             *ent->salttype = 2;
333         else {
334             kdc_log(context, config, 0, "unknown salt-type: %d", 
335                     key->salt->type);
336             return KRB5KRB_ERR_GENERIC;
337         }
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
342            case) */
343 #else
344         *ent->salttype = key->salt->type;
345 #endif
346         krb5_copy_data(context, &key->salt->salt,
347                        &ent->salt);
348     } else {
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
352          * here. */
353
354         ent->salttype = NULL;
355         ent->salt = NULL;
356     }
357     return 0;
358 }
359
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)
365 {
366     krb5_error_code ret = 0;
367     int i, j;
368     unsigned int n = 0;
369     ETYPE_INFO pa;
370     unsigned char *buf;
371     size_t len;
372     
373
374     pa.len = client->keys.len;
375     if(pa.len > UINT_MAX/sizeof(*pa.val))
376         return ERANGE;
377     pa.val = malloc(pa.len * sizeof(*pa.val));
378     if(pa.val == NULL)
379         return ENOMEM;
380     memset(pa.val, 0, pa.len * sizeof(*pa.val));
381
382     for(j = 0; j < etypes_len; j++) {
383         for (i = 0; i < n; i++)
384             if (pa.val[i].etype == etypes[j])
385                 goto skip1;
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)
389                     continue;
390                 if((ret = make_etype_info_entry(context, 
391                                                 &pa.val[n++], 
392                                                 &client->keys.val[i])) != 0) {
393                     free_ETYPE_INFO(&pa);
394                     return ret;
395                 }
396             }
397         }
398     skip1:;
399     }
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])
403                 goto skip2;
404         }
405         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
406             continue;
407         if((ret = make_etype_info_entry(context, 
408                                         &pa.val[n++], 
409                                         &client->keys.val[i])) != 0) {
410             free_ETYPE_INFO(&pa);
411             return ret;
412         }
413     skip2:;
414     }
415     
416     if(n != pa.len) {
417         char *name;
418         ret = krb5_unparse_name(context, client->principal, &name);
419         if (ret)
420             name = "<unparse_name failed>";
421         kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d", 
422                 name, n, pa.len);
423         if (ret == 0)
424             free(name);
425         pa.len = n;
426     }
427
428     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
429     free_ETYPE_INFO(&pa);
430     if(ret)
431         return ret;
432     ret = realloc_method_data(md);
433     if(ret) {
434         free(buf);
435         return ret;
436     }
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;
440     return 0;
441 }
442
443 /*
444  *
445  */
446
447 extern int _krb5_AES_string_to_default_iterator;
448
449 static krb5_error_code
450 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
451 {
452     ent->etype = key->key.keytype;
453     if(key->salt) {
454         ALLOC(ent->salt);
455         if (ent->salt == NULL)
456             return ENOMEM;
457         *ent->salt = malloc(key->salt->salt.length + 1);
458         if (*ent->salt == NULL) {
459             free(ent->salt);
460             ent->salt = NULL;
461             return ENOMEM;
462         }
463         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
464         (*ent->salt)[key->salt->salt.length] = '\0';
465     } else
466         ent->salt = NULL;
467
468     ent->s2kparams = NULL;
469
470     switch (key->key.keytype) {
471     case KEYTYPE_AES128:
472     case KEYTYPE_AES256:
473         ALLOC(ent->s2kparams);
474         if (ent->s2kparams == NULL)
475             return ENOMEM;
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;
481             return ENOMEM;
482         }
483         _krb5_put_int(ent->s2kparams->data, 
484                       _krb5_AES_string_to_default_iterator, 
485                       ent->s2kparams->length);
486         break;
487     default:
488         break;
489     }
490     return 0;
491 }
492
493 /*
494  * Return 1 if the client have only older enctypes, this is for
495  * determining if the server should send ETYPE_INFO2 or not.
496  */
497
498 static int
499 only_older_enctype_p(const KDC_REQ *req)
500 {
501     int i;
502
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:
511             break;
512         default:
513             return 0;
514         }
515     }
516     return 1;
517 }
518
519 /*
520  *
521  */
522
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)
528 {
529     krb5_error_code ret = 0;
530     int i, j;
531     unsigned int n = 0;
532     ETYPE_INFO2 pa;
533     unsigned char *buf;
534     size_t len;
535
536     pa.len = client->keys.len;
537     if(pa.len > UINT_MAX/sizeof(*pa.val))
538         return ERANGE;
539     pa.val = malloc(pa.len * sizeof(*pa.val));
540     if(pa.val == NULL)
541         return ENOMEM;
542     memset(pa.val, 0, pa.len * sizeof(*pa.val));
543
544     for(j = 0; j < etypes_len; j++) {
545         for (i = 0; i < n; i++)
546             if (pa.val[i].etype == etypes[j])
547                 goto skip1;
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)
551                     continue;
552                 if((ret = make_etype_info2_entry(&pa.val[n++], 
553                                                  &client->keys.val[i])) != 0) {
554                     free_ETYPE_INFO2(&pa);
555                     return ret;
556                 }
557             }
558         }
559     skip1:;
560     }
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])
564                 goto skip2;
565         }
566         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
567             continue;
568         if((ret = make_etype_info2_entry(&pa.val[n++],
569                                          &client->keys.val[i])) != 0) {
570             free_ETYPE_INFO2(&pa);
571             return ret;
572         }
573       skip2:;
574     }
575     
576     if(n != pa.len) {
577         char *name;
578         ret = krb5_unparse_name(context, client->principal, &name);
579         if (ret)
580             name = "<unparse_name failed>";
581         kdc_log(context, config, 0, "internal error in get_pa_etype_info2(%s): %d != %d", 
582                 name, n, pa.len);
583         if (ret == 0)
584             free(name);
585         pa.len = n;
586     }
587
588     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
589     free_ETYPE_INFO2(&pa);
590     if(ret)
591         return ret;
592     ret = realloc_method_data(md);
593     if(ret) {
594         free(buf);
595         return ret;
596     }
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;
600     return 0;
601 }
602
603 /*
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.
607  */
608
609 krb5_error_code
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)
615 {
616     if(client != NULL) {
617         /* check client */
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;
622         }
623         
624         if(!client->flags.client){
625             kdc_log(context, config, 0,
626                     "Principal may not act as client -- %s", 
627                     client_name);
628             return KRB5KDC_ERR_POLICY;
629         }
630         
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;
634         }
635         
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;
639         }
640         
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;
645         }
646     }
647
648     /* check server */
649     
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;
654         }
655
656         if(!server->flags.server){
657             kdc_log(context, config, 0, "Principal may not act as server -- %s", 
658                     server_name);
659             return KRB5KDC_ERR_POLICY;
660         }
661
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;
665         }
666
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;
670         }
671
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;
675         }
676
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;
680         }
681     }
682     return 0;
683 }
684
685 /*
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
688  * these checks
689  */
690
691 static krb5_boolean
692 check_addresses(krb5_context context,        
693                 krb5_kdc_configuration *config,
694                 HostAddresses *addresses, const struct sockaddr *from)
695 {
696     krb5_error_code ret;
697     krb5_address addr;
698     krb5_boolean result;
699     
700     if(config->check_ticket_addresses == 0)
701         return TRUE;
702
703     if(addresses == NULL)
704         return config->allow_null_ticket_addresses;
705     
706     ret = krb5_sockaddr2address (context, from, &addr);
707     if(ret)
708         return FALSE;
709
710     result = krb5_address_search(context, &addr, addresses);
711     krb5_free_address (context, &addr);
712     return result;
713 }
714
715 krb5_error_code
716 _kdc_as_rep(krb5_context context, 
717             krb5_kdc_configuration *config,
718             KDC_REQ *req, 
719             krb5_data *reply,
720             const char *from,
721             struct sockaddr *from_addr)
722 {
723     KDC_REQ_BODY *b = &req->req_body;
724     AS_REP rep;
725     KDCOptions f = b->kdc_options;
726     hdb_entry *client = NULL, *server = NULL;
727     krb5_enctype cetype, setype;
728     EncTicketPart et;
729     EncKDCRepPart ek;
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;
734     krb5_crypto crypto;
735     Key *ckey, *skey;
736     EncryptionKey *reply_key;
737 #ifdef PKINIT
738     pk_client_params *pkp = NULL;
739 #endif
740
741     memset(&rep, 0, sizeof(rep));
742
743     if(b->sname == NULL){
744         ret = KRB5KRB_ERR_GENERIC;
745         e_text = "No server in request";
746     } else{
747         _krb5_principalname2krb5_principal (&server_princ,
748                                             *(b->sname), b->realm);
749         ret = krb5_unparse_name(context, server_princ, &server_name);
750     }
751     if (ret) {
752         kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
753         goto out;
754     }
755     
756     if(b->cname == NULL){
757         ret = KRB5KRB_ERR_GENERIC;
758         e_text = "No client in request";
759     } else {
760         _krb5_principalname2krb5_principal (&client_princ,
761                                             *(b->cname), b->realm);
762         ret = krb5_unparse_name(context, client_princ, &client_name);
763     }
764     if (ret) {
765         kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
766         goto out;
767     }
768
769     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
770             client_name, from, server_name);
771
772     ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
773     if(ret){
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;
777         goto out;
778     }
779
780     ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
781     if(ret){
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;
785         goto out;
786     }
787
788     ret = _kdc_check_flags(context, config, 
789                            client, client_name,
790                            server, server_name,
791                            TRUE);
792     if(ret)
793         goto out;
794
795     memset(&et, 0, sizeof(et));
796     memset(&ek, 0, sizeof(ek));
797
798     if(req->padata){
799         int i = 0;
800         PA_DATA *pa;
801         int found_pa = 0;
802
803 #ifdef PKINIT
804         kdc_log(context, config, 5, 
805                 "Looking for PKINIT pa-data -- %s", client_name);
806
807         e_text = "No PKINIT PA found";
808
809         i = 0;
810         if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
811             ;
812         if (pa == NULL) {
813             i = 0;
814             if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
815                 ;
816         }
817         if (pa == NULL) {
818             i = 0;
819             if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
820                 ;
821         }
822         if (pa) {
823             char *client_cert = NULL;
824
825             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
826             if (ret) {
827                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
828                 kdc_log(context, config, 5, 
829                         "Failed to decode PKINIT PA-DATA -- %s", 
830                         client_name);
831                 goto ts_enc;
832             }
833             if (ret == 0 && pkp == NULL)
834                 goto ts_enc;
835
836             ret = _kdc_pk_check_client(context,
837                                        config,
838                                        client_princ, 
839                                        client,
840                                        pkp,
841                                        &client_cert);
842             if (ret) {
843                 e_text = "PKINIT certificate not allowed to "
844                     "impersonate principal";
845                 _kdc_pk_free_client_param(context, pkp);
846                 pkp = NULL;
847                 goto ts_enc;
848             }
849             found_pa = 1;
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);
854             free(client_cert);
855             if (pkp)
856                 goto preauth_done;
857         }
858     ts_enc:
859 #endif
860         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
861                 client_name);
862
863         i = 0;
864         e_text = "No ENC-TS found";
865         while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
866             krb5_data ts_data;
867             PA_ENC_TS_ENC p;
868             size_t len;
869             EncryptedData enc_data;
870             Key *pa_key;
871             
872             found_pa = 1;
873             
874             ret = decode_EncryptedData(pa->padata_value.data,
875                                        pa->padata_value.length,
876                                        &enc_data,
877                                        &len);
878             if (ret) {
879                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
880                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
881                         client_name);
882                 goto out;
883             }
884             
885             ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
886             if(ret){
887                 char *estr;
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))
891                     estr = NULL;
892                 if(estr == NULL)
893                     kdc_log(context, config, 5, 
894                             "No client key matching pa-data (%d) -- %s", 
895                             enc_data.etype, client_name);
896                 else
897                     kdc_log(context, config, 5,
898                             "No client key matching pa-data (%s) -- %s", 
899                             estr, client_name);
900                 free(estr);
901                     
902                 free_EncryptedData(&enc_data);
903                 continue;
904             }
905
906         try_next_key:
907             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
908             if (ret) {
909                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
910                         krb5_get_err_text(context, ret));
911                 free_EncryptedData(&enc_data);
912                 continue;
913             }
914
915             ret = krb5_decrypt_EncryptedData (context,
916                                               crypto,
917                                               KRB5_KU_PA_ENC_TIMESTAMP,
918                                               &enc_data,
919                                               &ts_data);
920             krb5_crypto_destroy(context, crypto);
921             if(ret){
922                 if(hdb_next_enctype2key(context, client, 
923                                         enc_data.etype, &pa_key) == 0)
924                     goto try_next_key;
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",
929                         client_name);
930                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
931                 continue;
932             }
933             free_EncryptedData(&enc_data);
934             ret = decode_PA_ENC_TS_ENC(ts_data.data,
935                                        ts_data.length,
936                                        &p,
937                                        &len);
938             krb5_data_free(&ts_data);
939             if(ret){
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",
944                         client_name);
945                 continue;
946             }
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);
953                 goto out;
954             }
955             et.flags.pre_authent = 1;
956             kdc_log(context, config, 2,
957                     "ENC-TS Pre-authentication succeeded -- %s", 
958                     client_name);
959             break;
960         }
961 #ifdef PKINIT
962     preauth_done:
963 #endif
964         if(found_pa == 0 && config->require_preauth)
965             goto use_pa;
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);
970             e_text = NULL;
971             goto out;
972         }
973     }else if (config->require_preauth
974               || client->flags.require_preauth
975               || server->flags.require_preauth) {
976         METHOD_DATA method_data;
977         PA_DATA *pa;
978         unsigned char *buf;
979         size_t len;
980         krb5_data foo_data;
981
982     use_pa: 
983         method_data.len = 0;
984         method_data.val = NULL;
985
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;
991
992 #ifdef PKINIT
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;
998
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;
1004 #endif
1005
1006         /* XXX check ret */
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); 
1010         /* XXX check ret */
1011         ret = get_pa_etype_info2(context, config, &method_data, client, 
1012                                  b->etype.val, b->etype.len);
1013
1014         
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;
1019         
1020         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1021         krb5_mk_error(context,
1022                       ret,
1023                       "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1024                       &foo_data,
1025                       client_princ,
1026                       server_princ,
1027                       NULL,
1028                       NULL,
1029                       reply);
1030         free(buf);
1031         kdc_log(context, config, 0,
1032                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1033                 client_name);
1034         ret = 0;
1035         goto out2;
1036     }
1037     
1038     ret = find_keys(context, config, 
1039                     client, server, &ckey, &cetype, &skey, &setype,
1040                     b->etype.val, b->etype.len);
1041     if(ret) {
1042         kdc_log(context, config, 0, "Server/client has no support for etypes");
1043         goto out;
1044     }
1045         
1046     {
1047         struct rk_strpool *p = NULL;
1048         char *str;
1049         int i;
1050
1051         for (i = 0; i < b->etype.len; i++) {
1052             ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1053             if (ret == 0) {
1054                 p = rk_strpoolprintf(p, "%s", str);
1055                 free(str);
1056             } else
1057                 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1058             if (p && i + 1 < b->etype.len)
1059                 p = rk_strpoolprintf(p, ", ");
1060             if (p == NULL) {
1061                 kdc_log(context, config, 0, "out of meory");
1062                 goto out;
1063             }
1064         }
1065         str = rk_strpoolcollect(p);
1066         kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1067         free(str);
1068     }
1069     {
1070         char *cet;
1071         char *set;
1072
1073         ret = krb5_enctype_to_string(context, cetype, &cet);
1074         if(ret == 0) {
1075             ret = krb5_enctype_to_string(context, setype, &set);
1076             if (ret == 0) {
1077                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1078                 free(set);
1079             }
1080             free(cet);
1081         }
1082         if (ret != 0)
1083             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1084     }
1085     
1086     {
1087         char str[128];
1088         unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(), 
1089                       str, sizeof(str));
1090         if(*str)
1091             kdc_log(context, config, 2, "Requested flags: %s", str);
1092     }
1093     
1094
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);
1099         goto out;
1100     }
1101     
1102     rep.pvno = 5;
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);
1107     else
1108         _krb5_principal2principalname(&rep.cname, 
1109                                       client->principal);
1110     rep.ticket.tkt_vno = 5;
1111     copy_Realm(&server->principal->realm, &rep.ticket.realm);
1112     _krb5_principal2principalname(&rep.ticket.sname, 
1113                                   server->principal);
1114
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);
1122         goto out;
1123     }
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);
1130         goto out;
1131     }
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);
1138         goto out;
1139     }
1140
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);
1146         goto out;
1147     }
1148
1149     krb5_generate_random_keyblock(context, setype, &et.key);
1150     copy_PrincipalName(&rep.cname, &et.cname);
1151     copy_Realm(&rep.crealm, &et.crealm);
1152     
1153     {
1154         time_t start;
1155         time_t t;
1156         
1157         start = et.authtime = kdc_time;
1158     
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 ??? */
1164         }
1165         fix_time(&b->till);
1166         t = *b->till;
1167
1168         /* be careful not overflowing */
1169
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);
1174 #if 0
1175         t = min(t, start + realm->max_life);
1176 #endif
1177         et.endtime = t;
1178         if(f.renewable_ok && et.endtime < *b->till){
1179             f.renewable = 1;
1180             if(b->rtime == NULL){
1181                 ALLOC(b->rtime);
1182                 *b->rtime = 0;
1183             }
1184             if(*b->rtime < *b->till)
1185                 *b->rtime = *b->till;
1186         }
1187         if(f.renewable && b->rtime){
1188             t = *b->rtime;
1189             if(t == 0)
1190                 t = MAX_TIME;
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);
1195 #if 0
1196             t = min(t, start + realm->max_renew);
1197 #endif
1198             ALLOC(et.renew_till);
1199             *et.renew_till = t;
1200             et.flags.renewable = 1;
1201         }
1202     }
1203
1204     if (f.request_anonymous)
1205         et.flags.anonymous = 1;
1206     
1207     if(b->addresses){
1208         ALLOC(et.caddr);
1209         copy_HostAddresses(b->addresses, et.caddr);
1210     }
1211     
1212     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1213     krb5_data_zero(&et.transited.contents); 
1214      
1215     copy_EncryptionKey(&et.key, &ek.key);
1216
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.
1220      *
1221      * To fix this, always send at least one no-op last_req
1222      *
1223      * If there's a pw_end or valid_end we will use that,
1224      * otherwise just a dummy lr.
1225      */
1226     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1227     ek.last_req.len = 0;
1228     if (client->pw_end
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;
1233         ++ek.last_req.len;
1234     }
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;
1238         ++ek.last_req.len;
1239     }
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;
1243         ++ek.last_req.len;
1244     }
1245     ek.nonce = b->nonce;
1246     if (client->valid_end || client->pw_end) {
1247         ALLOC(ek.key_expiration);
1248         if (client->valid_end) {
1249             if (client->pw_end)
1250                 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1251             else
1252                 *ek.key_expiration = *client->valid_end;
1253         } else
1254             *ek.key_expiration = *client->pw_end;
1255     } else
1256         ek.key_expiration = NULL;
1257     ek.flags = et.flags;
1258     ek.authtime = et.authtime;
1259     if (et.starttime) {
1260         ALLOC(ek.starttime);
1261         *ek.starttime = *et.starttime;
1262     }
1263     ek.endtime = et.endtime;
1264     if (et.renew_till) {
1265         ALLOC(ek.renew_till);
1266         *ek.renew_till = *et.renew_till;
1267     }
1268     copy_Realm(&rep.ticket.realm, &ek.srealm);
1269     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1270     if(et.caddr){
1271         ALLOC(ek.caddr);
1272         copy_HostAddresses(et.caddr, ek.caddr);
1273     }
1274
1275     ALLOC(rep.padata);
1276     rep.padata->len = 0;
1277     rep.padata->val = NULL;
1278
1279     reply_key = &ckey->key;
1280 #if PKINIT
1281     if (pkp) {
1282         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, req,
1283                               &reply_key, rep.padata);
1284         if (ret)
1285             goto out;
1286     }
1287 #endif
1288
1289     set_salt_padata (rep.padata, ckey->salt);
1290
1291     if (rep.padata->len == 0) {
1292         free(rep.padata);
1293         rep.padata = NULL;
1294     }
1295
1296     log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1297                   et.endtime, et.renew_till);
1298
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);
1304  out:
1305     free_AS_REP(&rep);
1306     if(ret){
1307         krb5_mk_error(context,
1308                       ret,
1309                       e_text,
1310                       NULL,
1311                       client_princ,
1312                       server_princ,
1313                       NULL,
1314                       NULL,
1315                       reply);
1316         ret = 0;
1317     }
1318  out2:
1319 #ifdef PKINIT
1320     if (pkp)
1321         _kdc_pk_free_client_param(context, pkp);
1322 #endif
1323     if (client_princ)
1324         krb5_free_principal(context, client_princ);
1325     free(client_name);
1326     if (server_princ)
1327         krb5_free_principal(context, server_princ);
1328     free(server_name);
1329     if(client)
1330         _kdc_free_ent(context, client);
1331     if(server)
1332         _kdc_free_ent(context, server);
1333     return ret;
1334 }
1335
1336
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)
1341 {
1342     KDCOptions f = b->kdc_options;
1343         
1344     if(f.validate){
1345         if(!tgt->flags.invalid || tgt->starttime == NULL){
1346             kdc_log(context, config, 0, "Bad request to validate ticket");
1347             return KRB5KDC_ERR_BADOPTION;
1348         }
1349         if(*tgt->starttime > kdc_time){
1350             kdc_log(context, config, 0, "Early request to validate ticket");
1351             return KRB5KRB_AP_ERR_TKT_NYV;
1352         }
1353         /* XXX  tkt = tgt */
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;
1358     }
1359
1360     if(f.forwardable){
1361         if(!tgt->flags.forwardable){
1362             kdc_log(context, config, 0, "Bad request for forwardable ticket");
1363             return KRB5KDC_ERR_BADOPTION;
1364         }
1365         et->flags.forwardable = 1;
1366     }
1367     if(f.forwarded){
1368         if(!tgt->flags.forwardable){
1369             kdc_log(context, config, 0, "Request to forward non-forwardable ticket");
1370             return KRB5KDC_ERR_BADOPTION;
1371         }
1372         et->flags.forwarded = 1;
1373         et->caddr = b->addresses;
1374     }
1375     if(tgt->flags.forwarded)
1376         et->flags.forwarded = 1;
1377         
1378     if(f.proxiable){
1379         if(!tgt->flags.proxiable){
1380             kdc_log(context, config, 0,
1381                     "Bad request for proxiable ticket");
1382             return KRB5KDC_ERR_BADOPTION;
1383         }
1384         et->flags.proxiable = 1;
1385     }
1386     if(f.proxy){
1387         if(!tgt->flags.proxiable){
1388             kdc_log(context, config, 0,
1389                     "Request to proxy non-proxiable ticket");
1390             return KRB5KDC_ERR_BADOPTION;
1391         }
1392         et->flags.proxy = 1;
1393         et->caddr = b->addresses;
1394     }
1395     if(tgt->flags.proxy)
1396         et->flags.proxy = 1;
1397
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;
1403         }
1404         et->flags.may_postdate = 1;
1405     }
1406     if(f.postdated){
1407         if(!tgt->flags.may_postdate){
1408             kdc_log(context, config, 0,
1409                     "Bad request for postdated ticket");
1410             return KRB5KDC_ERR_BADOPTION;
1411         }
1412         if(b->from)
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;
1419     }
1420
1421     if(f.renewable){
1422         if(!tgt->flags.renewable){
1423             kdc_log(context, config, 0,
1424                     "Bad request for renewable ticket");
1425             return KRB5KDC_ERR_BADOPTION;
1426         }
1427         et->flags.renewable = 1;
1428         ALLOC(et->renew_till);
1429         fix_time(&b->rtime);
1430         *et->renew_till = *b->rtime;
1431     }
1432     if(f.renew){
1433         time_t old_life;
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;
1438         }
1439         old_life = tgt->endtime;
1440         if(tgt->starttime)
1441             old_life -= *tgt->starttime;
1442         else
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);
1447     }       
1448     
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;
1454     }
1455     return 0;
1456 }
1457
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, 
1463                        EncTicketPart *et, 
1464                        const char *client_realm, 
1465                        const char *server_realm, 
1466                        const char *tgt_realm)
1467 {
1468     krb5_error_code ret = 0;
1469     char **realms, **tmp;
1470     int num_realms;
1471     int i;
1472
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;
1477     }
1478
1479     ret = krb5_domain_x500_decode(context, 
1480                                   tr->contents,
1481                                   &realms, 
1482                                   &num_realms,
1483                                   client_realm,
1484                                   server_realm);
1485     if(ret){
1486         krb5_warn(context, ret,
1487                   "Decoding transited encoding");
1488         return ret;
1489     }
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)) {
1493             ret = ERANGE;
1494             goto free_realms;
1495         }
1496         tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1497         if(tmp == NULL){
1498             ret = ENOMEM;
1499             goto free_realms;
1500         }
1501         realms = tmp;
1502         realms[num_realms] = strdup(tgt_realm);
1503         if(realms[num_realms] == NULL){
1504             ret = ENOMEM;
1505             goto free_realms;
1506         }
1507         num_realms++;
1508     }
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);
1513     } else {
1514         size_t l = 0;
1515         char *rs;
1516         for(i = 0; i < num_realms; i++)
1517             l += strlen(realms[i]) + 2;
1518         rs = malloc(l);
1519         if(rs != NULL) {
1520             *rs = '\0';
1521             for(i = 0; i < num_realms; i++) {
1522                 if(i > 0)
1523                     strlcat(rs, ", ", l);
1524                 strlcat(rs, realms[i], l);
1525             }
1526             kdc_log(context, config, 0,
1527                     "cross-realm %s -> %s via [%s]",
1528                     client_realm, server_realm, rs);
1529             free(rs);
1530         }
1531     }
1532     if(check_policy) {
1533         ret = krb5_check_transited(context, client_realm, 
1534                                    server_realm, 
1535                                    realms, num_realms, NULL);
1536         if(ret) {
1537             krb5_warn(context, ret, "cross-realm %s -> %s", 
1538                       client_realm, server_realm);
1539             goto free_realms;
1540         }
1541         et->flags.transited_policy_checked = 1;
1542     }
1543     et->transited.tr_type = DOMAIN_X500_COMPRESS;
1544     ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1545     if(ret)
1546         krb5_warn(context, ret, "Encoding transited encoding");
1547   free_realms:
1548     for(i = 0; i < num_realms; i++)
1549         free(realms[i]);
1550     free(realms);
1551     return ret;
1552 }
1553
1554
1555 static krb5_error_code
1556 tgs_make_reply(krb5_context context, 
1557                krb5_kdc_configuration *config,
1558                KDC_REQ_BODY *b, 
1559                EncTicketPart *tgt, 
1560                EncTicketPart *adtkt, 
1561                AuthorizationData *auth_data,
1562                hdb_entry *server, 
1563                hdb_entry *client, 
1564                krb5_principal client_principal, 
1565                hdb_entry *krbtgt,
1566                EncryptionKey *tgtkey,
1567                krb5_enctype cetype,
1568                const char **e_text,
1569                krb5_data *reply)
1570 {
1571     KDC_REP rep;
1572     EncKDCRepPart ek;
1573     EncTicketPart et;
1574     KDCOptions f = b->kdc_options;
1575     krb5_error_code ret;
1576     krb5_enctype etype;
1577     Key *skey;
1578     EncryptionKey *ekey;
1579     
1580     if(adtkt) {
1581         int i;
1582         krb5_keytype kt;
1583         ekey = &adtkt->key;
1584         for(i = 0; i < b->etype.len; i++){
1585             ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1586             if(ret)
1587                 continue;
1588             if(adtkt->key.keytype == kt)
1589                 break;
1590         }
1591         if(i == b->etype.len)
1592             return KRB5KDC_ERR_ETYPE_NOSUPP;
1593         etype = b->etype.val[i];
1594     }else{
1595         ret = find_keys(context, config, 
1596                         NULL, server, NULL, NULL, &skey, &etype, 
1597                         b->etype.val, b->etype.len);
1598         if(ret) {
1599             kdc_log(context, config, 0, "Server has no support for etypes");
1600             return ret;
1601         }
1602         ekey = &skey->key;
1603     }
1604     
1605     memset(&rep, 0, sizeof(rep));
1606     memset(&et, 0, sizeof(et));
1607     memset(&ek, 0, sizeof(ek));
1608     
1609     rep.pvno = 5;
1610     rep.msg_type = krb_tgs_rep;
1611
1612     et.authtime = tgt->authtime;
1613     fix_time(&b->till);
1614     et.endtime = min(tgt->endtime, *b->till);
1615     ALLOC(et.starttime);
1616     *et.starttime = kdc_time;
1617     
1618     ret = check_tgs_flags(context, config, b, tgt, &et);
1619     if(ret)
1620         goto out;
1621
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
1628     */
1629
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)
1636
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
1640
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));
1652     if(ret)
1653         goto out;
1654
1655     copy_Realm(krb5_princ_realm(context, server->principal), 
1656                &rep.ticket.realm);
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);
1661     else
1662         copy_PrincipalName(&tgt->cname, &rep.cname);
1663     rep.ticket.tkt_vno = 5;
1664
1665     ek.caddr = et.caddr;
1666     if(et.caddr == NULL)
1667         et.caddr = tgt->caddr;
1668
1669     {
1670         time_t life;
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;
1677     }
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;
1683     }
1684     if(et.renew_till){
1685         time_t renew;
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;
1692     }
1693             
1694     if(et.renew_till){
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);
1698     }
1699     
1700     *et.starttime = min(*et.starttime, et.endtime);
1701
1702     if(*et.starttime == et.endtime){
1703         ret = KRB5KDC_ERR_NEVER_VALID;
1704         goto out;
1705     }
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;
1710     }
1711     
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;
1716             
1717 #ifdef _SAMBA_BUILD_
1718  
1719     {
1720
1721             unsigned char *buf;
1722             size_t buf_size;
1723             size_t len;
1724
1725             krb5_data pac;
1726             AD_IF_RELEVANT *if_relevant;
1727             ALLOC(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;
1733
1734             /* Get PAC from Samba */
1735             ret = samba_get_pac(context, config, 
1736                                 client->principal,
1737                                 tgtkey,
1738                                 ekey,
1739                                 &pac);
1740             if (ret) {
1741                     free_AuthorizationData(if_relevant);
1742                     goto out;
1743             }
1744
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;
1748
1749             ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1750             
1751             auth_data = NULL;
1752             ALLOC(auth_data);
1753             auth_data->len = 1;
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;
1758             if (ret) {
1759                     goto out;
1760             }
1761     }
1762
1763 #endif
1764     /* XXX Check enc-authorization-data */
1765     et.authorization_data = auth_data;
1766
1767     krb5_generate_random_keyblock(context, etype, &et.key);
1768     et.crealm = tgt->crealm;
1769     et.cname = tgt->cname;
1770             
1771     ek.key = et.key;
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;
1783     
1784     log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, 
1785                   et.endtime, et.renew_till);
1786
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
1796        DES3? */
1797     ret = encode_reply(context, config, 
1798                        &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1799                        0, &tgt->key, e_text, reply);
1800   out:
1801     free_TGS_REP(&rep);
1802     free_TransitedEncoding(&et.transited);
1803     if(et.starttime)
1804         free(et.starttime);
1805     if(et.renew_till)
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);
1810     return ret;
1811 }
1812
1813 static krb5_error_code
1814 tgs_check_authenticator(krb5_context context, 
1815                         krb5_kdc_configuration *config,
1816                         krb5_auth_context ac,
1817                         KDC_REQ_BODY *b, 
1818                         const char **e_text,
1819                         krb5_keyblock *key)
1820 {
1821     krb5_authenticator auth;
1822     size_t len;
1823     unsigned char *buf;
1824     size_t buf_size;
1825     krb5_error_code ret;
1826     krb5_crypto crypto;
1827     
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;
1832         goto out;
1833     }
1834     /*
1835      * according to RFC1510 it doesn't need to be keyed,
1836      * but according to the latest draft it needs to.
1837      */
1838     if (
1839 #if 0
1840 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1841         ||
1842 #endif
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;
1847         goto out;
1848     }
1849                 
1850     /* XXX should not re-encode this */
1851     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1852     if(ret){
1853         kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", 
1854                 krb5_get_err_text(context, ret));
1855         goto out;
1856     }
1857     if(buf_size != len) {
1858         free(buf);
1859         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1860         *e_text = "KDC internal error";
1861         ret = KRB5KRB_ERR_GENERIC;
1862         goto out;
1863     }
1864     ret = krb5_crypto_init(context, key, 0, &crypto);
1865     if (ret) {
1866         free(buf);
1867         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1868                 krb5_get_err_text(context, ret));
1869         goto out;
1870     }
1871     ret = krb5_verify_checksum(context,
1872                                crypto,
1873                                KRB5_KU_TGS_REQ_AUTH_CKSUM,
1874                                buf, 
1875                                len,
1876                                auth->cksum);
1877     free(buf);
1878     krb5_crypto_destroy(context, crypto);
1879     if(ret){
1880         kdc_log(context, config, 0, "Failed to verify checksum: %s", 
1881                 krb5_get_err_text(context, ret));
1882     }
1883 out:
1884     free_Authenticator(auth);
1885     free(auth);
1886     return ret;
1887 }
1888
1889 /*
1890  * return the realm of a krbtgt-ticket or NULL
1891  */
1892
1893 static Realm 
1894 get_krbtgt_realm(const PrincipalName *p)
1895 {
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];
1899     else
1900         return NULL;
1901 }
1902
1903 static const char *
1904 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1905 {
1906     const char *new_realm = krb5_config_get_string(context,
1907                                                    NULL,
1908                                                    "capaths", 
1909                                                    crealm,
1910                                                    srealm,
1911                                                    NULL);
1912     return new_realm;
1913 }
1914             
1915
1916 static krb5_boolean
1917 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1918 {
1919     if(server->name.name_type != KRB5_NT_SRV_INST ||
1920        server->name.name_string.len != 2)
1921         return FALSE;
1922  
1923     return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1924                                     FALSE, realms) == 0;
1925 }
1926
1927 static krb5_error_code
1928 tgs_rep2(krb5_context context, 
1929          krb5_kdc_configuration *config,
1930          KDC_REQ_BODY *b,
1931          PA_DATA *tgs_req,
1932          krb5_data *reply,
1933          const char *from,
1934          const struct sockaddr *from_addr,
1935          time_t **csec,
1936          int **cusec)
1937 {
1938     krb5_ap_req ap_req;
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;
1946     krb5_crypto crypto;
1947
1948     hdb_entry *krbtgt = NULL;
1949     EncTicketPart *tgt;
1950     Key *tkey;
1951     krb5_enctype cetype;
1952     krb5_principal cp = NULL;
1953     krb5_principal sp = NULL;
1954     AuthorizationData *auth_data = NULL;
1955
1956     *csec  = NULL;
1957     *cusec = NULL;
1958
1959     memset(&ap_req, 0, sizeof(ap_req));
1960     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1961     if(ret){
1962         kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", 
1963                 krb5_get_err_text(context, ret));
1964         goto out2;
1965     }
1966     
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; /* ? */
1971         goto out2;
1972     }
1973     
1974     _krb5_principalname2krb5_principal(&princ,
1975                                        ap_req.ticket.sname,
1976                                        ap_req.ticket.realm);
1977     
1978     ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
1979
1980     if(ret) {
1981         char *p;
1982         ret = krb5_unparse_name(context, princ, &p);
1983         if (ret != 0)
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));
1989         if (ret == 0)
1990             free(p);
1991         ret = KRB5KRB_AP_ERR_NOT_US;
1992         goto out2;
1993     }
1994     
1995     if(ap_req.ticket.enc_part.kvno && 
1996        *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1997         char *p;
1998
1999         ret = krb5_unparse_name (context, princ, &p);
2000         krb5_free_principal(context, princ);
2001         if (ret != 0)
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,
2006                 krbtgt->kvno,
2007                 p);
2008         if (ret == 0)
2009             free (p);
2010         ret = KRB5KRB_AP_ERR_BADKEYVER;
2011         goto out2;
2012     }
2013
2014     ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2015     if(ret){
2016         char *str;
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);
2020         free(str);
2021         ret = KRB5KRB_AP_ERR_BADKEYVER;
2022         goto out2;
2023     }
2024     
2025     if (b->kdc_options.validate)
2026         verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2027     else
2028         verify_ap_req_flags = 0;
2029
2030     ret = krb5_verify_ap_req2(context,
2031                               &ac,
2032                               &ap_req,
2033                               princ,
2034                               &tkey->key,
2035                               verify_ap_req_flags,
2036                               &ap_req_options,
2037                               &ticket,
2038                               KRB5_KU_TGS_REQ_AUTH);
2039                              
2040     krb5_free_principal(context, princ);
2041     if(ret) {
2042         kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", 
2043                 krb5_get_err_text(context, ret));
2044         goto out2;
2045     }
2046
2047     {
2048         krb5_authenticator auth;
2049
2050         ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2051         if (ret == 0) {
2052             *csec   = malloc(sizeof(**csec));
2053             if (*csec == NULL) {
2054                 krb5_free_authenticator(context, &auth);
2055                 kdc_log(context, config, 0, "malloc failed");
2056                 goto out2;
2057             }
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");
2063                 goto out2;
2064             }
2065             **csec  = auth->cusec;
2066             krb5_free_authenticator(context, &auth);
2067         }
2068     }
2069
2070     cetype = ap_req.authenticator.etype;
2071
2072     tgt = &ticket->ticket;
2073
2074     ret = tgs_check_authenticator(context, config, 
2075                                   ac, b, &e_text, &tgt->key);
2076
2077     if (b->enc_authorization_data) {
2078         krb5_keyblock *subkey;
2079         krb5_data ad;
2080         ret = krb5_auth_con_getremotesubkey(context,
2081                                             ac,
2082                                             &subkey);
2083         if(ret){
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));
2087             goto out2;
2088         }
2089         if(subkey == NULL){
2090             ret = krb5_auth_con_getkey(context, ac, &subkey);
2091             if(ret) {
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));
2095                 goto out2;
2096             }
2097         }
2098         if(subkey == NULL){
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; /* ? */
2103             goto out2;
2104         }
2105         ret = krb5_crypto_init(context, subkey, 0, &crypto);
2106         if (ret) {
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));
2110             goto out2;
2111         }
2112         ret = krb5_decrypt_EncryptedData (context,
2113                                           crypto,
2114                                           KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2115                                           b->enc_authorization_data,
2116                                           &ad);
2117         krb5_crypto_destroy(context, crypto);
2118         if(ret){
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; /* ? */
2122             goto out2;
2123         }
2124         krb5_free_keyblock(context, subkey);
2125         ALLOC(auth_data);
2126         ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2127         if(ret){
2128             krb5_auth_con_free(context, ac);
2129             free(auth_data);
2130             auth_data = NULL;
2131             kdc_log(context, config, 0, "Failed to decode authorization data");
2132             ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2133             goto out2;
2134         }
2135     }
2136
2137     krb5_auth_con_free(context, ac);
2138
2139     if(ret){
2140         kdc_log(context, config, 0, "Failed to verify authenticator: %s", 
2141                 krb5_get_err_text(context, ret));
2142         goto out2;
2143     }
2144     
2145     {
2146         PrincipalName *s;
2147         Realm r;
2148         char *spn = NULL, *cpn = NULL;
2149         hdb_entry *server = NULL, *client = NULL;
2150         int nloop = 0;
2151         EncTicketPart adtkt;
2152         char opt_str[128];
2153
2154         s = b->sname;
2155         r = b->realm;
2156         if(b->kdc_options.enc_tkt_in_skey){
2157             Ticket *t;
2158             hdb_entry *uu;
2159             krb5_principal p;
2160             Key *uukey;
2161             
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");
2167                 goto out;
2168             }
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;
2174                 goto out2;
2175             }
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);
2179             if(ret){
2180                 if (ret == HDB_ERR_NOENTRY)
2181                     ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2182                 goto out;
2183             }
2184             ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2185             if(ret){
2186                 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2187                 goto out;
2188             }
2189             ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2190
2191             if(ret)
2192                 goto out;
2193             s = &adtkt.cname;
2194             r = adtkt.crealm;
2195         }
2196
2197         _krb5_principalname2krb5_principal(&sp, *s, r);
2198         ret = krb5_unparse_name(context, sp, &spn);     
2199         if (ret)
2200             goto out;
2201         _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2202         ret = krb5_unparse_name(context, cp, &cpn);
2203         if (ret)
2204             goto out;
2205         unparse_flags (KDCOptions2int(b->kdc_options),
2206                        asn1_KDCOptions_units(),
2207                        opt_str, sizeof(opt_str));
2208         if(*opt_str)
2209             kdc_log(context, config, 0,
2210                     "TGS-REQ %s from %s for %s [%s]", 
2211                     cpn, from, spn, opt_str);
2212         else
2213             kdc_log(context, config, 0,
2214                     "TGS-REQ %s from %s for %s", cpn, from, spn);
2215     server_lookup:
2216         ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2217
2218         if(ret){
2219             const char *new_rlm;
2220             Realm req_rlm;
2221             krb5_realm *realms;
2222
2223             if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2224                 if(nloop++ < 2) {
2225                     new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2226                     if(new_rlm) {
2227                         kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s", 
2228                                 req_rlm, new_rlm);
2229                         krb5_free_principal(context, sp);
2230                         free(spn);
2231                         krb5_make_principal(context, &sp, r, 
2232                                             KRB5_TGS_NAME, new_rlm, NULL);
2233                         ret = krb5_unparse_name(context, sp, &spn);     
2234                         if (ret)
2235                             goto out;
2236                         goto server_lookup;
2237                     }
2238                 }
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",
2244                             realms[0], spn);
2245                     krb5_free_principal(context, sp);
2246                     free(spn);
2247                     krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2248                                         realms[0], NULL);
2249                     ret = krb5_unparse_name(context, sp, &spn);
2250                     if (ret)
2251                         goto out;
2252                     krb5_free_host_realm(context, realms);
2253                     goto server_lookup;
2254                 }
2255                 krb5_free_host_realm(context, realms);
2256             }
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;
2262             goto out;
2263         }
2264
2265         ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2266         if(ret)
2267             kdc_log(context, config, 1, "Client not found in database: %s: %s",
2268                     cpn, krb5_get_err_text(context, ret));
2269 #if 0
2270         /* XXX check client only if same realm as krbtgt-instance */
2271         if(ret){
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;
2277             goto out;
2278         }
2279 #endif
2280
2281         if(strcmp(krb5_principal_get_realm(context, sp),
2282                   krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2283             char *tpn;
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>");
2288             if(ret == 0)
2289                 free(tpn);
2290             ret = KRB5KRB_AP_ERR_NOT_US;
2291             goto out;
2292             
2293         }
2294
2295         ret = _kdc_check_flags(context, config, 
2296                                client, cpn,
2297                                server, spn,
2298                                FALSE);
2299         if(ret)
2300             goto out;
2301
2302         if((b->kdc_options.validate || b->kdc_options.renew) && 
2303            !krb5_principal_compare(context, 
2304                                    krbtgt->principal,
2305                                    server->principal)){
2306             kdc_log(context, config, 0, "Inconsistent request.");
2307             ret = KRB5KDC_ERR_SERVER_NOMATCH;
2308             goto out;
2309         }
2310
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");
2315             goto out;
2316         }
2317         
2318         ret = tgs_make_reply(context, config, 
2319                              b, 
2320                              tgt, 
2321                              b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, 
2322                              auth_data,
2323                              server, 
2324                              client, 
2325                              cp, 
2326                              krbtgt, 
2327                              &tkey->key,
2328                              cetype, 
2329                              &e_text,
2330                              reply);
2331         
2332     out:
2333         free(spn);
2334         free(cpn);
2335             
2336         if(server)
2337             _kdc_free_ent(context, server);
2338         if(client)
2339             _kdc_free_ent(context, client);
2340     }
2341  out2:
2342     if(ret) {
2343         krb5_mk_error(context,
2344                       ret,
2345                       e_text,
2346                       NULL,
2347                       cp,
2348                       sp,
2349                       NULL,
2350                       NULL,
2351                       reply);
2352         free(*csec);
2353         free(*cusec);
2354         *csec  = NULL;
2355         *cusec = NULL;
2356     }
2357     krb5_free_principal(context, cp);
2358     krb5_free_principal(context, sp);
2359     if (ticket)
2360         krb5_free_ticket(context, ticket);
2361     free_AP_REQ(&ap_req);
2362     if(auth_data){
2363         free_AuthorizationData(auth_data);
2364         free(auth_data);
2365     }
2366
2367     if(krbtgt)
2368         _kdc_free_ent(context, krbtgt);
2369
2370     return ret;
2371 }
2372
2373
2374 krb5_error_code
2375 _kdc_tgs_rep(krb5_context context, 
2376              krb5_kdc_configuration *config,
2377              KDC_REQ *req, 
2378              krb5_data *data,
2379              const char *from,
2380              struct sockaddr *from_addr)
2381 {
2382     krb5_error_code ret;
2383     int i = 0;
2384     PA_DATA *tgs_req = NULL;
2385     time_t *csec = NULL;
2386     int *cusec = NULL;
2387
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);
2392         goto out;
2393     }
2394     
2395     tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2396
2397     if(tgs_req == NULL){
2398         ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2399         
2400         kdc_log(context, config, 0, 
2401                 "TGS-REQ from %s without PA-TGS-REQ", from);
2402         goto out;
2403     }
2404     ret = tgs_rep2(context, config, 
2405                    &req->req_body, tgs_req, data, from, from_addr,
2406                    &csec, &cusec);
2407 out:
2408     if(ret && data->data == NULL){
2409         krb5_mk_error(context,
2410                       ret,
2411                       NULL,
2412                       NULL,
2413                       NULL,
2414                       NULL,
2415                       csec,
2416                       cusec,
2417                       data);
2418     }
2419     free(csec);
2420     free(cusec);
2421     return 0;
2422 }