bb0fda89e7693b5b9672faa38327529d8df82566
[sfrench/samba-autobuild/.git] / source4 / heimdal / kdc / kerberos5.c
1 /*
2  * Copyright (c) 1997-2006 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
36 RCSID("$Id: kerberos5.c,v 1.231 2007/01/04 13:27:27 lha Exp $");
37
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39
40 void
41 _kdc_fix_time(time_t **t)
42 {
43     if(*t == NULL){
44         ALLOC(*t);
45         **t = MAX_TIME;
46     }
47     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
48 }
49
50 static int
51 realloc_method_data(METHOD_DATA *md)
52 {
53     PA_DATA *pa;
54     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
55     if(pa == NULL)
56         return ENOMEM;
57     md->val = pa;
58     md->len++;
59     return 0;
60 }
61
62 static void
63 set_salt_padata (METHOD_DATA *md, Salt *salt)
64 {
65     if (salt) {
66         realloc_method_data(md);
67         md->val[md->len - 1].padata_type = salt->type;
68         der_copy_octet_string(&salt->salt,
69                               &md->val[md->len - 1].padata_value);
70     }
71 }
72
73 PA_DATA*
74 _kdc_find_padata(KDC_REQ *req, int *start, int type)
75 {
76     while(*start < req->padata->len){
77         (*start)++;
78         if(req->padata->val[*start - 1].padata_type == type)
79             return &req->padata->val[*start - 1];
80     }
81     return NULL;
82 }
83
84 /*
85  * return the first appropriate key of `princ' in `ret_key'.  Look for
86  * all the etypes in (`etypes', `len'), stopping as soon as we find
87  * one, but preferring one that has default salt
88  */
89
90 krb5_error_code
91 _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ,
92                 krb5_enctype *etypes, unsigned len, 
93                 Key **ret_key, krb5_enctype *ret_etype)
94 {
95     int i;
96     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
97
98     for(i = 0; ret != 0 && i < len ; i++) {
99         Key *key = NULL;
100
101         if (krb5_enctype_valid(context, etypes[i]) != 0)
102             continue;
103
104         while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
105             if (key->key.keyvalue.length == 0) {
106                 ret = KRB5KDC_ERR_NULL_KEY;
107                 continue;
108             }
109             *ret_key   = key;
110             *ret_etype = etypes[i];
111             ret = 0;
112             if (key->salt == NULL)
113                 return ret;
114         }
115     }
116     return ret;
117 }
118
119 krb5_error_code
120 _kdc_make_anonymous_principalname (PrincipalName *pn)
121 {
122     pn->name_type = KRB5_NT_PRINCIPAL;
123     pn->name_string.len = 1;
124     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
125     if (pn->name_string.val == NULL)
126         return ENOMEM;
127     pn->name_string.val[0] = strdup("anonymous");
128     if (pn->name_string.val[0] == NULL) {
129         free(pn->name_string.val);
130         pn->name_string.val = NULL;
131         return ENOMEM;
132     }
133     return 0;
134 }
135
136 void
137 _kdc_log_timestamp(krb5_context context, 
138                    krb5_kdc_configuration *config,
139                    const char *type,
140                    KerberosTime authtime, KerberosTime *starttime, 
141                    KerberosTime endtime, KerberosTime *renew_till)
142 {
143     char authtime_str[100], starttime_str[100], 
144         endtime_str[100], renewtime_str[100];
145     
146     krb5_format_time(context, authtime, 
147                      authtime_str, sizeof(authtime_str), TRUE); 
148     if (starttime)
149         krb5_format_time(context, *starttime, 
150                          starttime_str, sizeof(starttime_str), TRUE); 
151     else
152         strlcpy(starttime_str, "unset", sizeof(starttime_str));
153     krb5_format_time(context, endtime, 
154                      endtime_str, sizeof(endtime_str), TRUE); 
155     if (renew_till)
156         krb5_format_time(context, *renew_till, 
157                          renewtime_str, sizeof(renewtime_str), TRUE); 
158     else
159         strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
160     
161     kdc_log(context, config, 5,
162             "%s authtime: %s starttime: %s endtime: %s renew till: %s",
163             type, authtime_str, starttime_str, endtime_str, renewtime_str);
164 }
165
166 static void
167 log_patypes(krb5_context context, 
168             krb5_kdc_configuration *config,
169             METHOD_DATA *padata)
170 {
171     struct rk_strpool *p = NULL;
172     char *str;
173     int i;
174             
175     for (i = 0; i < padata->len; i++) {
176         switch(padata->val[i].padata_type) {
177         case KRB5_PADATA_PK_AS_REQ:
178             p = rk_strpoolprintf(p, "PK-INIT(ietf)");
179             break;
180         case KRB5_PADATA_PK_AS_REQ_WIN:
181             p = rk_strpoolprintf(p, "PK-INIT(win2k)");
182             break;
183         case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
184             p = rk_strpoolprintf(p, "OCSP");
185             break;
186         case KRB5_PADATA_ENC_TIMESTAMP:
187             p = rk_strpoolprintf(p, "encrypted-timestamp");
188             break;
189         default:
190             p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
191             break;
192         }
193         if (p && i + 1 < padata->len)
194             p = rk_strpoolprintf(p, ", ");
195         if (p == NULL) {
196             kdc_log(context, config, 0, "out of memory");
197             return;
198         }
199     }
200     if (p == NULL)
201         p = rk_strpoolprintf(p, "none");
202         
203     str = rk_strpoolcollect(p);
204     kdc_log(context, config, 0, "Client sent patypes: %s", str);
205     free(str);
206 }
207
208 /*
209  *
210  */
211
212
213 krb5_error_code
214 _kdc_encode_reply(krb5_context context,
215                   krb5_kdc_configuration *config,
216                   KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, 
217                   krb5_enctype etype, 
218                   int skvno, const EncryptionKey *skey,
219                   int ckvno, const EncryptionKey *ckey,
220                   const char **e_text,
221                   krb5_data *reply)
222 {
223     unsigned char *buf;
224     size_t buf_size;
225     size_t len;
226     krb5_error_code ret;
227     krb5_crypto crypto;
228
229     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
230     if(ret) {
231         kdc_log(context, config, 0, "Failed to encode ticket: %s", 
232                 krb5_get_err_text(context, ret));
233         return ret;
234     }
235     if(buf_size != len) {
236         free(buf);
237         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
238         *e_text = "KDC internal error";
239         return KRB5KRB_ERR_GENERIC;
240     }
241
242     ret = krb5_crypto_init(context, skey, etype, &crypto);
243     if (ret) {
244         free(buf);
245         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
246                 krb5_get_err_text(context, ret));
247         return ret;
248     }
249
250     ret = krb5_encrypt_EncryptedData(context, 
251                                      crypto,
252                                      KRB5_KU_TICKET,
253                                      buf,
254                                      len,
255                                      skvno,
256                                      &rep->ticket.enc_part);
257     free(buf);
258     krb5_crypto_destroy(context, crypto);
259     if(ret) {
260         kdc_log(context, config, 0, "Failed to encrypt data: %s",
261                 krb5_get_err_text(context, ret));
262         return ret;
263     }
264     
265     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
266         ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
267     else
268         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
269     if(ret) {
270         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
271                 krb5_get_err_text(context, ret));
272         return ret;
273     }
274     if(buf_size != len) {
275         free(buf);
276         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
277         *e_text = "KDC internal error";
278         return KRB5KRB_ERR_GENERIC;
279     }
280     ret = krb5_crypto_init(context, ckey, 0, &crypto);
281     if (ret) {
282         free(buf);
283         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
284                 krb5_get_err_text(context, ret));
285         return ret;
286     }
287     if(rep->msg_type == krb_as_rep) {
288         krb5_encrypt_EncryptedData(context,
289                                    crypto,
290                                    KRB5_KU_AS_REP_ENC_PART,
291                                    buf,
292                                    len,
293                                    ckvno,
294                                    &rep->enc_part);
295         free(buf);
296         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
297     } else {
298         krb5_encrypt_EncryptedData(context,
299                                    crypto,
300                                    KRB5_KU_TGS_REP_ENC_PART_SESSION,
301                                    buf,
302                                    len,
303                                    ckvno,
304                                    &rep->enc_part);
305         free(buf);
306         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
307     }
308     krb5_crypto_destroy(context, crypto);
309     if(ret) {
310         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
311                 krb5_get_err_text(context, ret));
312         return ret;
313     }
314     if(buf_size != len) {
315         free(buf);
316         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
317         *e_text = "KDC internal error";
318         return KRB5KRB_ERR_GENERIC;
319     }
320     reply->data = buf;
321     reply->length = buf_size;
322     return 0;
323 }
324
325 static krb5_error_code
326 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
327 {
328     ent->etype = key->key.keytype;
329     if(key->salt){
330 #if 0
331         ALLOC(ent->salttype);
332
333         if(key->salt->type == hdb_pw_salt)
334             *ent->salttype = 0; /* or 1? or NULL? */
335         else if(key->salt->type == hdb_afs3_salt)
336             *ent->salttype = 2;
337         else {
338             kdc_log(context, config, 0, "unknown salt-type: %d", 
339                     key->salt->type);
340             return KRB5KRB_ERR_GENERIC;
341         }
342         /* according to `the specs', we can't send a salt if
343            we have AFS3 salted key, but that requires that you
344            *know* what cell you are using (e.g by assuming
345            that the cell is the same as the realm in lower
346            case) */
347 #elif 0
348         ALLOC(ent->salttype);
349         *ent->salttype = key->salt->type;
350 #else
351         /* 
352          * We shouldn't sent salttype since its incompatible with the
353          * specification and its break windows clients.  The afs
354          * salting problem is solved by using KRB5-PADATA-AFS3-SALT
355          * implemented in Heimdal 0.7 and later.
356          */
357         ent->salttype = NULL;
358 #endif
359         krb5_copy_data(context, &key->salt->salt,
360                        &ent->salt);
361     } else {
362         /* we return no salt type at all, as that should indicate
363          * the default salt type and make everybody happy.  some
364          * systems (like w2k) dislike being told the salt type
365          * here. */
366
367         ent->salttype = NULL;
368         ent->salt = NULL;
369     }
370     return 0;
371 }
372
373 static krb5_error_code
374 get_pa_etype_info(krb5_context context, 
375                   krb5_kdc_configuration *config,
376                   METHOD_DATA *md, hdb_entry *client, 
377                   ENCTYPE *etypes, unsigned int etypes_len)
378 {
379     krb5_error_code ret = 0;
380     int i, j;
381     unsigned int n = 0;
382     ETYPE_INFO pa;
383     unsigned char *buf;
384     size_t len;
385     
386
387     pa.len = client->keys.len;
388     if(pa.len > UINT_MAX/sizeof(*pa.val))
389         return ERANGE;
390     pa.val = malloc(pa.len * sizeof(*pa.val));
391     if(pa.val == NULL)
392         return ENOMEM;
393     memset(pa.val, 0, pa.len * sizeof(*pa.val));
394
395     for(j = 0; j < etypes_len; j++) {
396         for (i = 0; i < n; i++)
397             if (pa.val[i].etype == etypes[j])
398                 goto skip1;
399         for(i = 0; i < client->keys.len; i++) {
400             if(client->keys.val[i].key.keytype == etypes[j]) {
401                 if (krb5_enctype_valid(context, etypes[j]) != 0)
402                     continue;
403                 if((ret = make_etype_info_entry(context, 
404                                                 &pa.val[n++], 
405                                                 &client->keys.val[i])) != 0) {
406                     free_ETYPE_INFO(&pa);
407                     return ret;
408                 }
409             }
410         }
411     skip1:;
412     }
413     for(i = 0; i < client->keys.len; i++) {
414         for(j = 0; j < etypes_len; j++) {
415             if(client->keys.val[i].key.keytype == etypes[j])
416                 goto skip2;
417         }
418         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
419             continue;
420         if((ret = make_etype_info_entry(context, 
421                                         &pa.val[n++], 
422                                         &client->keys.val[i])) != 0) {
423             free_ETYPE_INFO(&pa);
424             return ret;
425         }
426     skip2:;
427     }
428     
429     if(n != pa.len) {
430         char *name;
431         ret = krb5_unparse_name(context, client->principal, &name);
432         if (ret)
433             name = rk_UNCONST("<unparse_name failed>");
434         kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d", 
435                 name, n, pa.len);
436         if (ret == 0)
437             free(name);
438         pa.len = n;
439     }
440
441     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
442     free_ETYPE_INFO(&pa);
443     if(ret)
444         return ret;
445     ret = realloc_method_data(md);
446     if(ret) {
447         free(buf);
448         return ret;
449     }
450     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
451     md->val[md->len - 1].padata_value.length = len;
452     md->val[md->len - 1].padata_value.data = buf;
453     return 0;
454 }
455
456 /*
457  *
458  */
459
460 extern int _krb5_AES_string_to_default_iterator;
461
462 static krb5_error_code
463 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
464 {
465     ent->etype = key->key.keytype;
466     if(key->salt) {
467         ALLOC(ent->salt);
468         if (ent->salt == NULL)
469             return ENOMEM;
470         *ent->salt = malloc(key->salt->salt.length + 1);
471         if (*ent->salt == NULL) {
472             free(ent->salt);
473             ent->salt = NULL;
474             return ENOMEM;
475         }
476         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
477         (*ent->salt)[key->salt->salt.length] = '\0';
478     } else
479         ent->salt = NULL;
480
481     ent->s2kparams = NULL;
482
483     switch (key->key.keytype) {
484     case ETYPE_AES128_CTS_HMAC_SHA1_96:
485     case ETYPE_AES256_CTS_HMAC_SHA1_96:
486         ALLOC(ent->s2kparams);
487         if (ent->s2kparams == NULL)
488             return ENOMEM;
489         ent->s2kparams->length = 4;
490         ent->s2kparams->data = malloc(ent->s2kparams->length);
491         if (ent->s2kparams->data == NULL) {
492             free(ent->s2kparams);
493             ent->s2kparams = NULL;
494             return ENOMEM;
495         }
496         _krb5_put_int(ent->s2kparams->data, 
497                       _krb5_AES_string_to_default_iterator, 
498                       ent->s2kparams->length);
499         break;
500     case ETYPE_DES_CBC_CRC:
501     case ETYPE_DES_CBC_MD4:
502     case ETYPE_DES_CBC_MD5:
503         /* Check if this was a AFS3 salted key */
504         if(key->salt && key->salt->type == hdb_afs3_salt){
505             ALLOC(ent->s2kparams);
506             if (ent->s2kparams == NULL)
507                 return ENOMEM;
508             ent->s2kparams->length = 1;
509             ent->s2kparams->data = malloc(ent->s2kparams->length);
510             if (ent->s2kparams->data == NULL) {
511                 free(ent->s2kparams);
512                 ent->s2kparams = NULL;
513                 return ENOMEM;
514             }
515             _krb5_put_int(ent->s2kparams->data, 
516                           1,
517                           ent->s2kparams->length);
518         }
519         break;
520     default:
521         break;
522     }
523     return 0;
524 }
525
526 /*
527  * Return 1 if the client have only older enctypes, this is for
528  * determining if the server should send ETYPE_INFO2 or not.
529  */
530
531 static int
532 only_older_enctype_p(const KDC_REQ *req)
533 {
534     int i;
535
536     for(i = 0; i < req->req_body.etype.len; i++) {
537         switch (req->req_body.etype.val[i]) {
538         case ETYPE_DES_CBC_CRC:
539         case ETYPE_DES_CBC_MD4:
540         case ETYPE_DES_CBC_MD5:
541         case ETYPE_DES3_CBC_SHA1:
542         case ETYPE_ARCFOUR_HMAC_MD5:
543         case ETYPE_ARCFOUR_HMAC_MD5_56:
544             break;
545         default:
546             return 0;
547         }
548     }
549     return 1;
550 }
551
552 /*
553  *
554  */
555
556 static krb5_error_code
557 get_pa_etype_info2(krb5_context context, 
558                    krb5_kdc_configuration *config,
559                    METHOD_DATA *md, hdb_entry *client, 
560                    ENCTYPE *etypes, unsigned int etypes_len)
561 {
562     krb5_error_code ret = 0;
563     int i, j;
564     unsigned int n = 0;
565     ETYPE_INFO2 pa;
566     unsigned char *buf;
567     size_t len;
568
569     pa.len = client->keys.len;
570     if(pa.len > UINT_MAX/sizeof(*pa.val))
571         return ERANGE;
572     pa.val = malloc(pa.len * sizeof(*pa.val));
573     if(pa.val == NULL)
574         return ENOMEM;
575     memset(pa.val, 0, pa.len * sizeof(*pa.val));
576
577     for(j = 0; j < etypes_len; j++) {
578         for (i = 0; i < n; i++)
579             if (pa.val[i].etype == etypes[j])
580                 goto skip1;
581         for(i = 0; i < client->keys.len; i++) {
582             if(client->keys.val[i].key.keytype == etypes[j]) {
583                 if (krb5_enctype_valid(context, etypes[j]) != 0)
584                     continue;
585                 if((ret = make_etype_info2_entry(&pa.val[n++], 
586                                                  &client->keys.val[i])) != 0) {
587                     free_ETYPE_INFO2(&pa);
588                     return ret;
589                 }
590             }
591         }
592     skip1:;
593     }
594     for(i = 0; i < client->keys.len; i++) {
595         for(j = 0; j < etypes_len; j++) {
596             if(client->keys.val[i].key.keytype == etypes[j])
597                 goto skip2;
598         }
599         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
600             continue;
601         if((ret = make_etype_info2_entry(&pa.val[n++],
602                                          &client->keys.val[i])) != 0) {
603             free_ETYPE_INFO2(&pa);
604             return ret;
605         }
606       skip2:;
607     }
608     
609     if(n != pa.len) {
610         char *name;
611         ret = krb5_unparse_name(context, client->principal, &name);
612         if (ret)
613             name = rk_UNCONST("<unparse_name failed>");
614         kdc_log(context, config, 0,
615                 "internal error in get_pa_etype_info2(%s): %d != %d", 
616                 name, n, pa.len);
617         if (ret == 0)
618             free(name);
619         pa.len = n;
620     }
621
622     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
623     free_ETYPE_INFO2(&pa);
624     if(ret)
625         return ret;
626     ret = realloc_method_data(md);
627     if(ret) {
628         free(buf);
629         return ret;
630     }
631     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
632     md->val[md->len - 1].padata_value.length = len;
633     md->val[md->len - 1].padata_value.data = buf;
634     return 0;
635 }
636
637 /*
638  *
639  */
640
641 static void
642 log_as_req(krb5_context context,
643            krb5_kdc_configuration *config,
644            krb5_enctype cetype,
645            krb5_enctype setype,
646            const KDC_REQ_BODY *b)
647 {
648     krb5_error_code ret;
649     struct rk_strpool *p = NULL;
650     char *str;
651     int i;
652     
653     for (i = 0; i < b->etype.len; i++) {
654         ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
655         if (ret == 0) {
656             p = rk_strpoolprintf(p, "%s", str);
657             free(str);
658         } else
659             p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
660         if (p && i + 1 < b->etype.len)
661             p = rk_strpoolprintf(p, ", ");
662         if (p == NULL) {
663             kdc_log(context, config, 0, "out of memory");
664             return;
665         }
666     }
667     if (p == NULL)
668         p = rk_strpoolprintf(p, "no encryption types");
669     
670     str = rk_strpoolcollect(p);
671     kdc_log(context, config, 0, "Client supported enctypes: %s", str);
672     free(str);
673
674     {
675         char *cet;
676         char *set;
677
678         ret = krb5_enctype_to_string(context, cetype, &cet);
679         if(ret == 0) {
680             ret = krb5_enctype_to_string(context, setype, &set);
681             if (ret == 0) {
682                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
683                 free(set);
684             }
685             free(cet);
686         }
687         if (ret != 0)
688             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
689     }
690     
691     {
692         char _str[128];
693         unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(), 
694                       _str, sizeof(_str));
695         if(*_str)
696             kdc_log(context, config, 2, "Requested flags: %s", _str);
697     }
698 }
699
700 /*
701  * verify the flags on `client' and `server', returning 0
702  * if they are OK and generating an error messages and returning
703  * and error code otherwise.
704  */
705
706 krb5_error_code
707 _kdc_check_flags(krb5_context context, 
708                  krb5_kdc_configuration *config,
709                  hdb_entry_ex *client_ex, const char *client_name,
710                  hdb_entry_ex *server_ex, const char *server_name,
711                  krb5_boolean is_as_req)
712 {
713     if(client_ex != NULL) {
714         hdb_entry *client = &client_ex->entry;
715
716         /* check client */
717         if (client->flags.invalid) {
718             kdc_log(context, config, 0, 
719                     "Client (%s) has invalid bit set", client_name);
720             return KRB5KDC_ERR_POLICY;
721         }
722         
723         if(!client->flags.client){
724             kdc_log(context, config, 0,
725                     "Principal may not act as client -- %s", client_name);
726             return KRB5KDC_ERR_POLICY;
727         }
728         
729         if (client->valid_start && *client->valid_start > kdc_time) {
730             char starttime_str[100];
731             krb5_format_time(context, *client->valid_start, 
732                              starttime_str, sizeof(starttime_str), TRUE); 
733             kdc_log(context, config, 0,
734                     "Client not yet valid until %s -- %s", 
735                     starttime_str, client_name);
736             return KRB5KDC_ERR_CLIENT_NOTYET;
737         }
738         
739         if (client->valid_end && *client->valid_end < kdc_time) {
740             char endtime_str[100];
741             krb5_format_time(context, *client->valid_end, 
742                              endtime_str, sizeof(endtime_str), TRUE); 
743             kdc_log(context, config, 0,
744                     "Client expired at %s -- %s",
745                     endtime_str, client_name);
746             return KRB5KDC_ERR_NAME_EXP;
747         }
748         
749         if (client->pw_end && *client->pw_end < kdc_time 
750             && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
751             char pwend_str[100];
752             krb5_format_time(context, *client->pw_end, 
753                              pwend_str, sizeof(pwend_str), TRUE); 
754             kdc_log(context, config, 0,
755                     "Client's key has expired at %s -- %s", 
756                     pwend_str, client_name);
757             return KRB5KDC_ERR_KEY_EXPIRED;
758         }
759     }
760
761     /* check server */
762     
763     if (server_ex != NULL) {
764         hdb_entry *server = &server_ex->entry;
765
766         if (server->flags.invalid) {
767             kdc_log(context, config, 0,
768                     "Server has invalid flag set -- %s", server_name);
769             return KRB5KDC_ERR_POLICY;
770         }
771
772         if(!server->flags.server){
773             kdc_log(context, config, 0,
774                     "Principal may not act as server -- %s", server_name);
775             return KRB5KDC_ERR_POLICY;
776         }
777
778         if(!is_as_req && server->flags.initial) {
779             kdc_log(context, config, 0,
780                     "AS-REQ is required for server -- %s", server_name);
781             return KRB5KDC_ERR_POLICY;
782         }
783
784         if (server->valid_start && *server->valid_start > kdc_time) {
785             char starttime_str[100];
786             krb5_format_time(context, *server->valid_start, 
787                              starttime_str, sizeof(starttime_str), TRUE); 
788             kdc_log(context, config, 0,
789                     "Server not yet valid until %s -- %s",
790                     starttime_str, server_name);
791             return KRB5KDC_ERR_SERVICE_NOTYET;
792         }
793
794         if (server->valid_end && *server->valid_end < kdc_time) {
795             char endtime_str[100];
796             krb5_format_time(context, *server->valid_end, 
797                              endtime_str, sizeof(endtime_str), TRUE); 
798             kdc_log(context, config, 0,
799                     "Server expired at %s -- %s", 
800                     endtime_str, server_name);
801             return KRB5KDC_ERR_SERVICE_EXP;
802         }
803
804         if (server->pw_end && *server->pw_end < kdc_time) {
805             char pwend_str[100];
806             krb5_format_time(context, *server->pw_end, 
807                              pwend_str, sizeof(pwend_str), TRUE); 
808             kdc_log(context, config, 0,
809                     "Server's key has expired at -- %s", 
810                     pwend_str, server_name);
811             return KRB5KDC_ERR_KEY_EXPIRED;
812         }
813     }
814     return 0;
815 }
816
817 /*
818  * Return TRUE if `from' is part of `addresses' taking into consideration
819  * the configuration variables that tells us how strict we should be about
820  * these checks
821  */
822
823 krb5_boolean
824 _kdc_check_addresses(krb5_context context,        
825                      krb5_kdc_configuration *config,
826                      HostAddresses *addresses, const struct sockaddr *from)
827 {
828     krb5_error_code ret;
829     krb5_address addr;
830     krb5_boolean result;
831     krb5_boolean only_netbios = TRUE;
832     int i;
833     
834     if(config->check_ticket_addresses == 0)
835         return TRUE;
836
837     if(addresses == NULL)
838         return config->allow_null_ticket_addresses;
839     
840     for (i = 0; i < addresses->len; ++i) {
841         if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
842             only_netbios = FALSE;
843         }
844     }
845
846     /* Windows sends it's netbios name, which I can only assume is
847      * used for the 'allowed workstations' check.  This is painful,
848      * but we still want to check IP addresses if they happen to be
849      * present.
850      */
851
852     if(only_netbios)
853         return config->allow_null_ticket_addresses;
854
855     ret = krb5_sockaddr2address (context, from, &addr);
856     if(ret)
857         return FALSE;
858
859     result = krb5_address_search(context, &addr, addresses);
860     krb5_free_address (context, &addr);
861     return result;
862 }
863
864 /*
865  *
866  */
867
868 static krb5_boolean
869 send_pac_p(krb5_context context, KDC_REQ *req)
870 {
871     krb5_error_code ret;
872     PA_PAC_REQUEST pacreq;
873     PA_DATA *pa;
874     int i = 0;
875     
876     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
877     if (pa == NULL)
878         return TRUE;
879
880     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
881                                 pa->padata_value.length,
882                                 &pacreq,
883                                 NULL);
884     if (ret)
885         return TRUE;
886     i = pacreq.include_pac;
887     free_PA_PAC_REQUEST(&pacreq);
888     if (i == 0)
889         return FALSE;
890     return TRUE;
891 }
892
893 /*
894  *
895  */
896
897 krb5_error_code
898 _kdc_as_rep(krb5_context context, 
899             krb5_kdc_configuration *config,
900             KDC_REQ *req, 
901             const krb5_data *req_buffer, 
902             krb5_data *reply,
903             const char *from,
904             struct sockaddr *from_addr,
905             int datagram_reply)
906 {
907     KDC_REQ_BODY *b = &req->req_body;
908     AS_REP rep;
909     KDCOptions f = b->kdc_options;
910     hdb_entry_ex *client = NULL, *server = NULL;
911     krb5_enctype cetype, setype, sessionetype;
912     EncTicketPart et;
913     EncKDCRepPart ek;
914     krb5_principal client_princ = NULL, server_princ = NULL;
915     char *client_name = NULL, *server_name = NULL;
916     krb5_error_code ret = 0;
917     const char *e_text = NULL;
918     krb5_data e_data;
919     krb5_crypto crypto;
920     Key *ckey, *skey;
921     EncryptionKey *reply_key;
922 #ifdef PKINIT
923     pk_client_params *pkp = NULL;
924 #endif
925
926     memset(&rep, 0, sizeof(rep));
927     memset(&e_data, 0, sizeof(e_data));
928
929     if(b->sname == NULL){
930         ret = KRB5KRB_ERR_GENERIC;
931         e_text = "No server in request";
932     } else{
933         _krb5_principalname2krb5_principal (context,
934                                             &server_princ,
935                                             *(b->sname),
936                                             b->realm);
937         ret = krb5_unparse_name(context, server_princ, &server_name);
938     }
939     if (ret) {
940         kdc_log(context, config, 0, 
941                 "AS-REQ malformed server name from %s", from);
942         goto out;
943     }
944     
945     if(b->cname == NULL){
946         ret = KRB5KRB_ERR_GENERIC;
947         e_text = "No client in request";
948     } else {
949         _krb5_principalname2krb5_principal (context,
950                                             &client_princ,
951                                             *(b->cname),
952                                             b->realm);
953         ret = krb5_unparse_name(context, client_princ, &client_name);
954     }
955     if (ret) {
956         kdc_log(context, config, 0,
957                 "AS-REQ malformed client name from %s", from);
958         goto out;
959     }
960
961     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
962             client_name, from, server_name);
963
964     ret = _kdc_db_fetch(context, config, client_princ, 
965                         HDB_F_GET_CLIENT, NULL, &client);
966     if(ret){
967         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
968                 krb5_get_err_text(context, ret));
969         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
970         goto out;
971     }
972
973     ret = _kdc_db_fetch(context, config, server_princ,
974                         HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
975                         NULL, &server);
976     if(ret){
977         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
978                 krb5_get_err_text(context, ret));
979         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
980         goto out;
981     }
982
983     ret = _kdc_windc_client_access(context, client, req);
984     if(ret)
985         goto out;
986
987     ret = _kdc_check_flags(context, config, 
988                            client, client_name,
989                            server, server_name,
990                            TRUE);
991     if(ret)
992         goto out;
993
994     memset(&et, 0, sizeof(et));
995     memset(&ek, 0, sizeof(ek));
996
997     if(req->padata){
998         int i;
999         PA_DATA *pa;
1000         int found_pa = 0;
1001
1002         log_patypes(context, config, req->padata);
1003
1004 #ifdef PKINIT
1005         kdc_log(context, config, 5, 
1006                 "Looking for PKINIT pa-data -- %s", client_name);
1007
1008         e_text = "No PKINIT PA found";
1009
1010         i = 0;
1011         if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
1012             ;
1013         if (pa == NULL) {
1014             i = 0;
1015             if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
1016                 ;
1017         }
1018         if (pa) {
1019             char *client_cert = NULL;
1020
1021             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
1022             if (ret) {
1023                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1024                 kdc_log(context, config, 5, 
1025                         "Failed to decode PKINIT PA-DATA -- %s", 
1026                         client_name);
1027                 goto ts_enc;
1028             }
1029             if (ret == 0 && pkp == NULL)
1030                 goto ts_enc;
1031
1032             ret = _kdc_pk_check_client(context,
1033                                        config,
1034                                        client,
1035                                        pkp,
1036                                        &client_cert);
1037             if (ret) {
1038                 e_text = "PKINIT certificate not allowed to "
1039                     "impersonate principal";
1040                 _kdc_pk_free_client_param(context, pkp);
1041
1042                 kdc_log(context, config, 0, "%s", e_text);
1043                 pkp = NULL;
1044                 goto ts_enc;
1045             }
1046             found_pa = 1;
1047             et.flags.pre_authent = 1;
1048             kdc_log(context, config, 0,
1049                     "PKINIT pre-authentication succeeded -- %s using %s", 
1050                     client_name, client_cert);
1051             free(client_cert);
1052             if (pkp)
1053                 goto preauth_done;
1054         }
1055     ts_enc:
1056 #endif
1057         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
1058                 client_name);
1059
1060         i = 0;
1061         e_text = "No ENC-TS found";
1062         while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1063             krb5_data ts_data;
1064             PA_ENC_TS_ENC p;
1065             size_t len;
1066             EncryptedData enc_data;
1067             Key *pa_key;
1068             char *str;
1069             
1070             found_pa = 1;
1071             
1072             ret = decode_EncryptedData(pa->padata_value.data,
1073                                        pa->padata_value.length,
1074                                        &enc_data,
1075                                        &len);
1076             if (ret) {
1077                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1078                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
1079                         client_name);
1080                 goto out;
1081             }
1082             
1083             ret = hdb_enctype2key(context, &client->entry, 
1084                                   enc_data.etype, &pa_key);
1085             if(ret){
1086                 char *estr;
1087                 e_text = "No key matches pa-data";
1088                 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1089                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1090                     estr = NULL;
1091                 if(estr == NULL)
1092                     kdc_log(context, config, 5, 
1093                             "No client key matching pa-data (%d) -- %s", 
1094                             enc_data.etype, client_name);
1095                 else
1096                     kdc_log(context, config, 5,
1097                             "No client key matching pa-data (%s) -- %s", 
1098                             estr, client_name);
1099                 free(estr);
1100                     
1101                 free_EncryptedData(&enc_data);
1102                 continue;
1103             }
1104
1105         try_next_key:
1106             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1107             if (ret) {
1108                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1109                         krb5_get_err_text(context, ret));
1110                 free_EncryptedData(&enc_data);
1111                 continue;
1112             }
1113
1114             ret = krb5_decrypt_EncryptedData (context,
1115                                               crypto,
1116                                               KRB5_KU_PA_ENC_TIMESTAMP,
1117                                               &enc_data,
1118                                               &ts_data);
1119             krb5_crypto_destroy(context, crypto);
1120             if(ret){
1121                 krb5_error_code ret2;
1122                 ret2 = krb5_enctype_to_string(context, 
1123                                               pa_key->key.keytype, &str);
1124                 if (ret2)
1125                     str = NULL;
1126                 kdc_log(context, config, 5, 
1127                         "Failed to decrypt PA-DATA -- %s "
1128                         "(enctype %s) error %s",
1129                         client_name,
1130                         str ? str : "unknown enctype", 
1131                         krb5_get_err_text(context, ret));
1132                 free(str);
1133
1134                 if(hdb_next_enctype2key(context, &client->entry, 
1135                                         enc_data.etype, &pa_key) == 0)
1136                     goto try_next_key;
1137                 e_text = "Failed to decrypt PA-DATA";
1138
1139                 free_EncryptedData(&enc_data);
1140                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1141                 continue;
1142             }
1143             free_EncryptedData(&enc_data);
1144             ret = decode_PA_ENC_TS_ENC(ts_data.data,
1145                                        ts_data.length,
1146                                        &p,
1147                                        &len);
1148             krb5_data_free(&ts_data);
1149             if(ret){
1150                 e_text = "Failed to decode PA-ENC-TS-ENC";
1151                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1152                 kdc_log(context, config, 
1153                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
1154                         client_name);
1155                 continue;
1156             }
1157             free_PA_ENC_TS_ENC(&p);
1158             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1159                 char client_time[100];
1160                 
1161                 krb5_format_time(context, p.patimestamp, 
1162                                  client_time, sizeof(client_time), TRUE); 
1163
1164                 ret = KRB5KRB_AP_ERR_SKEW;
1165                 kdc_log(context, config, 0,
1166                         "Too large time skew, "
1167                         "client time %s is out by %u > %u seconds -- %s", 
1168                         client_time, 
1169                         (unsigned)abs(kdc_time - p.patimestamp), 
1170                         context->max_skew,
1171                         client_name);
1172                 /* 
1173                  * the following is needed to make windows clients
1174                  * to retry using the timestamp in the error message
1175                  *
1176                  * this is maybe a bug in windows to not trying when e_text
1177                  * is present...
1178                  */
1179                 e_text = NULL;
1180                 goto out;
1181             }
1182             et.flags.pre_authent = 1;
1183
1184             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1185             if (ret)
1186                 str = NULL;
1187
1188             kdc_log(context, config, 2,
1189                     "ENC-TS Pre-authentication succeeded -- %s using %s", 
1190                     client_name, str ? str : "unknown enctype");
1191             free(str);
1192             break;
1193         }
1194 #ifdef PKINIT
1195     preauth_done:
1196 #endif
1197         if(found_pa == 0 && config->require_preauth)
1198             goto use_pa;
1199         /* We come here if we found a pa-enc-timestamp, but if there
1200            was some problem with it, other than too large skew */
1201         if(found_pa && et.flags.pre_authent == 0){
1202             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1203             e_text = NULL;
1204             goto out;
1205         }
1206     }else if (config->require_preauth
1207               || client->entry.flags.require_preauth
1208               || server->entry.flags.require_preauth) {
1209         METHOD_DATA method_data;
1210         PA_DATA *pa;
1211         unsigned char *buf;
1212         size_t len;
1213
1214     use_pa: 
1215         method_data.len = 0;
1216         method_data.val = NULL;
1217
1218         ret = realloc_method_data(&method_data);
1219         pa = &method_data.val[method_data.len-1];
1220         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1221         pa->padata_value.length = 0;
1222         pa->padata_value.data   = NULL;
1223
1224 #ifdef PKINIT
1225         ret = realloc_method_data(&method_data);
1226         pa = &method_data.val[method_data.len-1];
1227         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1228         pa->padata_value.length = 0;
1229         pa->padata_value.data   = NULL;
1230 #endif
1231
1232         /* 
1233          * RFC4120 requires: 
1234          * - If the client only knows about old enctypes, then send
1235          *   both info replies (we send 'info' first in the list).
1236          * - If the client is 'modern', because it knows about 'new'
1237          *   enctype types, then only send the 'info2' reply.
1238          */
1239
1240         /* XXX check ret */
1241         if (only_older_enctype_p(req))
1242             ret = get_pa_etype_info(context, config,
1243                                     &method_data, &client->entry, 
1244                                     b->etype.val, b->etype.len); 
1245         /* XXX check ret */
1246         ret = get_pa_etype_info2(context, config, &method_data, 
1247                                  &client->entry, b->etype.val, b->etype.len);
1248
1249         
1250         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1251         free_METHOD_DATA(&method_data);
1252
1253         e_data.data   = buf;
1254         e_data.length = len;
1255         e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1256         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1257
1258         kdc_log(context, config, 0,
1259                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1260                 client_name);
1261
1262         goto out;
1263     }
1264     
1265     /*
1266      * Find the client key (for preauth ENC-TS verification and reply
1267      * encryption).  Then the best encryption type for the KDC and
1268      * last the best session key that shared between the client and
1269      * KDC runtime enctypes.
1270      */
1271
1272     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1273                           &ckey, &cetype);
1274     if (ret) {
1275         kdc_log(context, config, 0, 
1276                 "Client (%s) has no support for etypes", client_name);
1277         goto out;
1278     }
1279         
1280     ret = _kdc_get_preferred_key(context, config,
1281                                  server, server_name,
1282                                  &setype, &skey);
1283     if(ret)
1284         goto out;
1285
1286     {
1287         const krb5_enctype *p;
1288         int i, j, y;
1289
1290         p = krb5_kerberos_enctypes(context);
1291
1292         sessionetype = ETYPE_NULL;
1293
1294         for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1295             /* check it's valid */
1296             if (krb5_enctype_valid(context, p[i]) != 0)
1297                 continue;
1298
1299             /* check if the client supports it */
1300             for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {
1301                 if (p[i] == b->etype.val[j]) {
1302                     /*
1303                      * if the server (krbtgt) has explicit etypes,
1304                      * check if it also supports it
1305                      */
1306                     if (server->entry.etypes) {
1307                         for (y = 0; y < server->entry.etypes->len; y++) {
1308                             if (p[i] == server->entry.etypes->val[y]) {
1309                                 sessionetype = p[i];
1310                                 break;
1311                             }
1312                         }
1313                     } else {
1314                         sessionetype = p[i];
1315                         break;
1316                     }
1317                 }
1318             }
1319         }
1320         if (sessionetype == ETYPE_NULL) {
1321             kdc_log(context, config, 0, 
1322                     "Client (%s) from %s has no common enctypes with KDC"
1323                     "to use for the session key",
1324                     client_name, from);
1325             goto out;
1326         }
1327     }
1328
1329     log_as_req(context, config, cetype, setype, b);
1330
1331     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1332        || (f.request_anonymous && !config->allow_anonymous)) {
1333         ret = KRB5KDC_ERR_BADOPTION;
1334         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1335         goto out;
1336     }
1337     
1338     rep.pvno = 5;
1339     rep.msg_type = krb_as_rep;
1340     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1341     if (f.request_anonymous)
1342         _kdc_make_anonymous_principalname (&rep.cname);
1343     else
1344         _krb5_principal2principalname(&rep.cname, 
1345                                       client->entry.principal);
1346     rep.ticket.tkt_vno = 5;
1347     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1348     _krb5_principal2principalname(&rep.ticket.sname, 
1349                                   server->entry.principal);
1350
1351     et.flags.initial = 1;
1352     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1353         et.flags.forwardable = f.forwardable;
1354     else if (f.forwardable) {
1355         ret = KRB5KDC_ERR_POLICY;
1356         kdc_log(context, config, 0,
1357                 "Ticket may not be forwardable -- %s", client_name);
1358         goto out;
1359     }
1360     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1361         et.flags.proxiable = f.proxiable;
1362     else if (f.proxiable) {
1363         ret = KRB5KDC_ERR_POLICY;
1364         kdc_log(context, config, 0, 
1365                 "Ticket may not be proxiable -- %s", client_name);
1366         goto out;
1367     }
1368     if(client->entry.flags.postdate && server->entry.flags.postdate)
1369         et.flags.may_postdate = f.allow_postdate;
1370     else if (f.allow_postdate){
1371         ret = KRB5KDC_ERR_POLICY;
1372         kdc_log(context, config, 0,
1373                 "Ticket may not be postdatable -- %s", client_name);
1374         goto out;
1375     }
1376
1377     /* check for valid set of addresses */
1378     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1379         ret = KRB5KRB_AP_ERR_BADADDR;
1380         kdc_log(context, config, 0,
1381                 "Bad address list requested -- %s", client_name);
1382         goto out;
1383     }
1384
1385     ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1386     if (ret)
1387         goto out;
1388     copy_PrincipalName(&rep.cname, &et.cname);
1389     copy_Realm(&rep.crealm, &et.crealm);
1390     
1391     {
1392         time_t start;
1393         time_t t;
1394         
1395         start = et.authtime = kdc_time;
1396     
1397         if(f.postdated && req->req_body.from){
1398             ALLOC(et.starttime);
1399             start = *et.starttime = *req->req_body.from;
1400             et.flags.invalid = 1;
1401             et.flags.postdated = 1; /* XXX ??? */
1402         }
1403         _kdc_fix_time(&b->till);
1404         t = *b->till;
1405
1406         /* be careful not overflowing */
1407
1408         if(client->entry.max_life)
1409             t = start + min(t - start, *client->entry.max_life);
1410         if(server->entry.max_life)
1411             t = start + min(t - start, *server->entry.max_life);
1412 #if 0
1413         t = min(t, start + realm->max_life);
1414 #endif
1415         et.endtime = t;
1416         if(f.renewable_ok && et.endtime < *b->till){
1417             f.renewable = 1;
1418             if(b->rtime == NULL){
1419                 ALLOC(b->rtime);
1420                 *b->rtime = 0;
1421             }
1422             if(*b->rtime < *b->till)
1423                 *b->rtime = *b->till;
1424         }
1425         if(f.renewable && b->rtime){
1426             t = *b->rtime;
1427             if(t == 0)
1428                 t = MAX_TIME;
1429             if(client->entry.max_renew)
1430                 t = start + min(t - start, *client->entry.max_renew);
1431             if(server->entry.max_renew)
1432                 t = start + min(t - start, *server->entry.max_renew);
1433 #if 0
1434             t = min(t, start + realm->max_renew);
1435 #endif
1436             ALLOC(et.renew_till);
1437             *et.renew_till = t;
1438             et.flags.renewable = 1;
1439         }
1440     }
1441
1442     if (f.request_anonymous)
1443         et.flags.anonymous = 1;
1444     
1445     if(b->addresses){
1446         ALLOC(et.caddr);
1447         copy_HostAddresses(b->addresses, et.caddr);
1448     }
1449     
1450     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1451     krb5_data_zero(&et.transited.contents); 
1452      
1453     copy_EncryptionKey(&et.key, &ek.key);
1454
1455     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1456      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1457      * incapable of correctly decoding SEQUENCE OF's of zero length.
1458      *
1459      * To fix this, always send at least one no-op last_req
1460      *
1461      * If there's a pw_end or valid_end we will use that,
1462      * otherwise just a dummy lr.
1463      */
1464     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1465     ek.last_req.len = 0;
1466     if (client->entry.pw_end
1467         && (config->kdc_warn_pwexpire == 0
1468             || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1469         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1470         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1471         ++ek.last_req.len;
1472     }
1473     if (client->entry.valid_end) {
1474         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1475         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1476         ++ek.last_req.len;
1477     }
1478     if (ek.last_req.len == 0) {
1479         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1480         ek.last_req.val[ek.last_req.len].lr_value = 0;
1481         ++ek.last_req.len;
1482     }
1483     ek.nonce = b->nonce;
1484     if (client->entry.valid_end || client->entry.pw_end) {
1485         ALLOC(ek.key_expiration);
1486         if (client->entry.valid_end) {
1487             if (client->entry.pw_end)
1488                 *ek.key_expiration = min(*client->entry.valid_end, 
1489                                          *client->entry.pw_end);
1490             else
1491                 *ek.key_expiration = *client->entry.valid_end;
1492         } else
1493             *ek.key_expiration = *client->entry.pw_end;
1494     } else
1495         ek.key_expiration = NULL;
1496     ek.flags = et.flags;
1497     ek.authtime = et.authtime;
1498     if (et.starttime) {
1499         ALLOC(ek.starttime);
1500         *ek.starttime = *et.starttime;
1501     }
1502     ek.endtime = et.endtime;
1503     if (et.renew_till) {
1504         ALLOC(ek.renew_till);
1505         *ek.renew_till = *et.renew_till;
1506     }
1507     copy_Realm(&rep.ticket.realm, &ek.srealm);
1508     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1509     if(et.caddr){
1510         ALLOC(ek.caddr);
1511         copy_HostAddresses(et.caddr, ek.caddr);
1512     }
1513
1514     ALLOC(rep.padata);
1515     rep.padata->len = 0;
1516     rep.padata->val = NULL;
1517
1518     reply_key = &ckey->key;
1519 #if PKINIT
1520     if (pkp) {
1521         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 
1522                                   req, req_buffer, 
1523                                   &reply_key, rep.padata);
1524         if (ret)
1525             goto out;
1526         ret = _kdc_add_inital_verified_cas(context,
1527                                            config,
1528                                            pkp,
1529                                            &et);
1530         if (ret)
1531             goto out;
1532     }
1533 #endif
1534
1535     set_salt_padata (rep.padata, ckey->salt);
1536
1537     if (rep.padata->len == 0) {
1538         free(rep.padata);
1539         rep.padata = NULL;
1540     }
1541
1542     /* Add the PAC */
1543     if (send_pac_p(context, req)) {
1544         krb5_pac p = NULL;
1545         krb5_data data;
1546
1547         ret = _kdc_pac_generate(context, client, &p);
1548         if (ret) {
1549             kdc_log(context, config, 0, "PAC generation failed for -- %s", 
1550                     client_name);
1551             goto out;
1552         }
1553         if (p != NULL) {
1554             ret = _krb5_pac_sign(context, p, et.authtime,
1555                                  client->entry.principal,
1556                                  &skey->key, /* Server key */ 
1557                                  &skey->key, /* FIXME: should be krbtgt key */
1558                                  &data);
1559             krb5_pac_free(context, p);
1560             if (ret) {
1561                 kdc_log(context, config, 0, "PAC signing failed for -- %s", 
1562                         client_name);
1563                 goto out;
1564             }
1565
1566             ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1567                                               KRB5_AUTHDATA_WIN2K_PAC,
1568                                               &data);
1569             krb5_data_free(&data);
1570             if (ret)
1571                 goto out;
1572         }
1573     }
1574
1575     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1576                        et.endtime, et.renew_till);
1577
1578     /* do this as the last thing since this signs the EncTicketPart */
1579     ret = _kdc_add_KRB5SignedPath(context,
1580                                   config,
1581                                   server,
1582                                   setype,
1583                                   NULL,
1584                                   NULL,
1585                                   &et);
1586     if (ret)
1587         goto out;
1588
1589     ret = _kdc_encode_reply(context, config, 
1590                             &rep, &et, &ek, setype, server->entry.kvno, 
1591                             &skey->key, client->entry.kvno, 
1592                             reply_key, &e_text, reply);
1593     free_EncTicketPart(&et);
1594     free_EncKDCRepPart(&ek);
1595     if (ret)
1596         goto out;
1597
1598     /* */
1599     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1600         krb5_data_free(reply);
1601         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1602         e_text = "Reply packet too large";
1603     }
1604
1605 out:
1606     free_AS_REP(&rep);
1607     if(ret){
1608         krb5_mk_error(context,
1609                       ret,
1610                       e_text,
1611                       (e_data.data ? &e_data : NULL),
1612                       client_princ,
1613                       server_princ,
1614                       NULL,
1615                       NULL,
1616                       reply);
1617         ret = 0;
1618     }
1619 #ifdef PKINIT
1620     if (pkp)
1621         _kdc_pk_free_client_param(context, pkp);
1622 #endif
1623     if (e_data.data)
1624         free(e_data.data);
1625     if (client_princ)
1626         krb5_free_principal(context, client_princ);
1627     free(client_name);
1628     if (server_princ)
1629         krb5_free_principal(context, server_princ);
1630     free(server_name);
1631     if(client)
1632         _kdc_free_ent(context, client);
1633     if(server)
1634         _kdc_free_ent(context, server);
1635     return ret;
1636 }
1637
1638 /*
1639  * Add the AuthorizationData `data´ of `type´ to the last element in
1640  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1641  */
1642
1643 krb5_error_code
1644 _kdc_tkt_add_if_relevant_ad(krb5_context context,
1645                             EncTicketPart *tkt,
1646                             int type,
1647                             const krb5_data *data)
1648 {
1649     krb5_error_code ret;
1650     size_t size;
1651
1652     if (tkt->authorization_data == NULL) {
1653         tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1654         if (tkt->authorization_data == NULL) {
1655             krb5_set_error_string(context, "out of memory");
1656             return ENOMEM;
1657         }
1658     }
1659         
1660     /* add the entry to the last element */
1661     {
1662         AuthorizationData ad = { 0, NULL };
1663         AuthorizationDataElement ade;
1664
1665         ade.ad_type = type;
1666         ade.ad_data = *data;
1667
1668         ret = add_AuthorizationData(&ad, &ade);
1669         if (ret) {
1670             krb5_set_error_string(context, "add AuthorizationData failed");
1671             return ret;
1672         }
1673
1674         ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1675
1676         ASN1_MALLOC_ENCODE(AuthorizationData, 
1677                            ade.ad_data.data, ade.ad_data.length, 
1678                            &ad, &size, ret);
1679         free_AuthorizationData(&ad);
1680         if (ret) {
1681             krb5_set_error_string(context, "ASN.1 encode of "
1682                                   "AuthorizationData failed");
1683             return ret;
1684         }
1685         if (ade.ad_data.length != size)
1686             krb5_abortx(context, "internal asn.1 encoder error");
1687         
1688         ret = add_AuthorizationData(tkt->authorization_data, &ade);
1689         der_free_octet_string(&ade.ad_data);
1690         if (ret) {
1691             krb5_set_error_string(context, "add AuthorizationData failed");
1692             return ret;
1693         }
1694     }
1695
1696     return 0;
1697 }