r19633: Merge to lorikeet-heimdal, removing krb5_rd_req_return_keyblock in favour...
[samba.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.224 2006/11/04 17:05:28 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 = "<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 = "<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  * verify the flags on `client' and `server', returning 0
639  * if they are OK and generating an error messages and returning
640  * and error code otherwise.
641  */
642
643 krb5_error_code
644 _kdc_check_flags(krb5_context context, 
645                  krb5_kdc_configuration *config,
646                  hdb_entry_ex *client_ex, const char *client_name,
647                  hdb_entry_ex *server_ex, const char *server_name,
648                  krb5_boolean is_as_req)
649 {
650     if(client_ex != NULL) {
651         hdb_entry *client = &client_ex->entry;
652
653         /* check client */
654         if (client->flags.invalid) {
655             kdc_log(context, config, 0, 
656                     "Client (%s) has invalid bit set", client_name);
657             return KRB5KDC_ERR_POLICY;
658         }
659         
660         if(!client->flags.client){
661             kdc_log(context, config, 0,
662                     "Principal may not act as client -- %s", client_name);
663             return KRB5KDC_ERR_POLICY;
664         }
665         
666         if (client->valid_start && *client->valid_start > kdc_time) {
667             char starttime_str[100];
668             krb5_format_time(context, *client->valid_start, 
669                              starttime_str, sizeof(starttime_str), TRUE); 
670             kdc_log(context, config, 0,
671                     "Client not yet valid until %s -- %s", 
672                     starttime_str, client_name);
673             return KRB5KDC_ERR_CLIENT_NOTYET;
674         }
675         
676         if (client->valid_end && *client->valid_end < kdc_time) {
677             char endtime_str[100];
678             krb5_format_time(context, *client->valid_end, 
679                              endtime_str, sizeof(endtime_str), TRUE); 
680             kdc_log(context, config, 0,
681                     "Client expired at %s -- %s",
682                     endtime_str, client_name);
683             return KRB5KDC_ERR_NAME_EXP;
684         }
685         
686         if (client->pw_end && *client->pw_end < kdc_time 
687             && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
688             char pwend_str[100];
689             krb5_format_time(context, *client->pw_end, 
690                              pwend_str, sizeof(pwend_str), TRUE); 
691             kdc_log(context, config, 0,
692                     "Client's key has expired at %s -- %s", 
693                     pwend_str, client_name);
694             return KRB5KDC_ERR_KEY_EXPIRED;
695         }
696     }
697
698     /* check server */
699     
700     if (server_ex != NULL) {
701         hdb_entry *server = &server_ex->entry;
702
703         if (server->flags.invalid) {
704             kdc_log(context, config, 0,
705                     "Server has invalid flag set -- %s", server_name);
706             return KRB5KDC_ERR_POLICY;
707         }
708
709         if(!server->flags.server){
710             kdc_log(context, config, 0,
711                     "Principal may not act as server -- %s", server_name);
712             return KRB5KDC_ERR_POLICY;
713         }
714
715         if(!is_as_req && server->flags.initial) {
716             kdc_log(context, config, 0,
717                     "AS-REQ is required for server -- %s", server_name);
718             return KRB5KDC_ERR_POLICY;
719         }
720
721         if (server->valid_start && *server->valid_start > kdc_time) {
722             char starttime_str[100];
723             krb5_format_time(context, *server->valid_start, 
724                              starttime_str, sizeof(starttime_str), TRUE); 
725             kdc_log(context, config, 0,
726                     "Server not yet valid until %s -- %s",
727                     starttime_str, server_name);
728             return KRB5KDC_ERR_SERVICE_NOTYET;
729         }
730
731         if (server->valid_end && *server->valid_end < kdc_time) {
732             char endtime_str[100];
733             krb5_format_time(context, *server->valid_end, 
734                              endtime_str, sizeof(endtime_str), TRUE); 
735             kdc_log(context, config, 0,
736                     "Server expired at %s -- %s", 
737                     endtime_str, server_name);
738             return KRB5KDC_ERR_SERVICE_EXP;
739         }
740
741         if (server->pw_end && *server->pw_end < kdc_time) {
742             char pwend_str[100];
743             krb5_format_time(context, *server->pw_end, 
744                              pwend_str, sizeof(pwend_str), TRUE); 
745             kdc_log(context, config, 0,
746                     "Server's key has expired at -- %s", 
747                     pwend_str, server_name);
748             return KRB5KDC_ERR_KEY_EXPIRED;
749         }
750     }
751     return 0;
752 }
753
754 /*
755  * Return TRUE if `from' is part of `addresses' taking into consideration
756  * the configuration variables that tells us how strict we should be about
757  * these checks
758  */
759
760 krb5_boolean
761 _kdc_check_addresses(krb5_context context,        
762                      krb5_kdc_configuration *config,
763                      HostAddresses *addresses, const struct sockaddr *from)
764 {
765     krb5_error_code ret;
766     krb5_address addr;
767     krb5_boolean result;
768     krb5_boolean only_netbios = TRUE;
769     int i;
770     
771     if(config->check_ticket_addresses == 0)
772         return TRUE;
773
774     if(addresses == NULL)
775         return config->allow_null_ticket_addresses;
776     
777     for (i = 0; i < addresses->len; ++i) {
778         if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
779             only_netbios = FALSE;
780         }
781     }
782
783     /* Windows sends it's netbios name, which I can only assume is
784      * used for the 'allowed workstations' check.  This is painful,
785      * but we still want to check IP addresses if they happen to be
786      * present.
787      */
788
789     if(only_netbios)
790         return config->allow_null_ticket_addresses;
791
792     ret = krb5_sockaddr2address (context, from, &addr);
793     if(ret)
794         return FALSE;
795
796     result = krb5_address_search(context, &addr, addresses);
797     krb5_free_address (context, &addr);
798     return result;
799 }
800
801 krb5_error_code
802 _kdc_as_rep(krb5_context context, 
803             krb5_kdc_configuration *config,
804             KDC_REQ *req, 
805             const krb5_data *req_buffer, 
806             krb5_data *reply,
807             const char *from,
808             struct sockaddr *from_addr,
809             int datagram_reply)
810 {
811     KDC_REQ_BODY *b = &req->req_body;
812     AS_REP rep;
813     KDCOptions f = b->kdc_options;
814     hdb_entry_ex *client = NULL, *server = NULL;
815     krb5_enctype cetype, setype, sessionetype;
816     EncTicketPart et;
817     EncKDCRepPart ek;
818     krb5_principal client_princ = NULL, server_princ = NULL;
819     char *client_name = NULL, *server_name = NULL;
820     krb5_error_code ret = 0;
821     const char *e_text = NULL;
822     krb5_crypto crypto;
823     Key *ckey, *skey;
824     EncryptionKey *reply_key;
825 #ifdef PKINIT
826     pk_client_params *pkp = NULL;
827 #endif
828
829     memset(&rep, 0, sizeof(rep));
830
831     if(b->sname == NULL){
832         ret = KRB5KRB_ERR_GENERIC;
833         e_text = "No server in request";
834     } else{
835         _krb5_principalname2krb5_principal (context,
836                                             &server_princ,
837                                             *(b->sname),
838                                             b->realm);
839         ret = krb5_unparse_name(context, server_princ, &server_name);
840     }
841     if (ret) {
842         kdc_log(context, config, 0, 
843                 "AS-REQ malformed server name from %s", from);
844         goto out;
845     }
846     
847     if(b->cname == NULL){
848         ret = KRB5KRB_ERR_GENERIC;
849         e_text = "No client in request";
850     } else {
851         _krb5_principalname2krb5_principal (context,
852                                             &client_princ,
853                                             *(b->cname),
854                                             b->realm);
855         ret = krb5_unparse_name(context, client_princ, &client_name);
856     }
857     if (ret) {
858         kdc_log(context, config, 0,
859                 "AS-REQ malformed client name from %s", from);
860         goto out;
861     }
862
863     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
864             client_name, from, server_name);
865
866     ret = _kdc_db_fetch(context, config, client_princ, 
867                         HDB_F_GET_CLIENT, NULL, &client);
868     if(ret){
869         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
870                 krb5_get_err_text(context, ret));
871         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
872         goto out;
873     }
874
875     ret = _kdc_db_fetch(context, config, server_princ,
876                         HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
877                         NULL, &server);
878     if(ret){
879         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
880                 krb5_get_err_text(context, ret));
881         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
882         goto out;
883     }
884
885     ret = _kdc_check_flags(context, config, 
886                            client, client_name,
887                            server, server_name,
888                            TRUE);
889     if(ret)
890         goto out;
891
892     if (client->check_client_access) {
893         ret = client->check_client_access(context, client, 
894                                           b->addresses);
895         if(ret)
896             goto out;
897     }
898
899     memset(&et, 0, sizeof(et));
900     memset(&ek, 0, sizeof(ek));
901
902     if(req->padata){
903         int i;
904         PA_DATA *pa;
905         int found_pa = 0;
906
907         log_patypes(context, config, req->padata);
908
909 #ifdef PKINIT
910         kdc_log(context, config, 5, 
911                 "Looking for PKINIT pa-data -- %s", client_name);
912
913         e_text = "No PKINIT PA found";
914
915         i = 0;
916         if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
917             ;
918         if (pa == NULL) {
919             i = 0;
920             if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
921                 ;
922         }
923         if (pa) {
924             char *client_cert = NULL;
925
926             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
927             if (ret) {
928                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
929                 kdc_log(context, config, 5, 
930                         "Failed to decode PKINIT PA-DATA -- %s", 
931                         client_name);
932                 goto ts_enc;
933             }
934             if (ret == 0 && pkp == NULL)
935                 goto ts_enc;
936
937             ret = _kdc_pk_check_client(context,
938                                        config,
939                                        client_princ, 
940                                        client,
941                                        pkp,
942                                        &client_cert);
943             if (ret) {
944                 e_text = "PKINIT certificate not allowed to "
945                     "impersonate principal";
946                 _kdc_pk_free_client_param(context, pkp);
947
948                 kdc_log(context, config, 0, "%s", e_text);
949                 pkp = NULL;
950                 goto ts_enc;
951             }
952             found_pa = 1;
953             et.flags.pre_authent = 1;
954             kdc_log(context, config, 0,
955                     "PKINIT pre-authentication succeeded -- %s using %s", 
956                     client_name, client_cert);
957             free(client_cert);
958             if (pkp)
959                 goto preauth_done;
960         }
961     ts_enc:
962 #endif
963         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
964                 client_name);
965
966         i = 0;
967         e_text = "No ENC-TS found";
968         while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
969             krb5_data ts_data;
970             PA_ENC_TS_ENC p;
971             size_t len;
972             EncryptedData enc_data;
973             Key *pa_key;
974             char *str;
975             
976             found_pa = 1;
977             
978             ret = decode_EncryptedData(pa->padata_value.data,
979                                        pa->padata_value.length,
980                                        &enc_data,
981                                        &len);
982             if (ret) {
983                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
984                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
985                         client_name);
986                 goto out;
987             }
988             
989             ret = hdb_enctype2key(context, &client->entry, 
990                                   enc_data.etype, &pa_key);
991             if(ret){
992                 char *estr;
993                 e_text = "No key matches pa-data";
994                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
995                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
996                     estr = NULL;
997                 if(estr == NULL)
998                     kdc_log(context, config, 5, 
999                             "No client key matching pa-data (%d) -- %s", 
1000                             enc_data.etype, client_name);
1001                 else
1002                     kdc_log(context, config, 5,
1003                             "No client key matching pa-data (%s) -- %s", 
1004                             estr, client_name);
1005                 free(estr);
1006                     
1007                 free_EncryptedData(&enc_data);
1008                 continue;
1009             }
1010
1011         try_next_key:
1012             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1013             if (ret) {
1014                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1015                         krb5_get_err_text(context, ret));
1016                 free_EncryptedData(&enc_data);
1017                 continue;
1018             }
1019
1020             ret = krb5_decrypt_EncryptedData (context,
1021                                               crypto,
1022                                               KRB5_KU_PA_ENC_TIMESTAMP,
1023                                               &enc_data,
1024                                               &ts_data);
1025             krb5_crypto_destroy(context, crypto);
1026             if(ret){
1027                 krb5_error_code ret2;
1028                 ret2 = krb5_enctype_to_string(context, 
1029                                               pa_key->key.keytype, &str);
1030                 if (ret2)
1031                     str = NULL;
1032                 kdc_log(context, config, 5, 
1033                         "Failed to decrypt PA-DATA -- %s "
1034                         "(enctype %s) error %s",
1035                         client_name,
1036                         str ? str : "unknown enctype", 
1037                         krb5_get_err_text(context, ret));
1038                 free(str);
1039
1040                 if(hdb_next_enctype2key(context, &client->entry, 
1041                                         enc_data.etype, &pa_key) == 0)
1042                     goto try_next_key;
1043                 e_text = "Failed to decrypt PA-DATA";
1044
1045                 free_EncryptedData(&enc_data);
1046                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1047                 continue;
1048             }
1049             free_EncryptedData(&enc_data);
1050             ret = decode_PA_ENC_TS_ENC(ts_data.data,
1051                                        ts_data.length,
1052                                        &p,
1053                                        &len);
1054             krb5_data_free(&ts_data);
1055             if(ret){
1056                 e_text = "Failed to decode PA-ENC-TS-ENC";
1057                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1058                 kdc_log(context, config, 
1059                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
1060                         client_name);
1061                 continue;
1062             }
1063             free_PA_ENC_TS_ENC(&p);
1064             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1065                 char client_time[100];
1066                 
1067                 krb5_format_time(context, p.patimestamp, 
1068                                  client_time, sizeof(client_time), TRUE); 
1069
1070                 ret = KRB5KRB_AP_ERR_SKEW;
1071                 kdc_log(context, config, 0,
1072                         "Too large time skew, "
1073                         "client time %s is out by %u > %u seconds -- %s", 
1074                         client_time, 
1075                         (unsigned)abs(kdc_time - p.patimestamp), 
1076                         context->max_skew,
1077                         client_name);
1078                 /* 
1079                  * the following is needed to make windows clients
1080                  * to retry using the timestamp in the error message
1081                  *
1082                  * this is maybe a bug in windows to not trying when e_text
1083                  * is present...
1084                  */
1085                 e_text = NULL;
1086                 goto out;
1087             }
1088             et.flags.pre_authent = 1;
1089
1090             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1091             if (ret)
1092                 str = NULL;
1093
1094             kdc_log(context, config, 2,
1095                     "ENC-TS Pre-authentication succeeded -- %s using %s", 
1096                     client_name, str ? str : "unknown enctype");
1097             free(str);
1098             break;
1099         }
1100 #ifdef PKINIT
1101     preauth_done:
1102 #endif
1103         if(found_pa == 0 && config->require_preauth)
1104             goto use_pa;
1105         /* We come here if we found a pa-enc-timestamp, but if there
1106            was some problem with it, other than too large skew */
1107         if(found_pa && et.flags.pre_authent == 0){
1108             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1109             e_text = NULL;
1110             goto out;
1111         }
1112     }else if (config->require_preauth
1113               || client->entry.flags.require_preauth
1114               || server->entry.flags.require_preauth) {
1115         METHOD_DATA method_data;
1116         PA_DATA *pa;
1117         unsigned char *buf;
1118         size_t len;
1119         krb5_data foo_data;
1120
1121     use_pa: 
1122         method_data.len = 0;
1123         method_data.val = NULL;
1124
1125         ret = realloc_method_data(&method_data);
1126         pa = &method_data.val[method_data.len-1];
1127         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1128         pa->padata_value.length = 0;
1129         pa->padata_value.data   = NULL;
1130
1131 #ifdef PKINIT
1132         ret = realloc_method_data(&method_data);
1133         pa = &method_data.val[method_data.len-1];
1134         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1135         pa->padata_value.length = 0;
1136         pa->padata_value.data   = NULL;
1137 #endif
1138
1139         /* 
1140          * RFC4120 requires: 
1141          * - If the client only knows about old enctypes, then send
1142          *   both info replies (we send 'info' first in the list).
1143          * - If the client is 'modern', because it knows about 'new'
1144          *   enctype types, then only send the 'info2' reply.
1145          */
1146
1147         /* XXX check ret */
1148         if (only_older_enctype_p(req))
1149             ret = get_pa_etype_info(context, config,
1150                                     &method_data, &client->entry, 
1151                                     b->etype.val, b->etype.len); 
1152         /* XXX check ret */
1153         ret = get_pa_etype_info2(context, config, &method_data, 
1154                                  &client->entry, b->etype.val, b->etype.len);
1155
1156         
1157         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1158         free_METHOD_DATA(&method_data);
1159         foo_data.data   = buf;
1160         foo_data.length = len;
1161         
1162         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1163         krb5_mk_error(context,
1164                       ret,
1165                       "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1166                       &foo_data,
1167                       client_princ,
1168                       server_princ,
1169                       NULL,
1170                       NULL,
1171                       reply);
1172         free(buf);
1173         kdc_log(context, config, 0,
1174                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1175                 client_name);
1176         ret = 0;
1177         goto out2;
1178     }
1179     
1180     /*
1181      * Find the client key (for preauth ENC-TS verification and reply
1182      * encryption).  Then the best encryption type for the KDC and
1183      * last the best session key that shared between the client and
1184      * KDC runtime enctypes.
1185      */
1186
1187     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1188                           &ckey, &cetype);
1189     if (ret) {
1190         kdc_log(context, config, 0, 
1191                 "Client (%s) has no support for etypes", client_name);
1192         goto out;
1193     }
1194         
1195     ret = _kdc_get_preferred_key(context, config,
1196                                  server, server_name,
1197                                  &setype, &skey);
1198     if(ret)
1199         goto out;
1200
1201     {
1202         const krb5_enctype *p;
1203         int i, j;
1204
1205         p = krb5_kerberos_enctypes(context);
1206
1207         sessionetype = ETYPE_NULL;
1208
1209         for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1210             if (krb5_enctype_valid(context, p[i]) != 0)
1211                 continue;
1212             for (j = 0; j < b->etype.len; j++) {
1213                 if (p[i] == b->etype.val[j]) {
1214                     sessionetype = p[i];
1215                     break;
1216                 }
1217             }
1218         }
1219         if (sessionetype == ETYPE_NULL) {
1220             kdc_log(context, config, 0, 
1221                     "Client (%s) from %s has no common enctypes with KDC"
1222                     "to use for the session key",
1223                     client_name, from);
1224             goto out;
1225         }
1226     }
1227
1228     {
1229         struct rk_strpool *p = NULL;
1230         char *str;
1231         int i;
1232
1233         for (i = 0; i < b->etype.len; i++) {
1234             ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1235             if (ret == 0) {
1236                 p = rk_strpoolprintf(p, "%s", str);
1237                 free(str);
1238             } else
1239                 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1240             if (p && i + 1 < b->etype.len)
1241                 p = rk_strpoolprintf(p, ", ");
1242             if (p == NULL) {
1243                 kdc_log(context, config, 0, "out of memory");
1244                 goto out;
1245             }
1246         }
1247         if (p == NULL)
1248             p = rk_strpoolprintf(p, "no encryption types");
1249
1250         str = rk_strpoolcollect(p);
1251         kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1252         free(str);
1253     }
1254     {
1255         char *cet;
1256         char *set;
1257
1258         ret = krb5_enctype_to_string(context, cetype, &cet);
1259         if(ret == 0) {
1260             ret = krb5_enctype_to_string(context, setype, &set);
1261             if (ret == 0) {
1262                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1263                 free(set);
1264             }
1265             free(cet);
1266         }
1267         if (ret != 0)
1268             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1269     }
1270     
1271     {
1272         char str[128];
1273         unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(), 
1274                       str, sizeof(str));
1275         if(*str)
1276             kdc_log(context, config, 2, "Requested flags: %s", str);
1277     }
1278     
1279
1280     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1281        || (f.request_anonymous && !config->allow_anonymous)) {
1282         ret = KRB5KDC_ERR_BADOPTION;
1283         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1284         goto out;
1285     }
1286     
1287     rep.pvno = 5;
1288     rep.msg_type = krb_as_rep;
1289     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1290     if (f.request_anonymous)
1291         _kdc_make_anonymous_principalname (&rep.cname);
1292     else
1293         _krb5_principal2principalname(&rep.cname, 
1294                                       client->entry.principal);
1295     rep.ticket.tkt_vno = 5;
1296     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1297     _krb5_principal2principalname(&rep.ticket.sname, 
1298                                   server->entry.principal);
1299
1300     et.flags.initial = 1;
1301     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1302         et.flags.forwardable = f.forwardable;
1303     else if (f.forwardable) {
1304         ret = KRB5KDC_ERR_POLICY;
1305         kdc_log(context, config, 0,
1306                 "Ticket may not be forwardable -- %s", client_name);
1307         goto out;
1308     }
1309     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1310         et.flags.proxiable = f.proxiable;
1311     else if (f.proxiable) {
1312         ret = KRB5KDC_ERR_POLICY;
1313         kdc_log(context, config, 0, 
1314                 "Ticket may not be proxiable -- %s", client_name);
1315         goto out;
1316     }
1317     if(client->entry.flags.postdate && server->entry.flags.postdate)
1318         et.flags.may_postdate = f.allow_postdate;
1319     else if (f.allow_postdate){
1320         ret = KRB5KDC_ERR_POLICY;
1321         kdc_log(context, config, 0,
1322                 "Ticket may not be postdatable -- %s", client_name);
1323         goto out;
1324     }
1325
1326     /* check for valid set of addresses */
1327     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1328         ret = KRB5KRB_AP_ERR_BADADDR;
1329         kdc_log(context, config, 0,
1330                 "Bad address list requested -- %s", client_name);
1331         goto out;
1332     }
1333
1334     krb5_generate_random_keyblock(context, sessionetype, &et.key);
1335     copy_PrincipalName(&rep.cname, &et.cname);
1336     copy_Realm(&rep.crealm, &et.crealm);
1337     
1338     {
1339         time_t start;
1340         time_t t;
1341         
1342         start = et.authtime = kdc_time;
1343     
1344         if(f.postdated && req->req_body.from){
1345             ALLOC(et.starttime);
1346             start = *et.starttime = *req->req_body.from;
1347             et.flags.invalid = 1;
1348             et.flags.postdated = 1; /* XXX ??? */
1349         }
1350         _kdc_fix_time(&b->till);
1351         t = *b->till;
1352
1353         /* be careful not overflowing */
1354
1355         if(client->entry.max_life)
1356             t = start + min(t - start, *client->entry.max_life);
1357         if(server->entry.max_life)
1358             t = start + min(t - start, *server->entry.max_life);
1359 #if 0
1360         t = min(t, start + realm->max_life);
1361 #endif
1362         et.endtime = t;
1363         if(f.renewable_ok && et.endtime < *b->till){
1364             f.renewable = 1;
1365             if(b->rtime == NULL){
1366                 ALLOC(b->rtime);
1367                 *b->rtime = 0;
1368             }
1369             if(*b->rtime < *b->till)
1370                 *b->rtime = *b->till;
1371         }
1372         if(f.renewable && b->rtime){
1373             t = *b->rtime;
1374             if(t == 0)
1375                 t = MAX_TIME;
1376             if(client->entry.max_renew)
1377                 t = start + min(t - start, *client->entry.max_renew);
1378             if(server->entry.max_renew)
1379                 t = start + min(t - start, *server->entry.max_renew);
1380 #if 0
1381             t = min(t, start + realm->max_renew);
1382 #endif
1383             ALLOC(et.renew_till);
1384             *et.renew_till = t;
1385             et.flags.renewable = 1;
1386         }
1387     }
1388
1389     if (f.request_anonymous)
1390         et.flags.anonymous = 1;
1391     
1392     if(b->addresses){
1393         ALLOC(et.caddr);
1394         copy_HostAddresses(b->addresses, et.caddr);
1395     }
1396     
1397     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1398     krb5_data_zero(&et.transited.contents); 
1399      
1400     copy_EncryptionKey(&et.key, &ek.key);
1401
1402     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1403      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1404      * incapable of correctly decoding SEQUENCE OF's of zero length.
1405      *
1406      * To fix this, always send at least one no-op last_req
1407      *
1408      * If there's a pw_end or valid_end we will use that,
1409      * otherwise just a dummy lr.
1410      */
1411     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1412     ek.last_req.len = 0;
1413     if (client->entry.pw_end
1414         && (config->kdc_warn_pwexpire == 0
1415             || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1416         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1417         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1418         ++ek.last_req.len;
1419     }
1420     if (client->entry.valid_end) {
1421         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1422         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1423         ++ek.last_req.len;
1424     }
1425     if (ek.last_req.len == 0) {
1426         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1427         ek.last_req.val[ek.last_req.len].lr_value = 0;
1428         ++ek.last_req.len;
1429     }
1430     ek.nonce = b->nonce;
1431     if (client->entry.valid_end || client->entry.pw_end) {
1432         ALLOC(ek.key_expiration);
1433         if (client->entry.valid_end) {
1434             if (client->entry.pw_end)
1435                 *ek.key_expiration = min(*client->entry.valid_end, 
1436                                          *client->entry.pw_end);
1437             else
1438                 *ek.key_expiration = *client->entry.valid_end;
1439         } else
1440             *ek.key_expiration = *client->entry.pw_end;
1441     } else
1442         ek.key_expiration = NULL;
1443     ek.flags = et.flags;
1444     ek.authtime = et.authtime;
1445     if (et.starttime) {
1446         ALLOC(ek.starttime);
1447         *ek.starttime = *et.starttime;
1448     }
1449     ek.endtime = et.endtime;
1450     if (et.renew_till) {
1451         ALLOC(ek.renew_till);
1452         *ek.renew_till = *et.renew_till;
1453     }
1454     copy_Realm(&rep.ticket.realm, &ek.srealm);
1455     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1456     if(et.caddr){
1457         ALLOC(ek.caddr);
1458         copy_HostAddresses(et.caddr, ek.caddr);
1459     }
1460
1461     ALLOC(rep.padata);
1462     rep.padata->len = 0;
1463     rep.padata->val = NULL;
1464
1465     reply_key = &ckey->key;
1466 #if PKINIT
1467     if (pkp) {
1468         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 
1469                                   req, req_buffer, 
1470                                   &reply_key, rep.padata);
1471         if (ret)
1472             goto out;
1473     }
1474 #endif
1475
1476     set_salt_padata (rep.padata, ckey->salt);
1477
1478     if (rep.padata->len == 0) {
1479         free(rep.padata);
1480         rep.padata = NULL;
1481     }
1482
1483     /* Add the PAC, via a HDB abstraction */
1484     if (client->authz_data_as_req) {
1485             ret = client->authz_data_as_req(context, client, 
1486                                             req->padata, 
1487                                             et.authtime,
1488                                             &skey->key,
1489                                             &et.key,
1490                                             &et.authorization_data);
1491             if (ret) 
1492                     goto out;
1493     }
1494
1495     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1496                        et.endtime, et.renew_till);
1497
1498     /* do this as the last thing since this signs the EncTicketPart */
1499     ret = _kdc_add_KRB5SignedPath(context,
1500                                   config,
1501                                   server,
1502                                   setype,
1503                                   NULL,
1504                                   NULL,
1505                                   &et);
1506     if (ret)
1507         goto out;
1508
1509     ret = _kdc_encode_reply(context, config, 
1510                             &rep, &et, &ek, setype, server->entry.kvno, 
1511                             &skey->key, client->entry.kvno, 
1512                             reply_key, &e_text, reply);
1513     free_EncTicketPart(&et);
1514     free_EncKDCRepPart(&ek);
1515     if (ret)
1516         goto out;
1517
1518     /* */
1519     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1520         krb5_data_free(reply);
1521         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1522         e_text = "Reply packet too large";
1523     }
1524
1525 out:
1526     free_AS_REP(&rep);
1527     if(ret){
1528         krb5_mk_error(context,
1529                       ret,
1530                       e_text,
1531                       NULL,
1532                       client_princ,
1533                       server_princ,
1534                       NULL,
1535                       NULL,
1536                       reply);
1537         ret = 0;
1538     }
1539 out2:
1540 #ifdef PKINIT
1541     if (pkp)
1542         _kdc_pk_free_client_param(context, pkp);
1543 #endif
1544     if (client_princ)
1545         krb5_free_principal(context, client_princ);
1546     free(client_name);
1547     if (server_princ)
1548         krb5_free_principal(context, server_princ);
1549     free(server_name);
1550     if(client)
1551         _kdc_free_ent(context, client);
1552     if(server)
1553         _kdc_free_ent(context, server);
1554     return ret;
1555 }