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