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