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