r21439: fix compiler warnings
[amitay/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.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_crypto crypto;
919     Key *ckey, *skey;
920     EncryptionKey *reply_key;
921 #ifdef PKINIT
922     pk_client_params *pkp = NULL;
923 #endif
924
925     memset(&rep, 0, sizeof(rep));
926
927     if(b->sname == NULL){
928         ret = KRB5KRB_ERR_GENERIC;
929         e_text = "No server in request";
930     } else{
931         _krb5_principalname2krb5_principal (context,
932                                             &server_princ,
933                                             *(b->sname),
934                                             b->realm);
935         ret = krb5_unparse_name(context, server_princ, &server_name);
936     }
937     if (ret) {
938         kdc_log(context, config, 0, 
939                 "AS-REQ malformed server name from %s", from);
940         goto out;
941     }
942     
943     if(b->cname == NULL){
944         ret = KRB5KRB_ERR_GENERIC;
945         e_text = "No client in request";
946     } else {
947         _krb5_principalname2krb5_principal (context,
948                                             &client_princ,
949                                             *(b->cname),
950                                             b->realm);
951         ret = krb5_unparse_name(context, client_princ, &client_name);
952     }
953     if (ret) {
954         kdc_log(context, config, 0,
955                 "AS-REQ malformed client name from %s", from);
956         goto out;
957     }
958
959     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
960             client_name, from, server_name);
961
962     ret = _kdc_db_fetch(context, config, client_princ, 
963                         HDB_F_GET_CLIENT, NULL, &client);
964     if(ret){
965         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
966                 krb5_get_err_text(context, ret));
967         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
968         goto out;
969     }
970
971     ret = _kdc_db_fetch(context, config, server_princ,
972                         HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
973                         NULL, &server);
974     if(ret){
975         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
976                 krb5_get_err_text(context, ret));
977         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
978         goto out;
979     }
980
981     ret = _kdc_windc_client_access(context, client, req);
982     if(ret)
983         goto out;
984
985     ret = _kdc_check_flags(context, config, 
986                            client, client_name,
987                            server, server_name,
988                            TRUE);
989     if(ret)
990         goto out;
991
992     memset(&et, 0, sizeof(et));
993     memset(&ek, 0, sizeof(ek));
994
995     if(req->padata){
996         int i;
997         PA_DATA *pa;
998         int found_pa = 0;
999
1000         log_patypes(context, config, req->padata);
1001
1002 #ifdef PKINIT
1003         kdc_log(context, config, 5, 
1004                 "Looking for PKINIT pa-data -- %s", client_name);
1005
1006         e_text = "No PKINIT PA found";
1007
1008         i = 0;
1009         if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
1010             ;
1011         if (pa == NULL) {
1012             i = 0;
1013             if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
1014                 ;
1015         }
1016         if (pa) {
1017             char *client_cert = NULL;
1018
1019             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
1020             if (ret) {
1021                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1022                 kdc_log(context, config, 5, 
1023                         "Failed to decode PKINIT PA-DATA -- %s", 
1024                         client_name);
1025                 goto ts_enc;
1026             }
1027             if (ret == 0 && pkp == NULL)
1028                 goto ts_enc;
1029
1030             ret = _kdc_pk_check_client(context,
1031                                        config,
1032                                        client,
1033                                        pkp,
1034                                        &client_cert);
1035             if (ret) {
1036                 e_text = "PKINIT certificate not allowed to "
1037                     "impersonate principal";
1038                 _kdc_pk_free_client_param(context, pkp);
1039
1040                 kdc_log(context, config, 0, "%s", e_text);
1041                 pkp = NULL;
1042                 goto ts_enc;
1043             }
1044             found_pa = 1;
1045             et.flags.pre_authent = 1;
1046             kdc_log(context, config, 0,
1047                     "PKINIT pre-authentication succeeded -- %s using %s", 
1048                     client_name, client_cert);
1049             free(client_cert);
1050             if (pkp)
1051                 goto preauth_done;
1052         }
1053     ts_enc:
1054 #endif
1055         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
1056                 client_name);
1057
1058         i = 0;
1059         e_text = "No ENC-TS found";
1060         while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1061             krb5_data ts_data;
1062             PA_ENC_TS_ENC p;
1063             size_t len;
1064             EncryptedData enc_data;
1065             Key *pa_key;
1066             char *str;
1067             
1068             found_pa = 1;
1069             
1070             ret = decode_EncryptedData(pa->padata_value.data,
1071                                        pa->padata_value.length,
1072                                        &enc_data,
1073                                        &len);
1074             if (ret) {
1075                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1076                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
1077                         client_name);
1078                 goto out;
1079             }
1080             
1081             ret = hdb_enctype2key(context, &client->entry, 
1082                                   enc_data.etype, &pa_key);
1083             if(ret){
1084                 char *estr;
1085                 e_text = "No key matches pa-data";
1086                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1087                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1088                     estr = NULL;
1089                 if(estr == NULL)
1090                     kdc_log(context, config, 5, 
1091                             "No client key matching pa-data (%d) -- %s", 
1092                             enc_data.etype, client_name);
1093                 else
1094                     kdc_log(context, config, 5,
1095                             "No client key matching pa-data (%s) -- %s", 
1096                             estr, client_name);
1097                 free(estr);
1098                     
1099                 free_EncryptedData(&enc_data);
1100                 continue;
1101             }
1102
1103         try_next_key:
1104             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1105             if (ret) {
1106                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1107                         krb5_get_err_text(context, ret));
1108                 free_EncryptedData(&enc_data);
1109                 continue;
1110             }
1111
1112             ret = krb5_decrypt_EncryptedData (context,
1113                                               crypto,
1114                                               KRB5_KU_PA_ENC_TIMESTAMP,
1115                                               &enc_data,
1116                                               &ts_data);
1117             krb5_crypto_destroy(context, crypto);
1118             if(ret){
1119                 krb5_error_code ret2;
1120                 ret2 = krb5_enctype_to_string(context, 
1121                                               pa_key->key.keytype, &str);
1122                 if (ret2)
1123                     str = NULL;
1124                 kdc_log(context, config, 5, 
1125                         "Failed to decrypt PA-DATA -- %s "
1126                         "(enctype %s) error %s",
1127                         client_name,
1128                         str ? str : "unknown enctype", 
1129                         krb5_get_err_text(context, ret));
1130                 free(str);
1131
1132                 if(hdb_next_enctype2key(context, &client->entry, 
1133                                         enc_data.etype, &pa_key) == 0)
1134                     goto try_next_key;
1135                 e_text = "Failed to decrypt PA-DATA";
1136
1137                 free_EncryptedData(&enc_data);
1138                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1139                 continue;
1140             }
1141             free_EncryptedData(&enc_data);
1142             ret = decode_PA_ENC_TS_ENC(ts_data.data,
1143                                        ts_data.length,
1144                                        &p,
1145                                        &len);
1146             krb5_data_free(&ts_data);
1147             if(ret){
1148                 e_text = "Failed to decode PA-ENC-TS-ENC";
1149                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1150                 kdc_log(context, config, 
1151                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
1152                         client_name);
1153                 continue;
1154             }
1155             free_PA_ENC_TS_ENC(&p);
1156             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1157                 char client_time[100];
1158                 
1159                 krb5_format_time(context, p.patimestamp, 
1160                                  client_time, sizeof(client_time), TRUE); 
1161
1162                 ret = KRB5KRB_AP_ERR_SKEW;
1163                 kdc_log(context, config, 0,
1164                         "Too large time skew, "
1165                         "client time %s is out by %u > %u seconds -- %s", 
1166                         client_time, 
1167                         (unsigned)abs(kdc_time - p.patimestamp), 
1168                         context->max_skew,
1169                         client_name);
1170                 /* 
1171                  * the following is needed to make windows clients
1172                  * to retry using the timestamp in the error message
1173                  *
1174                  * this is maybe a bug in windows to not trying when e_text
1175                  * is present...
1176                  */
1177                 e_text = NULL;
1178                 goto out;
1179             }
1180             et.flags.pre_authent = 1;
1181
1182             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1183             if (ret)
1184                 str = NULL;
1185
1186             kdc_log(context, config, 2,
1187                     "ENC-TS Pre-authentication succeeded -- %s using %s", 
1188                     client_name, str ? str : "unknown enctype");
1189             free(str);
1190             break;
1191         }
1192 #ifdef PKINIT
1193     preauth_done:
1194 #endif
1195         if(found_pa == 0 && config->require_preauth)
1196             goto use_pa;
1197         /* We come here if we found a pa-enc-timestamp, but if there
1198            was some problem with it, other than too large skew */
1199         if(found_pa && et.flags.pre_authent == 0){
1200             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1201             e_text = NULL;
1202             goto out;
1203         }
1204     }else if (config->require_preauth
1205               || client->entry.flags.require_preauth
1206               || server->entry.flags.require_preauth) {
1207         METHOD_DATA method_data;
1208         PA_DATA *pa;
1209         unsigned char *buf;
1210         size_t len;
1211         krb5_data foo_data;
1212
1213     use_pa: 
1214         method_data.len = 0;
1215         method_data.val = NULL;
1216
1217         ret = realloc_method_data(&method_data);
1218         pa = &method_data.val[method_data.len-1];
1219         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1220         pa->padata_value.length = 0;
1221         pa->padata_value.data   = NULL;
1222
1223 #ifdef PKINIT
1224         ret = realloc_method_data(&method_data);
1225         pa = &method_data.val[method_data.len-1];
1226         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1227         pa->padata_value.length = 0;
1228         pa->padata_value.data   = NULL;
1229 #endif
1230
1231         /* 
1232          * RFC4120 requires: 
1233          * - If the client only knows about old enctypes, then send
1234          *   both info replies (we send 'info' first in the list).
1235          * - If the client is 'modern', because it knows about 'new'
1236          *   enctype types, then only send the 'info2' reply.
1237          */
1238
1239         /* XXX check ret */
1240         if (only_older_enctype_p(req))
1241             ret = get_pa_etype_info(context, config,
1242                                     &method_data, &client->entry, 
1243                                     b->etype.val, b->etype.len); 
1244         /* XXX check ret */
1245         ret = get_pa_etype_info2(context, config, &method_data, 
1246                                  &client->entry, b->etype.val, b->etype.len);
1247
1248         
1249         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1250         free_METHOD_DATA(&method_data);
1251         foo_data.data   = buf;
1252         foo_data.length = len;
1253         
1254         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1255         krb5_mk_error(context,
1256                       ret,
1257                       "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1258                       &foo_data,
1259                       client_princ,
1260                       server_princ,
1261                       NULL,
1262                       NULL,
1263                       reply);
1264         free(buf);
1265         kdc_log(context, config, 0,
1266                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1267                 client_name);
1268         ret = 0;
1269         goto out2;
1270     }
1271     
1272     /*
1273      * Find the client key (for preauth ENC-TS verification and reply
1274      * encryption).  Then the best encryption type for the KDC and
1275      * last the best session key that shared between the client and
1276      * KDC runtime enctypes.
1277      */
1278
1279     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1280                           &ckey, &cetype);
1281     if (ret) {
1282         kdc_log(context, config, 0, 
1283                 "Client (%s) has no support for etypes", client_name);
1284         goto out;
1285     }
1286         
1287     ret = _kdc_get_preferred_key(context, config,
1288                                  server, server_name,
1289                                  &setype, &skey);
1290     if(ret)
1291         goto out;
1292
1293     {
1294         const krb5_enctype *p;
1295         int i, j, y;
1296
1297         p = krb5_kerberos_enctypes(context);
1298
1299         sessionetype = ETYPE_NULL;
1300
1301         for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1302             /* check it's valid */
1303             if (krb5_enctype_valid(context, p[i]) != 0)
1304                 continue;
1305
1306             /* check if the client supports it */
1307             for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {
1308                 if (p[i] == b->etype.val[j]) {
1309                     /*
1310                      * if the server (krbtgt) has explicit etypes,
1311                      * check if it also supports it
1312                      */
1313                     if (server->entry.etypes) {
1314                         for (y = 0; y < server->entry.etypes->len; y++) {
1315                             if (p[i] == server->entry.etypes->val[y]) {
1316                                 sessionetype = p[i];
1317                                 break;
1318                             }
1319                         }
1320                     } else {
1321                         sessionetype = p[i];
1322                         break;
1323                     }
1324                 }
1325             }
1326         }
1327         if (sessionetype == ETYPE_NULL) {
1328             kdc_log(context, config, 0, 
1329                     "Client (%s) from %s has no common enctypes with KDC"
1330                     "to use for the session key",
1331                     client_name, from);
1332             goto out;
1333         }
1334     }
1335
1336     log_as_req(context, config, cetype, setype, b);
1337
1338     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1339        || (f.request_anonymous && !config->allow_anonymous)) {
1340         ret = KRB5KDC_ERR_BADOPTION;
1341         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1342         goto out;
1343     }
1344     
1345     rep.pvno = 5;
1346     rep.msg_type = krb_as_rep;
1347     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1348     if (f.request_anonymous)
1349         _kdc_make_anonymous_principalname (&rep.cname);
1350     else
1351         _krb5_principal2principalname(&rep.cname, 
1352                                       client->entry.principal);
1353     rep.ticket.tkt_vno = 5;
1354     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1355     _krb5_principal2principalname(&rep.ticket.sname, 
1356                                   server->entry.principal);
1357
1358     et.flags.initial = 1;
1359     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1360         et.flags.forwardable = f.forwardable;
1361     else if (f.forwardable) {
1362         ret = KRB5KDC_ERR_POLICY;
1363         kdc_log(context, config, 0,
1364                 "Ticket may not be forwardable -- %s", client_name);
1365         goto out;
1366     }
1367     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1368         et.flags.proxiable = f.proxiable;
1369     else if (f.proxiable) {
1370         ret = KRB5KDC_ERR_POLICY;
1371         kdc_log(context, config, 0, 
1372                 "Ticket may not be proxiable -- %s", client_name);
1373         goto out;
1374     }
1375     if(client->entry.flags.postdate && server->entry.flags.postdate)
1376         et.flags.may_postdate = f.allow_postdate;
1377     else if (f.allow_postdate){
1378         ret = KRB5KDC_ERR_POLICY;
1379         kdc_log(context, config, 0,
1380                 "Ticket may not be postdatable -- %s", client_name);
1381         goto out;
1382     }
1383
1384     /* check for valid set of addresses */
1385     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1386         ret = KRB5KRB_AP_ERR_BADADDR;
1387         kdc_log(context, config, 0,
1388                 "Bad address list requested -- %s", client_name);
1389         goto out;
1390     }
1391
1392     ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1393     if (ret)
1394         goto out;
1395     copy_PrincipalName(&rep.cname, &et.cname);
1396     copy_Realm(&rep.crealm, &et.crealm);
1397     
1398     {
1399         time_t start;
1400         time_t t;
1401         
1402         start = et.authtime = kdc_time;
1403     
1404         if(f.postdated && req->req_body.from){
1405             ALLOC(et.starttime);
1406             start = *et.starttime = *req->req_body.from;
1407             et.flags.invalid = 1;
1408             et.flags.postdated = 1; /* XXX ??? */
1409         }
1410         _kdc_fix_time(&b->till);
1411         t = *b->till;
1412
1413         /* be careful not overflowing */
1414
1415         if(client->entry.max_life)
1416             t = start + min(t - start, *client->entry.max_life);
1417         if(server->entry.max_life)
1418             t = start + min(t - start, *server->entry.max_life);
1419 #if 0
1420         t = min(t, start + realm->max_life);
1421 #endif
1422         et.endtime = t;
1423         if(f.renewable_ok && et.endtime < *b->till){
1424             f.renewable = 1;
1425             if(b->rtime == NULL){
1426                 ALLOC(b->rtime);
1427                 *b->rtime = 0;
1428             }
1429             if(*b->rtime < *b->till)
1430                 *b->rtime = *b->till;
1431         }
1432         if(f.renewable && b->rtime){
1433             t = *b->rtime;
1434             if(t == 0)
1435                 t = MAX_TIME;
1436             if(client->entry.max_renew)
1437                 t = start + min(t - start, *client->entry.max_renew);
1438             if(server->entry.max_renew)
1439                 t = start + min(t - start, *server->entry.max_renew);
1440 #if 0
1441             t = min(t, start + realm->max_renew);
1442 #endif
1443             ALLOC(et.renew_till);
1444             *et.renew_till = t;
1445             et.flags.renewable = 1;
1446         }
1447     }
1448
1449     if (f.request_anonymous)
1450         et.flags.anonymous = 1;
1451     
1452     if(b->addresses){
1453         ALLOC(et.caddr);
1454         copy_HostAddresses(b->addresses, et.caddr);
1455     }
1456     
1457     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1458     krb5_data_zero(&et.transited.contents); 
1459      
1460     copy_EncryptionKey(&et.key, &ek.key);
1461
1462     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1463      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1464      * incapable of correctly decoding SEQUENCE OF's of zero length.
1465      *
1466      * To fix this, always send at least one no-op last_req
1467      *
1468      * If there's a pw_end or valid_end we will use that,
1469      * otherwise just a dummy lr.
1470      */
1471     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1472     ek.last_req.len = 0;
1473     if (client->entry.pw_end
1474         && (config->kdc_warn_pwexpire == 0
1475             || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1476         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1477         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1478         ++ek.last_req.len;
1479     }
1480     if (client->entry.valid_end) {
1481         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1482         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1483         ++ek.last_req.len;
1484     }
1485     if (ek.last_req.len == 0) {
1486         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1487         ek.last_req.val[ek.last_req.len].lr_value = 0;
1488         ++ek.last_req.len;
1489     }
1490     ek.nonce = b->nonce;
1491     if (client->entry.valid_end || client->entry.pw_end) {
1492         ALLOC(ek.key_expiration);
1493         if (client->entry.valid_end) {
1494             if (client->entry.pw_end)
1495                 *ek.key_expiration = min(*client->entry.valid_end, 
1496                                          *client->entry.pw_end);
1497             else
1498                 *ek.key_expiration = *client->entry.valid_end;
1499         } else
1500             *ek.key_expiration = *client->entry.pw_end;
1501     } else
1502         ek.key_expiration = NULL;
1503     ek.flags = et.flags;
1504     ek.authtime = et.authtime;
1505     if (et.starttime) {
1506         ALLOC(ek.starttime);
1507         *ek.starttime = *et.starttime;
1508     }
1509     ek.endtime = et.endtime;
1510     if (et.renew_till) {
1511         ALLOC(ek.renew_till);
1512         *ek.renew_till = *et.renew_till;
1513     }
1514     copy_Realm(&rep.ticket.realm, &ek.srealm);
1515     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1516     if(et.caddr){
1517         ALLOC(ek.caddr);
1518         copy_HostAddresses(et.caddr, ek.caddr);
1519     }
1520
1521     ALLOC(rep.padata);
1522     rep.padata->len = 0;
1523     rep.padata->val = NULL;
1524
1525     reply_key = &ckey->key;
1526 #if PKINIT
1527     if (pkp) {
1528         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 
1529                                   req, req_buffer, 
1530                                   &reply_key, rep.padata);
1531         if (ret)
1532             goto out;
1533         ret = _kdc_add_inital_verified_cas(context,
1534                                            config,
1535                                            pkp,
1536                                            &et);
1537         if (ret)
1538             goto out;
1539     }
1540 #endif
1541
1542     set_salt_padata (rep.padata, ckey->salt);
1543
1544     if (rep.padata->len == 0) {
1545         free(rep.padata);
1546         rep.padata = NULL;
1547     }
1548
1549     /* Add the PAC */
1550     if (send_pac_p(context, req)) {
1551         krb5_pac p = NULL;
1552         krb5_data data;
1553
1554         ret = _kdc_pac_generate(context, client, &p);
1555         if (ret) {
1556             kdc_log(context, config, 0, "PAC generation failed for -- %s", 
1557                     client_name);
1558             goto out;
1559         }
1560         if (p != NULL) {
1561             ret = _krb5_pac_sign(context, p, et.authtime,
1562                                  client->entry.principal,
1563                                  &skey->key, /* Server key */ 
1564                                  &skey->key, /* FIXME: should be krbtgt key */
1565                                  &data);
1566             krb5_pac_free(context, p);
1567             if (ret) {
1568                 kdc_log(context, config, 0, "PAC signing failed for -- %s", 
1569                         client_name);
1570                 goto out;
1571             }
1572
1573             ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1574                                               KRB5_AUTHDATA_WIN2K_PAC,
1575                                               &data);
1576             krb5_data_free(&data);
1577             if (ret)
1578                 goto out;
1579         }
1580     }
1581
1582     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1583                        et.endtime, et.renew_till);
1584
1585     /* do this as the last thing since this signs the EncTicketPart */
1586     ret = _kdc_add_KRB5SignedPath(context,
1587                                   config,
1588                                   server,
1589                                   setype,
1590                                   NULL,
1591                                   NULL,
1592                                   &et);
1593     if (ret)
1594         goto out;
1595
1596     ret = _kdc_encode_reply(context, config, 
1597                             &rep, &et, &ek, setype, server->entry.kvno, 
1598                             &skey->key, client->entry.kvno, 
1599                             reply_key, &e_text, reply);
1600     free_EncTicketPart(&et);
1601     free_EncKDCRepPart(&ek);
1602     if (ret)
1603         goto out;
1604
1605     /* */
1606     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1607         krb5_data_free(reply);
1608         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1609         e_text = "Reply packet too large";
1610     }
1611
1612 out:
1613     free_AS_REP(&rep);
1614     if(ret){
1615         krb5_mk_error(context,
1616                       ret,
1617                       e_text,
1618                       NULL,
1619                       client_princ,
1620                       server_princ,
1621                       NULL,
1622                       NULL,
1623                       reply);
1624         ret = 0;
1625     }
1626 out2:
1627 #ifdef PKINIT
1628     if (pkp)
1629         _kdc_pk_free_client_param(context, pkp);
1630 #endif
1631     if (client_princ)
1632         krb5_free_principal(context, client_princ);
1633     free(client_name);
1634     if (server_princ)
1635         krb5_free_principal(context, server_princ);
1636     free(server_name);
1637     if(client)
1638         _kdc_free_ent(context, client);
1639     if(server)
1640         _kdc_free_ent(context, server);
1641     return ret;
1642 }
1643
1644 /*
1645  * Add the AuthorizationData `data´ of `type´ to the last element in
1646  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1647  */
1648
1649 krb5_error_code
1650 _kdc_tkt_add_if_relevant_ad(krb5_context context,
1651                             EncTicketPart *tkt,
1652                             int type,
1653                             const krb5_data *data)
1654 {
1655     krb5_error_code ret;
1656     size_t size;
1657
1658     if (tkt->authorization_data == NULL) {
1659         tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1660         if (tkt->authorization_data == NULL) {
1661             krb5_set_error_string(context, "out of memory");
1662             return ENOMEM;
1663         }
1664     }
1665         
1666     /* add the entry to the last element */
1667     {
1668         AuthorizationData ad = { 0, NULL };
1669         AuthorizationDataElement ade;
1670
1671         ade.ad_type = type;
1672         ade.ad_data = *data;
1673
1674         ret = add_AuthorizationData(&ad, &ade);
1675         if (ret) {
1676             krb5_set_error_string(context, "add AuthorizationData failed");
1677             return ret;
1678         }
1679
1680         ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1681
1682         ASN1_MALLOC_ENCODE(AuthorizationData, 
1683                            ade.ad_data.data, ade.ad_data.length, 
1684                            &ad, &size, ret);
1685         free_AuthorizationData(&ad);
1686         if (ret) {
1687             krb5_set_error_string(context, "ASN.1 encode of "
1688                                   "AuthorizationData failed");
1689             return ret;
1690         }
1691         if (ade.ad_data.length != size)
1692             krb5_abortx(context, "internal asn.1 encoder error");
1693         
1694         ret = add_AuthorizationData(tkt->authorization_data, &ade);
1695         der_free_octet_string(&ade.ad_data);
1696         if (ret) {
1697             krb5_set_error_string(context, "add AuthorizationData failed");
1698             return ret;
1699         }
1700     }
1701
1702     return 0;
1703 }