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