kdc: omit default salt from PA-ETYPE-INFO[2]
[metze/heimdal/wip.git] / 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 == (krb5_enctype)ETYPE_DES_CBC_CRC
96          || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
97          || etype == (krb5_enctype)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_principal request_princ, krb5_enctype *etypes, unsigned len,
129                 krb5_enctype *ret_enctype, Key **ret_key,
130                 krb5_boolean *ret_default_salt)
131 {
132     krb5_error_code ret;
133     krb5_salt def_salt;
134     krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
135     const krb5_enctype *p;
136     Key *key = NULL;
137     int i, k;
138
139     /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
140     ret = krb5_get_pw_salt(context, request_princ, &def_salt);
141     if (ret)
142         return ret;
143
144     ret = KRB5KDC_ERR_ETYPE_NOSUPP;
145
146     if (use_strongest_session_key) {
147
148         /*
149          * Pick the strongest key that the KDC, target service, and
150          * client all support, using the local cryptosystem enctype
151          * list in strongest-to-weakest order to drive the search.
152          *
153          * This is not what RFC4120 says to do, but it encourages
154          * adoption of stronger enctypes.  This doesn't play well with
155          * clients that have multiple Kerberos client implementations
156          * available with different supported enctype lists.
157          */
158
159         /* drive the search with local supported enctypes list */
160         p = krb5_kerberos_enctypes(context);
161         for (i = 0;
162             p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
163             i++) {
164             if (krb5_enctype_valid(context, p[i]) != 0 &&
165                 !_kdc_is_weak_exception(princ->entry.principal, p[i]))
166                 continue;
167
168             /* check that the client supports it too */
169             for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
170
171                 if (p[i] != etypes[k])
172                     continue;
173
174                 /* check target princ support */
175                 key = NULL;
176                 while (hdb_next_enctype2key(context, &princ->entry, NULL,
177                                              p[i], &key) == 0) {
178                     if (key->key.keyvalue.length == 0) {
179                         ret = KRB5KDC_ERR_NULL_KEY;
180                         continue;
181                     }
182                     enctype = p[i];
183                     ret = 0;
184                     if (is_preauth && ret_key != NULL &&
185                         !is_default_salt_p(&def_salt, key))
186                         continue;
187                 }
188             }
189         }
190     } else {
191         /*
192          * Pick the first key from the client's enctype list that is
193          * supported by the cryptosystem and by the given principal.
194          *
195          * RFC4120 says we SHOULD pick the first _strong_ key from the
196          * client's list... not the first key...  If the admin disallows
197          * weak enctypes in krb5.conf and selects this key selection
198          * algorithm, then we get exactly what RFC4120 says.
199          */
200         for(i = 0; ret != 0 && i < len; i++) {
201
202             if (krb5_enctype_valid(context, etypes[i]) != 0 &&
203                 !_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
204                 continue;
205
206             key = NULL;
207             while (ret != 0 &&
208                    hdb_next_enctype2key(context, &princ->entry, NULL,
209                                         etypes[i], &key) == 0) {
210                 if (key->key.keyvalue.length == 0) {
211                     ret = KRB5KDC_ERR_NULL_KEY;
212                     continue;
213                 }
214                 enctype = etypes[i];
215                 ret = 0;
216                 if (is_preauth && ret_key != NULL &&
217                     !is_default_salt_p(&def_salt, key))
218                     continue;
219             }
220         }
221     }
222
223     if (enctype == (krb5_enctype)ETYPE_NULL) {
224         /*
225          * if the service principal is one for which there is a known 1DES
226          * exception and no other enctype matches both the client request and
227          * the service key list, provide a DES-CBC-CRC key.
228          */
229         if (ret_key == NULL &&
230             _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
231             ret = 0;
232             enctype = ETYPE_DES_CBC_CRC;
233         } else {
234             ret = KRB5KDC_ERR_ETYPE_NOSUPP;
235         }
236     }
237
238     if (ret == 0) {
239         if (ret_enctype != NULL)
240             *ret_enctype = enctype;
241         if (ret_key != NULL)
242             *ret_key = key;
243         if (ret_default_salt != NULL)
244             *ret_default_salt = is_default_salt_p(&def_salt, key);
245     }
246
247     krb5_free_salt (context, def_salt);
248     return ret;
249 }
250
251 krb5_error_code
252 _kdc_make_anonymous_principalname (PrincipalName *pn)
253 {
254     pn->name_type = KRB5_NT_PRINCIPAL;
255     pn->name_string.len = 1;
256     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
257     if (pn->name_string.val == NULL)
258         return ENOMEM;
259     pn->name_string.val[0] = strdup("anonymous");
260     if (pn->name_string.val[0] == NULL) {
261         free(pn->name_string.val);
262         pn->name_string.val = NULL;
263         return ENOMEM;
264     }
265     return 0;
266 }
267
268 static void
269 _kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
270 {
271     va_list ap;
272     char *s;
273     va_start(ap, fmt);
274     s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
275     if(s) free(s);
276     va_end(ap);
277 }
278
279 static void
280 _kdc_set_e_text(kdc_request_t r, const char *e_text)
281 {
282     r->e_text = e_text;
283     kdc_log(r->context, r->config, 0, "%s", e_text);
284 }
285
286 void
287 _kdc_log_timestamp(krb5_context context,
288                    krb5_kdc_configuration *config,
289                    const char *type,
290                    KerberosTime authtime, KerberosTime *starttime,
291                    KerberosTime endtime, KerberosTime *renew_till)
292 {
293     char authtime_str[100], starttime_str[100],
294         endtime_str[100], renewtime_str[100];
295
296     krb5_format_time(context, authtime,
297                      authtime_str, sizeof(authtime_str), TRUE);
298     if (starttime)
299         krb5_format_time(context, *starttime,
300                          starttime_str, sizeof(starttime_str), TRUE);
301     else
302         strlcpy(starttime_str, "unset", sizeof(starttime_str));
303     krb5_format_time(context, endtime,
304                      endtime_str, sizeof(endtime_str), TRUE);
305     if (renew_till)
306         krb5_format_time(context, *renew_till,
307                          renewtime_str, sizeof(renewtime_str), TRUE);
308     else
309         strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
310
311     kdc_log(context, config, 5,
312             "%s authtime: %s starttime: %s endtime: %s renew till: %s",
313             type, authtime_str, starttime_str, endtime_str, renewtime_str);
314 }
315
316 /*
317  *
318  */
319
320 #ifdef PKINIT
321
322 static krb5_error_code
323 pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
324 {
325     pk_client_params *pkp = NULL;
326     char *client_cert = NULL;
327     krb5_error_code ret;
328
329     ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
330     if (ret || pkp == NULL) {
331         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
332         _kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s",
333                    r->client_name);
334         goto out;
335     }
336     
337     ret = _kdc_pk_check_client(r->context,
338                                r->config,
339                                r->clientdb, 
340                                r->client,
341                                pkp,
342                                &client_cert);
343     if (ret) {
344         _kdc_set_e_text(r, "PKINIT certificate not allowed to "
345                         "impersonate principal");
346         goto out;
347     }
348
349     _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s",
350                r->client_name, client_cert);
351     free(client_cert);
352
353     ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
354                               r->sessionetype, &r->req, &r->request,
355                               &r->reply_key, &r->session_key, &r->outpadata);
356     if (ret) {
357         _kdc_set_e_text(r, "Failed to build PK-INIT reply");
358         goto out;
359     }
360 #if 0
361     ret = _kdc_add_initial_verified_cas(r->context, r->config,
362                                         pkp, &r->et);
363 #endif
364  out:
365     if (pkp)
366         _kdc_pk_free_client_param(r->context, pkp);
367
368     return ret;
369 }
370
371 #endif /* PKINIT */
372
373 /*
374  *
375  */
376
377 static krb5_error_code
378 make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
379                       krb5_crypto crypto)
380 {
381     PA_ENC_TS_ENC p;
382     unsigned char *buf;
383     size_t buf_size;
384     size_t len;
385     EncryptedData encdata;
386     krb5_error_code ret;
387     int32_t usec;
388     int usec2;
389
390     krb5_us_timeofday (context, &p.patimestamp, &usec);
391     usec2         = usec;
392     p.pausec      = &usec2;
393
394     ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
395     if (ret)
396         return ret;
397     if(buf_size != len)
398         krb5_abortx(context, "internal error in ASN.1 encoder");
399
400     ret = krb5_encrypt_EncryptedData(context,
401                                      crypto,
402                                      KRB5_KU_ENC_CHALLENGE_KDC,
403                                      buf,
404                                      len,
405                                      0,
406                                      &encdata);
407     free(buf);
408     if (ret)
409         return ret;
410
411     ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
412     free_EncryptedData(&encdata);
413     if (ret)
414         return ret;
415     if(buf_size != len)
416         krb5_abortx(context, "internal error in ASN.1 encoder");
417
418     ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len);
419     if (ret)
420         free(buf);
421     return ret;
422 }
423
424 static krb5_error_code
425 pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
426 {
427     krb5_data pepper1, pepper2, ts_data;
428     KDC_REQ_BODY *b = &r->req.req_body;
429     int invalidPassword = 0;
430     EncryptedData enc_data;
431     krb5_enctype aenctype;
432     krb5_error_code ret;
433     struct Key *k;
434     size_t size;
435     int i;
436
437     heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
438     
439     if (_kdc_is_anon_request(b)) {
440         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
441         kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon");
442         return ret;
443     }
444
445     ret = decode_EncryptedData(pa->padata_value.data,
446                                pa->padata_value.length,
447                                &enc_data,
448                                &size);
449     if (ret) {
450         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
451         _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
452                    r->client_name);
453         return ret;
454     }
455
456     pepper1.data = "clientchallengearmor";
457     pepper1.length = strlen(pepper1.data);
458     pepper2.data = "challengelongterm";
459     pepper2.length = strlen(pepper2.data);
460
461     krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
462
463     for (i = 0; i < r->client->entry.keys.len; i++) {
464         krb5_crypto challangecrypto, longtermcrypto;
465         krb5_keyblock challangekey;
466         PA_ENC_TS_ENC p;
467
468         k = &r->client->entry.keys.val[i];
469         
470         ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
471         if (ret)
472             continue;                   
473         
474         ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
475                                  &pepper1, &pepper2, aenctype,
476                                  &challangekey);
477         krb5_crypto_destroy(r->context, longtermcrypto);
478         if (ret)
479             continue;
480         
481         ret = krb5_crypto_init(r->context, &challangekey, 0,
482                                &challangecrypto);
483         if (ret)
484             continue;
485         
486         ret = krb5_decrypt_EncryptedData(r->context, challangecrypto,
487                                          KRB5_KU_ENC_CHALLENGE_CLIENT,
488                                          &enc_data,
489                                          &ts_data);
490         if (ret) {
491             const char *msg = krb5_get_error_message(r->context, ret);
492             krb5_error_code ret2;
493             char *str = NULL;
494
495             invalidPassword = 1;
496
497             ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
498             if (ret2)
499                 str = NULL;
500             _kdc_r_log(r, 5, "Failed to decrypt ENC-CHAL -- %s "
501                        "(enctype %s) error %s",
502                        r->client_name, str ? str : "unknown enctype", msg);
503             krb5_free_error_message(r->context, msg);
504             free(str);
505
506             continue;
507         }
508         
509         ret = decode_PA_ENC_TS_ENC(ts_data.data,
510                                    ts_data.length,
511                                    &p,
512                                    &size);
513         krb5_data_free(&ts_data);
514         if(ret){
515             krb5_crypto_destroy(r->context, challangecrypto);
516             ret = KRB5KDC_ERR_PREAUTH_FAILED;
517             _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
518                        r->client_name);
519             continue;
520         }
521
522         if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
523             char client_time[100];
524
525             krb5_crypto_destroy(r->context, challangecrypto);
526
527             krb5_format_time(r->context, p.patimestamp,
528                              client_time, sizeof(client_time), TRUE);
529
530             ret = KRB5KRB_AP_ERR_SKEW;
531             _kdc_r_log(r, 0, "Too large time skew, "
532                        "client time %s is out by %u > %u seconds -- %s",
533                        client_time,
534                        (unsigned)labs(kdc_time - p.patimestamp),
535                        r->context->max_skew,
536                        r->client_name);
537
538             free_PA_ENC_TS_ENC(&p);
539             goto out;
540         }
541
542         free_PA_ENC_TS_ENC(&p);
543
544         ret = make_pa_enc_challange(r->context, &r->outpadata,
545                                     challangecrypto);
546         krb5_crypto_destroy(r->context, challangecrypto);
547         if (ret)
548             goto out;
549                                             
550         set_salt_padata(&r->outpadata, k->salt);
551         krb5_free_keyblock_contents(r->context,  &r->reply_key);
552         ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
553         if (ret)
554             goto out;
555
556         /*
557          * Success
558          */
559         if (r->clientdb->hdb_auth_status)
560             r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
561                                          HDB_AUTH_SUCCESS);
562         goto out;
563     }
564
565     if (invalidPassword && r->clientdb->hdb_auth_status) {
566         r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
567                                      HDB_AUTH_WRONG_PASSWORD);
568         ret = KRB5KDC_ERR_PREAUTH_FAILED;
569     }
570  out:
571     free_EncryptedData(&enc_data);
572
573     return ret;
574 }
575
576 static krb5_error_code
577 pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
578 {
579     EncryptedData enc_data;
580     krb5_error_code ret;
581     krb5_crypto crypto;
582     krb5_data ts_data;
583     PA_ENC_TS_ENC p;
584     size_t len;
585     Key *pa_key;
586     char *str;
587         
588     if (_kdc_is_anon_request(&r->req.req_body)) {
589         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
590         _kdc_set_e_text(r, "ENC-TS doesn't support anon");
591         goto out;
592     }
593
594     ret = decode_EncryptedData(pa->padata_value.data,
595                                pa->padata_value.length,
596                                &enc_data,
597                                &len);
598     if (ret) {
599         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
600         _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
601                    r->client_name);
602         goto out;
603     }
604         
605     ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
606                           enc_data.etype, &pa_key);
607     if(ret){
608         char *estr;
609         _kdc_set_e_text(r, "No key matching entype");
610         ret = KRB5KDC_ERR_ETYPE_NOSUPP;
611         if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
612             estr = NULL;
613         if(estr == NULL)
614             _kdc_r_log(r, 5,
615                        "No client key matching pa-data (%d) -- %s",
616                        enc_data.etype, r->client_name);
617         else
618             _kdc_r_log(r, 5,
619                        "No client key matching pa-data (%s) -- %s",
620                        estr, r->client_name);
621         free(estr);
622         free_EncryptedData(&enc_data);
623         goto out;
624     }
625
626  try_next_key:
627     ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
628     if (ret) {
629         const char *msg = krb5_get_error_message(r->context, ret);
630         _kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg);
631         krb5_free_error_message(r->context, msg);
632         free_EncryptedData(&enc_data);
633         goto out;
634     }
635
636     ret = krb5_decrypt_EncryptedData (r->context,
637                                       crypto,
638                                       KRB5_KU_PA_ENC_TIMESTAMP,
639                                       &enc_data,
640                                       &ts_data);
641     krb5_crypto_destroy(r->context, crypto);
642     /*
643      * Since the user might have several keys with the same
644      * enctype but with diffrent salting, we need to try all
645      * the keys with the same enctype.
646      */
647     if(ret){
648         krb5_error_code ret2;
649         const char *msg = krb5_get_error_message(r->context, ret);
650
651         ret2 = krb5_enctype_to_string(r->context,
652                                       pa_key->key.keytype, &str);
653         if (ret2)
654             str = NULL;
655         _kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s "
656                    "(enctype %s) error %s",
657                    r->client_name, str ? str : "unknown enctype", msg);
658         krb5_free_error_message(r->context, msg);
659         free(str);
660
661         if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
662                                 enc_data.etype, &pa_key) == 0)
663             goto try_next_key;
664
665         free_EncryptedData(&enc_data);
666
667         if (r->clientdb->hdb_auth_status)
668             r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
669                                          HDB_AUTH_WRONG_PASSWORD);
670
671         ret = KRB5KDC_ERR_PREAUTH_FAILED;
672         goto out;
673     }
674     free_EncryptedData(&enc_data);
675     ret = decode_PA_ENC_TS_ENC(ts_data.data,
676                                ts_data.length,
677                                &p,
678                                &len);
679     krb5_data_free(&ts_data);
680     if(ret){
681         ret = KRB5KDC_ERR_PREAUTH_FAILED;
682         _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
683                    r->client_name);
684         goto out;
685     }
686     if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
687         char client_time[100];
688                 
689         krb5_format_time(r->context, p.patimestamp,
690                          client_time, sizeof(client_time), TRUE);
691
692         ret = KRB5KRB_AP_ERR_SKEW;
693         _kdc_r_log(r, 0, "Too large time skew, "
694                    "client time %s is out by %u > %u seconds -- %s",
695                    client_time,
696                    (unsigned)labs(kdc_time - p.patimestamp),
697                    r->context->max_skew,
698                    r->client_name);
699
700         /*
701          * The following is needed to make windows clients to
702          * retry using the timestamp in the error message, if
703          * there is a e_text, they become unhappy.
704          */
705         r->e_text = NULL;
706         free_PA_ENC_TS_ENC(&p);
707         goto out;
708     }
709     free_PA_ENC_TS_ENC(&p);
710
711     set_salt_padata(&r->outpadata, pa_key->salt);
712
713     ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
714     if (ret)
715         return ret;
716
717     ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
718     if (ret)
719         str = NULL;
720     _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s",
721                r->client_name, str ? str : "unknown enctype");
722     free(str);
723
724     ret = 0;
725
726  out:
727
728     return ret;
729 }
730
731 struct kdc_patypes {
732     int type;
733     char *name;
734     unsigned int flags;
735 #define PA_ANNOUNCE     1
736 #define PA_REQ_FAST     2 /* only use inside fast */
737     krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
738 };
739
740 static const struct kdc_patypes pat[] = {
741 #ifdef PKINIT
742     {
743         KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
744         pa_pkinit_validate
745     },
746     {
747         KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
748         pa_pkinit_validate
749     },
750     {
751         KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
752         NULL
753     },
754 #else
755     { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
756     { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
757     { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL },
758 #endif
759     { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
760     { 
761         KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
762         PA_ANNOUNCE,
763         pa_enc_ts_validate
764     },
765     {
766         KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
767         PA_ANNOUNCE | PA_REQ_FAST,
768         pa_enc_chal_validate
769     },
770     { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
771     { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
772     { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
773     { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
774 };
775
776 static void
777 log_patypes(krb5_context context,
778             krb5_kdc_configuration *config,
779             METHOD_DATA *padata)
780 {
781     struct rk_strpool *p = NULL;
782     char *str;
783     size_t n, m;
784         
785     for (n = 0; n < padata->len; n++) {
786         for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
787             if (padata->val[n].padata_type == pat[m].type) {
788                 p = rk_strpoolprintf(p, "%s", pat[m].name);
789                 break;
790             }
791         }
792         if (m == sizeof(pat) / sizeof(pat[0]))
793             p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
794         if (p && n + 1 < padata->len)
795             p = rk_strpoolprintf(p, ", ");
796         if (p == NULL) {
797             kdc_log(context, config, 0, "out of memory");
798             return;
799         }
800     }
801     if (p == NULL)
802         p = rk_strpoolprintf(p, "none");
803
804     str = rk_strpoolcollect(p);
805     kdc_log(context, config, 0, "Client sent patypes: %s", str);
806     free(str);
807 }
808
809 /*
810  *
811  */
812
813 krb5_error_code
814 _kdc_encode_reply(krb5_context context,
815                   krb5_kdc_configuration *config,
816                   krb5_crypto armor_crypto, uint32_t nonce,
817                   KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
818                   krb5_enctype etype,
819                   int skvno, const EncryptionKey *skey,
820                   int ckvno, const EncryptionKey *reply_key,
821                   int rk_is_subkey,
822                   const char **e_text,
823                   krb5_data *reply)
824 {
825     unsigned char *buf;
826     size_t buf_size;
827     size_t len = 0;
828     krb5_error_code ret;
829     krb5_crypto crypto;
830
831     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
832     if(ret) {
833         const char *msg = krb5_get_error_message(context, ret);
834         kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
835         krb5_free_error_message(context, msg);
836         return ret;
837     }
838     if(buf_size != len)
839         krb5_abortx(context, "Internal error in ASN.1 encoder");
840
841     ret = krb5_crypto_init(context, skey, etype, &crypto);
842     if (ret) {
843         const char *msg = krb5_get_error_message(context, ret);
844         kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
845         krb5_free_error_message(context, msg);
846         free(buf);
847         return ret;
848     }
849
850     ret = krb5_encrypt_EncryptedData(context,
851                                      crypto,
852                                      KRB5_KU_TICKET,
853                                      buf,
854                                      len,
855                                      skvno,
856                                      &rep->ticket.enc_part);
857     free(buf);
858     krb5_crypto_destroy(context, crypto);
859     if(ret) {
860         const char *msg = krb5_get_error_message(context, ret);
861         kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
862         krb5_free_error_message(context, msg);
863         return ret;
864     }
865
866     if (armor_crypto) {
867         krb5_data data;
868         krb5_keyblock *strengthen_key = NULL;
869         KrbFastFinished finished;
870
871         kdc_log(context, config, 0, "FAST armor protection");
872
873         memset(&finished, 0, sizeof(finished));
874         krb5_data_zero(&data);
875
876         finished.timestamp = kdc_time;
877         finished.usec = 0;
878         finished.crealm = et->crealm;
879         finished.cname = et->cname;
880
881         ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
882                            &rep->ticket, &len, ret);
883         if (ret)
884             return ret;
885         if (data.length != len)
886             krb5_abortx(context, "internal asn.1 error");
887
888         ret = krb5_create_checksum(context, armor_crypto,
889                                    KRB5_KU_FAST_FINISHED, 0,
890                                    data.data, data.length,
891                                    &finished.ticket_checksum);
892         krb5_data_free(&data);
893         if (ret)
894             return ret;
895
896         ret = _kdc_fast_mk_response(context, armor_crypto,
897                                     rep->padata, strengthen_key, &finished,
898                                     nonce, &data);
899         free_Checksum(&finished.ticket_checksum);
900         if (ret)
901             return ret;
902
903         if (rep->padata) {
904             free_METHOD_DATA(rep->padata);
905         } else {
906             rep->padata = calloc(1, sizeof(*(rep->padata)));
907             if (rep->padata == NULL) {
908                 krb5_data_free(&data);
909                 return ENOMEM;
910             }
911         }
912
913         ret = krb5_padata_add(context, rep->padata,
914                               KRB5_PADATA_FX_FAST,
915                               data.data, data.length);
916         if (ret)
917             return ret;
918
919         /*
920          * Hide client name of privacy reasons
921          */
922         if (1 /* r->fast_options.hide_client_names */) {
923             rep->crealm[0] = '\0';
924             free_PrincipalName(&rep->cname);
925             rep->cname.name_type = 0;
926         }
927     }
928
929     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
930         ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
931     else
932         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
933     if(ret) {
934         const char *msg = krb5_get_error_message(context, ret);
935         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
936         krb5_free_error_message(context, msg);
937         return ret;
938     }
939     if(buf_size != len) {
940         free(buf);
941         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
942         *e_text = "KDC internal error";
943         return KRB5KRB_ERR_GENERIC;
944     }
945     ret = krb5_crypto_init(context, reply_key, 0, &crypto);
946     if (ret) {
947         const char *msg = krb5_get_error_message(context, ret);
948         free(buf);
949         kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
950         krb5_free_error_message(context, msg);
951         return ret;
952     }
953     if(rep->msg_type == krb_as_rep) {
954         krb5_encrypt_EncryptedData(context,
955                                    crypto,
956                                    KRB5_KU_AS_REP_ENC_PART,
957                                    buf,
958                                    len,
959                                    ckvno,
960                                    &rep->enc_part);
961         free(buf);
962         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
963     } else {
964         krb5_encrypt_EncryptedData(context,
965                                    crypto,
966                                    rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
967                                    buf,
968                                    len,
969                                    ckvno,
970                                    &rep->enc_part);
971         free(buf);
972         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
973     }
974     krb5_crypto_destroy(context, crypto);
975     if(ret) {
976         const char *msg = krb5_get_error_message(context, ret);
977         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
978         krb5_free_error_message(context, msg);
979         return ret;
980     }
981     if(buf_size != len) {
982         free(buf);
983         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
984         *e_text = "KDC internal error";
985         return KRB5KRB_ERR_GENERIC;
986     }
987     reply->data = buf;
988     reply->length = buf_size;
989     return 0;
990 }
991
992 /*
993  * Return 1 if the client have only older enctypes, this is for
994  * determining if the server should send ETYPE_INFO2 or not.
995  */
996
997 static int
998 older_enctype(krb5_enctype enctype)
999 {
1000     switch (enctype) {
1001     case ETYPE_DES_CBC_CRC:
1002     case ETYPE_DES_CBC_MD4:
1003     case ETYPE_DES_CBC_MD5:
1004     case ETYPE_DES3_CBC_SHA1:
1005     case ETYPE_ARCFOUR_HMAC_MD5:
1006     case ETYPE_ARCFOUR_HMAC_MD5_56:
1007     /*
1008      * The following three is "old" windows enctypes and is needed for
1009      * windows 2000 hosts.
1010      */
1011     case ETYPE_ARCFOUR_MD4:
1012     case ETYPE_ARCFOUR_HMAC_OLD:
1013     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
1014         return 1;
1015     default:
1016         return 0;
1017     }
1018 }
1019
1020 /*
1021  *
1022  */
1023
1024 static krb5_error_code
1025 make_etype_info_entry(krb5_context context,
1026                       ETYPE_INFO_ENTRY *ent,
1027                       Key *key,
1028                       krb5_boolean include_salt)
1029 {
1030     ent->etype = key->key.keytype;
1031     if (key->salt && include_salt){
1032 #if 0
1033         ALLOC(ent->salttype);
1034
1035         if(key->salt->type == hdb_pw_salt)
1036             *ent->salttype = 0; /* or 1? or NULL? */
1037         else if(key->salt->type == hdb_afs3_salt)
1038             *ent->salttype = 2;
1039         else {
1040             kdc_log(context, config, 0, "unknown salt-type: %d",
1041                     key->salt->type);
1042             return KRB5KRB_ERR_GENERIC;
1043         }
1044         /* according to `the specs', we can't send a salt if
1045            we have AFS3 salted key, but that requires that you
1046            *know* what cell you are using (e.g by assuming
1047            that the cell is the same as the realm in lower
1048            case) */
1049 #elif 0
1050         ALLOC(ent->salttype);
1051         *ent->salttype = key->salt->type;
1052 #else
1053         /*
1054          * We shouldn't sent salttype since it is incompatible with the
1055          * specification and it breaks windows clients.  The afs
1056          * salting problem is solved by using KRB5-PADATA-AFS3-SALT
1057          * implemented in Heimdal 0.7 and later.
1058          */
1059         ent->salttype = NULL;
1060 #endif
1061         krb5_copy_data(context, &key->salt->salt,
1062                        &ent->salt);
1063     } else {
1064         /* we return no salt type at all, as that should indicate
1065          * the default salt type and make everybody happy.  some
1066          * systems (like w2k) dislike being told the salt type
1067          * here. */
1068
1069         ent->salttype = NULL;
1070         ent->salt = NULL;
1071     }
1072     return 0;
1073 }
1074
1075 static krb5_error_code
1076 get_pa_etype_info(krb5_context context,
1077                   krb5_kdc_configuration *config,
1078                   METHOD_DATA *md, Key *ckey,
1079                   krb5_boolean include_salt)
1080 {
1081     krb5_error_code ret = 0;
1082     ETYPE_INFO pa;
1083     unsigned char *buf;
1084     size_t len;
1085
1086
1087     pa.len = 1;
1088     pa.val = calloc(1, sizeof(pa.val[0]));
1089     if(pa.val == NULL)
1090         return ENOMEM;
1091
1092     ret = make_etype_info_entry(context, &pa.val[0], ckey, include_salt);
1093     if (ret) {
1094         free_ETYPE_INFO(&pa);
1095         return ret;
1096     }
1097
1098     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
1099     free_ETYPE_INFO(&pa);
1100     if(ret)
1101         return ret;
1102     ret = realloc_method_data(md);
1103     if(ret) {
1104         free(buf);
1105         return ret;
1106     }
1107     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
1108     md->val[md->len - 1].padata_value.length = len;
1109     md->val[md->len - 1].padata_value.data = buf;
1110     return 0;
1111 }
1112
1113 /*
1114  *
1115  */
1116
1117 extern int _krb5_AES_SHA1_string_to_default_iterator;
1118 extern int _krb5_AES_SHA2_string_to_default_iterator;
1119
1120 static krb5_error_code
1121 make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1122 {
1123     krb5_data *s2kparams;
1124     krb5_error_code ret;
1125
1126     ALLOC(s2kparams);
1127     if (s2kparams == NULL)
1128         return ENOMEM;
1129     ret = krb5_data_alloc(s2kparams, len);
1130     if (ret) {
1131         free(s2kparams);
1132         return ret;
1133     }
1134     _krb5_put_int(s2kparams->data, value, len);
1135     *ps2kparams = s2kparams;
1136     return 0;
1137 }
1138
1139 static krb5_error_code
1140 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1141                        Key *key,
1142                        krb5_boolean include_salt)
1143 {
1144     krb5_error_code ret;
1145
1146     ent->etype = key->key.keytype;
1147     if (key->salt && include_salt) {
1148         ALLOC(ent->salt);
1149         if (ent->salt == NULL)
1150             return ENOMEM;
1151         *ent->salt = malloc(key->salt->salt.length + 1);
1152         if (*ent->salt == NULL) {
1153             free(ent->salt);
1154             ent->salt = NULL;
1155             return ENOMEM;
1156         }
1157         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1158         (*ent->salt)[key->salt->salt.length] = '\0';
1159     } else
1160         ent->salt = NULL;
1161
1162     ent->s2kparams = NULL;
1163
1164     switch (key->key.keytype) {
1165     case ETYPE_AES128_CTS_HMAC_SHA1_96:
1166     case ETYPE_AES256_CTS_HMAC_SHA1_96:
1167         ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1168                              4, &ent->s2kparams);
1169         break;
1170     case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1171     case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1172         ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1173                              4, &ent->s2kparams);
1174         break;
1175     case ETYPE_DES_CBC_CRC:
1176     case ETYPE_DES_CBC_MD4:
1177     case ETYPE_DES_CBC_MD5:
1178         /* Check if this was a AFS3 salted key */
1179         if(key->salt && key->salt->type == hdb_afs3_salt)
1180             ret = make_s2kparams(1, 1, &ent->s2kparams);
1181         else
1182             ret = 0;
1183         break;
1184     default:
1185         ret = 0;
1186         break;
1187     }
1188     return ret;
1189 }
1190
1191 /*
1192  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1193  * database (client supported enctypes first, then the unsupported
1194  * enctypes).
1195  */
1196
1197 static krb5_error_code
1198 get_pa_etype_info2(krb5_context context,
1199                    krb5_kdc_configuration *config,
1200                    METHOD_DATA *md, Key *ckey,
1201                    krb5_boolean include_salt)
1202 {
1203     krb5_error_code ret = 0;
1204     ETYPE_INFO2 pa;
1205     unsigned char *buf;
1206     size_t len;
1207
1208     pa.len = 1;
1209     pa.val = calloc(1, sizeof(pa.val[0]));
1210     if(pa.val == NULL)
1211         return ENOMEM;
1212
1213     ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1214     if (ret) {
1215         free_ETYPE_INFO2(&pa);
1216         return ret;
1217     }
1218
1219     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1220     free_ETYPE_INFO2(&pa);
1221     if(ret)
1222         return ret;
1223     ret = realloc_method_data(md);
1224     if(ret) {
1225         free(buf);
1226         return ret;
1227     }
1228     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1229     md->val[md->len - 1].padata_value.length = len;
1230     md->val[md->len - 1].padata_value.data = buf;
1231     return 0;
1232 }
1233
1234 static int
1235 newer_enctype_present(struct KDC_REQ_BODY_etype *etype_list)
1236 {
1237     size_t i;
1238
1239     for (i = 0; i < etype_list->len; i++) {
1240         if (!older_enctype(etype_list->val[i]))
1241             return 1;
1242     }
1243     return 0;
1244 }
1245
1246 static krb5_error_code
1247 get_pa_etype_info_both(krb5_context context,
1248                        krb5_kdc_configuration *config,
1249                        struct KDC_REQ_BODY_etype *etype_list,
1250                        METHOD_DATA *md, Key *ckey,
1251                        krb5_boolean include_salt)
1252 {
1253     krb5_error_code ret;
1254
1255     /*
1256      * RFC4120 requires:
1257      *   When the AS server is to include pre-authentication data in a
1258      *   KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1259      *   PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1260      *   at least one "newer" encryption type.  Otherwise (when the etype
1261      *   field of the client's AS-REQ does not list any "newer" encryption
1262      *   types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1263      *   with an entry for each enctype).  A "newer" enctype is any enctype
1264      *   first officially specified concurrently with or subsequent to the
1265      *   issue of this RFC.  The enctypes DES, 3DES, or RC4 and any defined
1266      *   in [RFC1510] are not "newer" enctypes.
1267      *
1268      * It goes on to state:
1269      *   The preferred ordering of the "hint" pre-authentication data that
1270      *   affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1271      *   followed by PW-SALT.  As noted in Section 3.1.3, a KDC MUST NOT send
1272      *   ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1273      *   "newer" etype.
1274      */
1275
1276     ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1277     if (ret)
1278         return ret;
1279
1280     if (!newer_enctype_present(etype_list))
1281         ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1282
1283     return ret;
1284 }
1285
1286 /*
1287  *
1288  */
1289
1290 static void
1291 log_as_req(krb5_context context,
1292            krb5_kdc_configuration *config,
1293            krb5_enctype cetype,
1294            krb5_enctype setype,
1295            const KDC_REQ_BODY *b)
1296 {
1297     krb5_error_code ret;
1298     struct rk_strpool *p;
1299     char *str;
1300     size_t i;
1301
1302     p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1303
1304     for (i = 0; i < b->etype.len; i++) {
1305         ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1306         if (ret == 0) {
1307             p = rk_strpoolprintf(p, "%s", str);
1308             free(str);
1309         } else
1310             p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1311         if (p && i + 1 < b->etype.len)
1312             p = rk_strpoolprintf(p, ", ");
1313         if (p == NULL) {
1314             kdc_log(context, config, 0, "out of memory");
1315             return;
1316         }
1317     }
1318     if (p == NULL)
1319         p = rk_strpoolprintf(p, "no encryption types");
1320
1321     {
1322         char *cet;
1323         char *set;
1324
1325         ret = krb5_enctype_to_string(context, cetype, &cet);
1326         if(ret == 0) {
1327             ret = krb5_enctype_to_string(context, setype, &set);
1328             if (ret == 0) {
1329                 p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1330                 free(set);
1331             }
1332             free(cet);
1333         }
1334         if (ret != 0)
1335             p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1336                                  cetype, setype);
1337     }
1338
1339     str = rk_strpoolcollect(p);
1340     kdc_log(context, config, 0, "%s", str);
1341     free(str);
1342
1343     {
1344         char fixedstr[128];
1345         unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1346                       fixedstr, sizeof(fixedstr));
1347         if(*fixedstr)
1348             kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
1349     }
1350 }
1351
1352 /*
1353  * verify the flags on `client' and `server', returning 0
1354  * if they are OK and generating an error messages and returning
1355  * and error code otherwise.
1356  */
1357
1358 krb5_error_code
1359 kdc_check_flags(krb5_context context,
1360                 krb5_kdc_configuration *config,
1361                 hdb_entry_ex *client_ex, const char *client_name,
1362                 hdb_entry_ex *server_ex, const char *server_name,
1363                 krb5_boolean is_as_req)
1364 {
1365     if(client_ex != NULL) {
1366         hdb_entry *client = &client_ex->entry;
1367
1368         /* check client */
1369         if (client->flags.locked_out) {
1370             kdc_log(context, config, 0,
1371                     "Client (%s) is locked out", client_name);
1372             return KRB5KDC_ERR_POLICY;
1373         }
1374
1375         if (client->flags.invalid) {
1376             kdc_log(context, config, 0,
1377                     "Client (%s) has invalid bit set", client_name);
1378             return KRB5KDC_ERR_POLICY;
1379         }
1380
1381         if(!client->flags.client){
1382             kdc_log(context, config, 0,
1383                     "Principal may not act as client -- %s", client_name);
1384             return KRB5KDC_ERR_POLICY;
1385         }
1386
1387         if (client->valid_start && *client->valid_start > kdc_time) {
1388             char starttime_str[100];
1389             krb5_format_time(context, *client->valid_start,
1390                              starttime_str, sizeof(starttime_str), TRUE);
1391             kdc_log(context, config, 0,
1392                     "Client not yet valid until %s -- %s",
1393                     starttime_str, client_name);
1394             return KRB5KDC_ERR_CLIENT_NOTYET;
1395         }
1396
1397         if (client->valid_end && *client->valid_end < kdc_time) {
1398             char endtime_str[100];
1399             krb5_format_time(context, *client->valid_end,
1400                              endtime_str, sizeof(endtime_str), TRUE);
1401             kdc_log(context, config, 0,
1402                     "Client expired at %s -- %s",
1403                     endtime_str, client_name);
1404             return KRB5KDC_ERR_NAME_EXP;
1405         }
1406
1407         if (client->flags.require_pwchange &&
1408             (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1409             kdc_log(context, config, 0,
1410                     "Client's key must be changed -- %s", client_name);
1411             return KRB5KDC_ERR_KEY_EXPIRED;
1412         }
1413
1414         if (client->pw_end && *client->pw_end < kdc_time
1415             && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1416             char pwend_str[100];
1417             krb5_format_time(context, *client->pw_end,
1418                              pwend_str, sizeof(pwend_str), TRUE);
1419             kdc_log(context, config, 0,
1420                     "Client's key has expired at %s -- %s",
1421                     pwend_str, client_name);
1422             return KRB5KDC_ERR_KEY_EXPIRED;
1423         }
1424     }
1425
1426     /* check server */
1427
1428     if (server_ex != NULL) {
1429         hdb_entry *server = &server_ex->entry;
1430
1431         if (server->flags.locked_out) {
1432             kdc_log(context, config, 0,
1433                     "Client server locked out -- %s", server_name);
1434             return KRB5KDC_ERR_POLICY;
1435         }
1436         if (server->flags.invalid) {
1437             kdc_log(context, config, 0,
1438                     "Server has invalid flag set -- %s", server_name);
1439             return KRB5KDC_ERR_POLICY;
1440         }
1441
1442         if(!server->flags.server){
1443             kdc_log(context, config, 0,
1444                     "Principal may not act as server -- %s", server_name);
1445             return KRB5KDC_ERR_POLICY;
1446         }
1447
1448         if(!is_as_req && server->flags.initial) {
1449             kdc_log(context, config, 0,
1450                     "AS-REQ is required for server -- %s", server_name);
1451             return KRB5KDC_ERR_POLICY;
1452         }
1453
1454         if (server->valid_start && *server->valid_start > kdc_time) {
1455             char starttime_str[100];
1456             krb5_format_time(context, *server->valid_start,
1457                              starttime_str, sizeof(starttime_str), TRUE);
1458             kdc_log(context, config, 0,
1459                     "Server not yet valid until %s -- %s",
1460                     starttime_str, server_name);
1461             return KRB5KDC_ERR_SERVICE_NOTYET;
1462         }
1463
1464         if (server->valid_end && *server->valid_end < kdc_time) {
1465             char endtime_str[100];
1466             krb5_format_time(context, *server->valid_end,
1467                              endtime_str, sizeof(endtime_str), TRUE);
1468             kdc_log(context, config, 0,
1469                     "Server expired at %s -- %s",
1470                     endtime_str, server_name);
1471             return KRB5KDC_ERR_SERVICE_EXP;
1472         }
1473
1474         if (server->pw_end && *server->pw_end < kdc_time) {
1475             char pwend_str[100];
1476             krb5_format_time(context, *server->pw_end,
1477                              pwend_str, sizeof(pwend_str), TRUE);
1478             kdc_log(context, config, 0,
1479                     "Server's key has expired at -- %s",
1480                     pwend_str, server_name);
1481             return KRB5KDC_ERR_KEY_EXPIRED;
1482         }
1483     }
1484     return 0;
1485 }
1486
1487 /*
1488  * Return TRUE if `from' is part of `addresses' taking into consideration
1489  * the configuration variables that tells us how strict we should be about
1490  * these checks
1491  */
1492
1493 krb5_boolean
1494 _kdc_check_addresses(krb5_context context,
1495                      krb5_kdc_configuration *config,
1496                      HostAddresses *addresses, const struct sockaddr *from)
1497 {
1498     krb5_error_code ret;
1499     krb5_address addr;
1500     krb5_boolean result;
1501     krb5_boolean only_netbios = TRUE;
1502     size_t i;
1503
1504     if(config->check_ticket_addresses == 0)
1505         return TRUE;
1506
1507     if(addresses == NULL)
1508         return config->allow_null_ticket_addresses;
1509
1510     for (i = 0; i < addresses->len; ++i) {
1511         if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
1512             only_netbios = FALSE;
1513         }
1514     }
1515
1516     /* Windows sends it's netbios name, which I can only assume is
1517      * used for the 'allowed workstations' check.  This is painful,
1518      * but we still want to check IP addresses if they happen to be
1519      * present.
1520      */
1521
1522     if(only_netbios)
1523         return config->allow_null_ticket_addresses;
1524
1525     ret = krb5_sockaddr2address (context, from, &addr);
1526     if(ret)
1527         return FALSE;
1528
1529     result = krb5_address_search(context, &addr, addresses);
1530     krb5_free_address (context, &addr);
1531     return result;
1532 }
1533
1534 /*
1535  *
1536  */
1537
1538 static krb5_boolean
1539 send_pac_p(krb5_context context, KDC_REQ *req)
1540 {
1541     krb5_error_code ret;
1542     PA_PAC_REQUEST pacreq;
1543     const PA_DATA *pa;
1544     int i = 0;
1545
1546     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
1547     if (pa == NULL)
1548         return TRUE;
1549
1550     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
1551                                 pa->padata_value.length,
1552                                 &pacreq,
1553                                 NULL);
1554     if (ret)
1555         return TRUE;
1556     i = pacreq.include_pac;
1557     free_PA_PAC_REQUEST(&pacreq);
1558     if (i == 0)
1559         return FALSE;
1560     return TRUE;
1561 }
1562
1563 /*
1564  *
1565  */
1566
1567 static krb5_error_code
1568 generate_pac(kdc_request_t r, Key *skey)
1569 {
1570     krb5_error_code ret;
1571     krb5_pac p = NULL;
1572     krb5_data data;
1573
1574     ret = _kdc_pac_generate(r->context, r->client, &p);
1575     if (ret) {
1576         _kdc_r_log(r, 0, "PAC generation failed for -- %s",
1577                    r->client_name);
1578         return ret;
1579     }
1580     if (p == NULL)
1581         return 0;
1582
1583     ret = _krb5_pac_sign(r->context, p, r->et.authtime,
1584                          r->client->entry.principal,
1585                          &skey->key, /* Server key */
1586                          &skey->key, /* FIXME: should be krbtgt key */
1587                          &data);
1588     krb5_pac_free(r->context, p);
1589     if (ret) {
1590         _kdc_r_log(r, 0, "PAC signing failed for -- %s",
1591                    r->client_name);
1592         return ret;
1593     }
1594     
1595     ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
1596                                       KRB5_AUTHDATA_WIN2K_PAC,
1597                                       &data);
1598     krb5_data_free(&data);
1599
1600     return ret;
1601 }
1602
1603 /*
1604  *
1605  */
1606
1607 krb5_boolean
1608 _kdc_is_anonymous(krb5_context context, krb5_principal principal)
1609 {
1610     if ((principal->name.name_type != KRB5_NT_WELLKNOWN &&
1611          principal->name.name_type != KRB5_NT_UNKNOWN) ||
1612         principal->name.name_string.len != 2 ||
1613         strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
1614         strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
1615         return 0;
1616     return 1;
1617 }
1618
1619 static int
1620 require_preauth_p(kdc_request_t r)
1621 {
1622     return r->config->require_preauth
1623         || r->client->entry.flags.require_preauth
1624         || r->server->entry.flags.require_preauth;
1625 }
1626
1627
1628 /*
1629  *
1630  */
1631
1632 static krb5_error_code
1633 add_enc_pa_rep(kdc_request_t r)
1634 {
1635     krb5_error_code ret;
1636     krb5_crypto crypto;
1637     Checksum checksum;
1638     krb5_data cdata;
1639     size_t len;
1640
1641     ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
1642     if (ret)
1643         return ret;
1644
1645     ret = krb5_create_checksum(r->context, crypto,
1646                                KRB5_KU_AS_REQ, 0,
1647                                r->request.data, r->request.length,
1648                                &checksum);
1649     krb5_crypto_destroy(r->context, crypto);
1650     if (ret)
1651         return ret;
1652
1653     ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
1654                        &checksum, &len, ret);
1655     free_Checksum(&checksum);
1656     if (ret)
1657         return ret;
1658     heim_assert(cdata.length == len, "ASN.1 internal error");
1659
1660     if (r->ek.encrypted_pa_data == NULL) {
1661         ALLOC(r->ek.encrypted_pa_data);
1662         if (r->ek.encrypted_pa_data == NULL)
1663             return ENOMEM;
1664     }
1665     ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1666                           KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
1667     if (ret)
1668         return ret;
1669     
1670     return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1671                            KRB5_PADATA_FX_FAST, NULL, 0);
1672 }
1673
1674 /*
1675  *
1676  */
1677
1678 krb5_error_code
1679 _kdc_as_rep(kdc_request_t r,
1680             krb5_data *reply,
1681             const char *from,
1682             struct sockaddr *from_addr,
1683             int datagram_reply)
1684 {
1685     krb5_context context = r->context;
1686     krb5_kdc_configuration *config = r->config;
1687     KDC_REQ *req = &r->req;
1688     KDC_REQ_BODY *b = NULL;
1689     AS_REP rep;
1690     KDCOptions f;
1691     krb5_enctype setype;
1692     krb5_error_code ret = 0;
1693     Key *skey;
1694     int found_pa = 0;
1695     int i, flags = HDB_F_FOR_AS_REQ;
1696     METHOD_DATA error_method;
1697     const PA_DATA *pa;
1698     krb5_boolean is_tgs;
1699
1700     memset(&rep, 0, sizeof(rep));
1701     error_method.len = 0;
1702     error_method.val = NULL;
1703
1704     /*
1705      * Look for FAST armor and unwrap
1706      */
1707     ret = _kdc_fast_unwrap_request(r);
1708     if (ret) {
1709         _kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
1710         goto out;
1711     }
1712
1713     b = &req->req_body;
1714     f = b->kdc_options;
1715
1716     if (f.canonicalize)
1717         flags |= HDB_F_CANON;
1718
1719     if(b->sname == NULL){
1720         ret = KRB5KRB_ERR_GENERIC;
1721         _kdc_set_e_text(r, "No server in request");
1722     } else{
1723         ret = _krb5_principalname2krb5_principal (context,
1724                                                   &r->server_princ,
1725                                                   *(b->sname),
1726                                                   b->realm);
1727         if (ret == 0)
1728             ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
1729     }
1730     if (ret) {
1731         kdc_log(context, config, 0,
1732                 "AS-REQ malformed server name from %s", from);
1733         goto out;
1734     }
1735     if(b->cname == NULL){
1736         ret = KRB5KRB_ERR_GENERIC;
1737         _kdc_set_e_text(r, "No client in request");
1738     } else {
1739         ret = _krb5_principalname2krb5_principal (context,
1740                                                   &r->client_princ,
1741                                                   *(b->cname),
1742                                                   b->realm);
1743         if (ret)
1744             goto out;
1745
1746         ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
1747     }
1748     if (ret) {
1749         kdc_log(context, config, 0,
1750                 "AS-REQ malformed client name from %s", from);
1751         goto out;
1752     }
1753
1754     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1755             r->client_name, from, r->server_name);
1756
1757     is_tgs = krb5_principal_is_krbtgt(context, r->server_princ);
1758
1759     /*
1760      *
1761      */
1762
1763     if (_kdc_is_anonymous(context, r->client_princ)) {
1764         if (!_kdc_is_anon_request(b)) {
1765             kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
1766             ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1767             goto out;
1768         }
1769     } else if (_kdc_is_anon_request(b)) {
1770         kdc_log(context, config, 0,
1771                 "Request for a anonymous ticket with non "
1772                 "anonymous client name: %s", r->client_name);
1773         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1774         goto out;
1775     }
1776
1777     /*
1778      *
1779      */
1780
1781     ret = _kdc_db_fetch(context, config, r->client_princ,
1782                         HDB_F_GET_CLIENT | flags, NULL,
1783                         &r->clientdb, &r->client);
1784     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1785         kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
1786                 r->client_name);
1787         goto out;
1788     } else if (ret == HDB_ERR_WRONG_REALM) {
1789         char *fixed_client_name = NULL;
1790
1791         ret = krb5_unparse_name(context, r->client->entry.principal,
1792                                 &fixed_client_name);
1793         if (ret) {
1794             goto out;
1795         }
1796
1797         kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
1798                 r->client_name, fixed_client_name);
1799         free(fixed_client_name);
1800
1801         ret = _kdc_fast_mk_error(context, r,
1802                                  &error_method,
1803                                  r->armor_crypto,
1804                                  &req->req_body,
1805                                  KRB5_KDC_ERR_WRONG_REALM,
1806                                  NULL,
1807                                  r->server_princ,
1808                                  NULL,
1809                                  &r->client->entry.principal->realm,
1810                                  NULL, NULL,
1811                                  reply);
1812         goto out;
1813     } else if(ret){
1814         const char *msg = krb5_get_error_message(context, ret);
1815         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
1816         krb5_free_error_message(context, msg);
1817         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1818         goto out;
1819     }
1820     ret = _kdc_db_fetch(context, config, r->server_princ,
1821                         HDB_F_GET_SERVER | flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
1822                         NULL, NULL, &r->server);
1823     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1824         kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
1825                 r->server_name);
1826         goto out;
1827     } else if(ret){
1828         const char *msg = krb5_get_error_message(context, ret);
1829         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
1830         krb5_free_error_message(context, msg);
1831         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1832         goto out;
1833     }
1834
1835     /*
1836      * Select a session enctype from the list of the crypto system
1837      * supported enctypes that is supported by the client and is one of
1838      * the enctype of the enctype of the service (likely krbtgt).
1839      *
1840      * The latter is used as a hint of what enctypes all KDC support,
1841      * to make sure a newer version of KDC won't generate a session
1842      * enctype that an older version of a KDC in the same realm can't
1843      * decrypt.
1844      */
1845
1846     ret = _kdc_find_etype(context,
1847                           is_tgs ? config->tgt_use_strongest_session_key
1848                                  : config->svc_use_strongest_session_key,
1849                           FALSE, r->client, r->client_princ,
1850                           b->etype.val, b->etype.len,
1851                           &r->sessionetype, NULL, NULL);
1852     if (ret) {
1853         kdc_log(context, config, 0,
1854                 "Client (%s) from %s has no common enctypes with KDC "
1855                 "to use for the session key",
1856                 r->client_name, from);
1857         goto out;
1858     }
1859
1860     /*
1861      * Pre-auth processing
1862      */
1863
1864     if(req->padata){
1865         unsigned int n;
1866
1867         log_patypes(context, config, req->padata);
1868
1869         /* Check if preauth matching */
1870
1871         for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
1872             if (pat[n].validate == NULL)
1873                 continue;
1874             if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
1875                 continue;
1876
1877             kdc_log(context, config, 5,
1878                     "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
1879             i = 0;
1880             pa = _kdc_find_padata(req, &i, pat[n].type);
1881             if (pa) {
1882                 ret = pat[n].validate(r, pa);
1883                 if (ret != 0) {
1884                     krb5_error_code  ret2;
1885                     Key *ckey = NULL;
1886                     krb5_boolean default_salt;
1887
1888                     /*
1889                      * If there is a client key, send ETYPE_INFO{,2}
1890                      */
1891                     ret2 = _kdc_find_etype(context,
1892                                            config->preauth_use_strongest_session_key,
1893                                            TRUE, r->client, r->client_princ, b->etype.val,
1894                                            b->etype.len, NULL, &ckey, &default_salt);
1895                     if (ret2 == 0) {
1896                         ret2 = get_pa_etype_info_both(context, config, &b->etype,
1897                                                       &error_method, ckey, !default_salt);
1898                         if (ret2 != 0)
1899                             ret = ret2;
1900                     }
1901                     goto out;
1902                 }
1903                 kdc_log(context, config, 0,
1904                         "%s pre-authentication succeeded -- %s",
1905                         pat[n].name, r->client_name);
1906                 found_pa = 1;
1907                 r->et.flags.pre_authent = 1;
1908             }
1909         }
1910     }
1911
1912     if (found_pa == 0) {
1913         Key *ckey = NULL;
1914         size_t n;
1915         krb5_boolean default_salt;
1916
1917         for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
1918             if ((pat[n].flags & PA_ANNOUNCE) == 0)
1919                 continue;
1920             ret = krb5_padata_add(context, &error_method,
1921                                   pat[n].type, NULL, 0);
1922             if (ret)
1923                 goto out;
1924         }
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                               r->client, r->client_princ,
1932                               b->etype.val, b->etype.len, NULL,
1933                               &ckey, &default_salt);
1934         if (ret == 0) {
1935             ret = get_pa_etype_info_both(context, config, &b->etype,
1936                                          &error_method, ckey, !default_salt);
1937             if (ret)
1938                 goto out;
1939         }
1940
1941         /* 
1942          * send requre preauth is its required or anon is requested,
1943          * anon is today only allowed via preauth mechanisms.
1944          */
1945         if (require_preauth_p(r) || _kdc_is_anon_request(b)) {
1946             ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1947             _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
1948             goto out;
1949         }
1950
1951         if (ckey == NULL) {
1952             ret = KRB5KDC_ERR_CLIENT_NOTYET;
1953             _kdc_set_e_text(r, "Doesn't have a client key available");
1954             goto out;
1955         }
1956         krb5_free_keyblock_contents(r->context,  &r->reply_key);
1957         ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
1958         if (ret)
1959             goto out;
1960     }
1961
1962     if (r->clientdb->hdb_auth_status) {
1963         r->clientdb->hdb_auth_status(context, r->clientdb, r->client, 
1964                                      HDB_AUTH_SUCCESS);
1965     }
1966
1967     /*
1968      * Verify flags after the user been required to prove its identity
1969      * with in a preauth mech.
1970      */
1971
1972     ret = _kdc_check_access(context, config, r->client, r->client_name,
1973                             r->server, r->server_name,
1974                             req, &error_method);
1975     if(ret)
1976         goto out;
1977
1978     /*
1979      * Select the best encryption type for the KDC with out regard to
1980      * the client since the client never needs to read that data.
1981      */
1982
1983     ret = _kdc_get_preferred_key(context, config,
1984                                  r->server, r->server_name,
1985                                  &setype, &skey);
1986     if(ret)
1987         goto out;
1988
1989     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1990        || (_kdc_is_anon_request(b) && !config->allow_anonymous)) {
1991         ret = KRB5KDC_ERR_BADOPTION;
1992         _kdc_set_e_text(r, "Bad KDC options");
1993         goto out;
1994     }
1995
1996     /*
1997      * Build reply
1998      */
1999
2000     rep.pvno = 5;
2001     rep.msg_type = krb_as_rep;
2002
2003     if (_kdc_is_anonymous(context, r->client_princ)) {
2004         Realm anon_realm=KRB5_ANON_REALM;
2005         ret = copy_Realm(&anon_realm, &rep.crealm);
2006     } else if (f.canonicalize || r->client->entry.flags.force_canonicalize)
2007         ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
2008     else
2009         ret = copy_Realm(&r->client_princ->realm, &rep.crealm);
2010     if (ret)
2011         goto out;
2012     if (f.canonicalize || r->client->entry.flags.force_canonicalize)
2013         ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
2014     else
2015         ret = _krb5_principal2principalname(&rep.cname, r->client_princ);
2016     if (ret)
2017         goto out;
2018
2019     rep.ticket.tkt_vno = 5;
2020     if (f.canonicalize || r->server->entry.flags.force_canonicalize)
2021         ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
2022     else
2023         ret = copy_Realm(&r->server_princ->realm, &rep.ticket.realm);
2024     if (ret)
2025         goto out;
2026     if (f.canonicalize || r->server->entry.flags.force_canonicalize)
2027         _krb5_principal2principalname(&rep.ticket.sname,
2028                                       r->server->entry.principal);
2029     else
2030         _krb5_principal2principalname(&rep.ticket.sname,
2031                                       r->server_princ);
2032     /* java 1.6 expects the name to be the same type, lets allow that
2033      * uncomplicated name-types. */
2034 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2035     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
2036         rep.ticket.sname.name_type = b->sname->name_type;
2037 #undef CNT
2038
2039     r->et.flags.initial = 1;
2040     if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
2041         r->et.flags.forwardable = f.forwardable;
2042     else if (f.forwardable) {
2043         _kdc_set_e_text(r, "Ticket may not be forwardable");
2044         ret = KRB5KDC_ERR_POLICY;
2045         goto out;
2046     }
2047     if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
2048         r->et.flags.proxiable = f.proxiable;
2049     else if (f.proxiable) {
2050         _kdc_set_e_text(r, "Ticket may not be proxiable");
2051         ret = KRB5KDC_ERR_POLICY;
2052         goto out;
2053     }
2054     if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
2055         r->et.flags.may_postdate = f.allow_postdate;
2056     else if (f.allow_postdate){
2057         _kdc_set_e_text(r, "Ticket may not be postdate");
2058         ret = KRB5KDC_ERR_POLICY;
2059         goto out;
2060     }
2061
2062     /* check for valid set of addresses */
2063     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
2064         _kdc_set_e_text(r, "Bad address list in requested");
2065         ret = KRB5KRB_AP_ERR_BADADDR;
2066         goto out;
2067     }
2068
2069     ret = copy_PrincipalName(&rep.cname, &r->et.cname);
2070     if (ret)
2071         goto out;
2072     ret = copy_Realm(&rep.crealm, &r->et.crealm);
2073     if (ret)
2074         goto out;
2075
2076     {
2077         time_t start;
2078         time_t t;
2079         
2080         start = r->et.authtime = kdc_time;
2081
2082         if(f.postdated && req->req_body.from){
2083             ALLOC(r->et.starttime);
2084             start = *r->et.starttime = *req->req_body.from;
2085             r->et.flags.invalid = 1;
2086             r->et.flags.postdated = 1; /* XXX ??? */
2087         }
2088         _kdc_fix_time(&b->till);
2089         t = *b->till;
2090
2091         /* be careful not overflowing */
2092
2093         if(r->client->entry.max_life)
2094             t = start + min(t - start, *r->client->entry.max_life);
2095         if(r->server->entry.max_life)
2096             t = start + min(t - start, *r->server->entry.max_life);
2097 #if 0
2098         t = min(t, start + realm->max_life);
2099 #endif
2100         r->et.endtime = t;
2101         if(f.renewable_ok && r->et.endtime < *b->till){
2102             f.renewable = 1;
2103             if(b->rtime == NULL){
2104                 ALLOC(b->rtime);
2105                 *b->rtime = 0;
2106             }
2107             if(*b->rtime < *b->till)
2108                 *b->rtime = *b->till;
2109         }
2110         if(f.renewable && b->rtime){
2111             t = *b->rtime;
2112             if(t == 0)
2113                 t = MAX_TIME;
2114             if(r->client->entry.max_renew)
2115                 t = start + min(t - start, *r->client->entry.max_renew);
2116             if(r->server->entry.max_renew)
2117                 t = start + min(t - start, *r->server->entry.max_renew);
2118 #if 0
2119             t = min(t, start + realm->max_renew);
2120 #endif
2121             ALLOC(r->et.renew_till);
2122             *r->et.renew_till = t;
2123             r->et.flags.renewable = 1;
2124         }
2125     }
2126
2127     if (_kdc_is_anon_request(b))
2128         r->et.flags.anonymous = 1;
2129
2130     if(b->addresses){
2131         ALLOC(r->et.caddr);
2132         copy_HostAddresses(b->addresses, r->et.caddr);
2133     }
2134
2135     r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
2136     krb5_data_zero(&r->et.transited.contents);
2137
2138     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
2139      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
2140      * incapable of correctly decoding SEQUENCE OF's of zero length.
2141      *
2142      * To fix this, always send at least one no-op last_req
2143      *
2144      * If there's a pw_end or valid_end we will use that,
2145      * otherwise just a dummy lr.
2146      */
2147     r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
2148     if (r->ek.last_req.val == NULL) {
2149         ret = ENOMEM;
2150         goto out;
2151     }
2152     r->ek.last_req.len = 0;
2153     if (r->client->entry.pw_end
2154         && (config->kdc_warn_pwexpire == 0
2155             || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
2156         r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
2157         r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
2158         ++r->ek.last_req.len;
2159     }
2160     if (r->client->entry.valid_end) {
2161         r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
2162         r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
2163         ++r->ek.last_req.len;
2164     }
2165     if (r->ek.last_req.len == 0) {
2166         r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_NONE;
2167         r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
2168         ++r->ek.last_req.len;
2169     }
2170     r->ek.nonce = b->nonce;
2171     if (r->client->entry.valid_end || r->client->entry.pw_end) {
2172         ALLOC(r->ek.key_expiration);
2173         if (r->client->entry.valid_end) {
2174             if (r->client->entry.pw_end)
2175                 *r->ek.key_expiration = min(*r->client->entry.valid_end,
2176                                          *r->client->entry.pw_end);
2177             else
2178                 *r->ek.key_expiration = *r->client->entry.valid_end;
2179         } else
2180             *r->ek.key_expiration = *r->client->entry.pw_end;
2181     } else
2182         r->ek.key_expiration = NULL;
2183     r->ek.flags = r->et.flags;
2184     r->ek.authtime = r->et.authtime;
2185     if (r->et.starttime) {
2186         ALLOC(r->ek.starttime);
2187         *r->ek.starttime = *r->et.starttime;
2188     }
2189     r->ek.endtime = r->et.endtime;
2190     if (r->et.renew_till) {
2191         ALLOC(r->ek.renew_till);
2192         *r->ek.renew_till = *r->et.renew_till;
2193     }
2194     ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
2195     if (ret)
2196         goto out;
2197     ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
2198     if (ret)
2199         goto out;
2200     if(r->et.caddr){
2201         ALLOC(r->ek.caddr);
2202         copy_HostAddresses(r->et.caddr, r->ek.caddr);
2203     }
2204
2205     /*
2206      * Check and session and reply keys
2207      */
2208
2209     if (r->session_key.keytype == ETYPE_NULL) {
2210         ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
2211         if (ret)
2212             goto out;
2213     }
2214
2215     if (r->reply_key.keytype == ETYPE_NULL) {
2216         _kdc_set_e_text(r, "Client have no reply key");
2217         ret = KRB5KDC_ERR_CLIENT_NOTYET;
2218         goto out;
2219     }
2220
2221     ret = copy_EncryptionKey(&r->session_key, &r->et.key);
2222     if (ret)
2223         goto out;
2224
2225     ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
2226     if (ret)
2227         goto out;
2228
2229     if (r->outpadata.len) {
2230
2231         ALLOC(rep.padata);
2232         if (rep.padata == NULL) {
2233             ret = ENOMEM;
2234             goto out;
2235         }
2236         ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
2237         if (ret)
2238             goto out;
2239     }
2240
2241     /* Add the PAC */
2242     if (send_pac_p(context, req)) {
2243         generate_pac(r, skey);
2244     }
2245
2246     _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
2247                        r->et.endtime, r->et.renew_till);
2248
2249     /* do this as the last thing since this signs the EncTicketPart */
2250     ret = _kdc_add_KRB5SignedPath(context,
2251                                   config,
2252                                   r->server,
2253                                   setype,
2254                                   r->client->entry.principal,
2255                                   NULL,
2256                                   NULL,
2257                                   &r->et);
2258     if (ret)
2259         goto out;
2260
2261     log_as_req(context, config, r->reply_key.keytype, setype, b);
2262
2263     /*
2264      * We always say we support FAST/enc-pa-rep
2265      */
2266
2267     r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
2268
2269     /*
2270      * Add REQ_ENC_PA_REP if client supports it
2271      */
2272
2273     i = 0;
2274     pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
2275     if (pa) {
2276
2277         ret = add_enc_pa_rep(r);
2278         if (ret) {
2279             const char *msg = krb5_get_error_message(r->context, ret);
2280             _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
2281             krb5_free_error_message(r->context, msg);
2282             goto out;
2283         }
2284     }
2285
2286     /*
2287      *
2288      */
2289
2290     ret = _kdc_encode_reply(context, config,
2291                             r->armor_crypto, req->req_body.nonce,
2292                             &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
2293                             &skey->key, r->client->entry.kvno,
2294                             &r->reply_key, 0, &r->e_text, reply);
2295     if (ret)
2296         goto out;
2297
2298     /*
2299      * Check if message too large
2300      */
2301     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
2302         krb5_data_free(reply);
2303         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2304         _kdc_set_e_text(r, "Reply packet too large");
2305     }
2306
2307 out:
2308     free_AS_REP(&rep);
2309
2310     /*
2311      * In case of a non proxy error, build an error message.
2312      */
2313     if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
2314         ret = _kdc_fast_mk_error(context, r,
2315                                  &error_method,
2316                                  r->armor_crypto,
2317                                  &req->req_body,
2318                                  ret, r->e_text,
2319                                  r->server_princ,
2320                                  r->client_princ ?
2321                                      &r->client_princ->name : NULL,
2322                                  r->client_princ ?
2323                                      &r->client_princ->realm : NULL,
2324                                  NULL, NULL,
2325                                  reply);
2326         if (ret)
2327             goto out2;
2328     }
2329 out2:
2330     free_EncTicketPart(&r->et);
2331     free_EncKDCRepPart(&r->ek);
2332     free_KDCFastState(&r->fast);
2333
2334     if (error_method.len)
2335         free_METHOD_DATA(&error_method);
2336     if (r->outpadata.len)
2337         free_METHOD_DATA(&r->outpadata);
2338     if (r->client_princ) {
2339         krb5_free_principal(context, r->client_princ);
2340         r->client_princ = NULL;
2341     }
2342     if (r->client_name) {
2343         free(r->client_name);
2344         r->client_name = NULL;
2345     }
2346     if (r->server_princ){
2347         krb5_free_principal(context, r->server_princ);
2348         r->server_princ = NULL;
2349     }
2350     if (r->server_name) {
2351         free(r->server_name);
2352         r->server_name = NULL;
2353     }
2354     if (r->client)
2355         _kdc_free_ent(context, r->client);
2356     if (r->server)
2357         _kdc_free_ent(context, r->server);
2358     if (r->armor_crypto) {
2359         krb5_crypto_destroy(r->context, r->armor_crypto);
2360         r->armor_crypto = NULL;
2361     }
2362     krb5_free_keyblock_contents(r->context, &r->reply_key);
2363     krb5_free_keyblock_contents(r->context, &r->session_key);
2364     return ret;
2365 }
2366
2367 /*
2368  * Add the AuthorizationData `data´ of `type´ to the last element in
2369  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
2370  */
2371
2372 krb5_error_code
2373 _kdc_tkt_add_if_relevant_ad(krb5_context context,
2374                             EncTicketPart *tkt,
2375                             int type,
2376                             const krb5_data *data)
2377 {
2378     krb5_error_code ret;
2379     size_t size = 0;
2380
2381     if (tkt->authorization_data == NULL) {
2382         tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
2383         if (tkt->authorization_data == NULL) {
2384             krb5_set_error_message(context, ENOMEM, "out of memory");
2385             return ENOMEM;
2386         }
2387     }
2388
2389     /* add the entry to the last element */
2390     {
2391         AuthorizationData ad = { 0, NULL };
2392         AuthorizationDataElement ade;
2393
2394         ade.ad_type = type;
2395         ade.ad_data = *data;
2396
2397         ret = add_AuthorizationData(&ad, &ade);
2398         if (ret) {
2399             krb5_set_error_message(context, ret, "add AuthorizationData failed");
2400             return ret;
2401         }
2402
2403         ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
2404
2405         ASN1_MALLOC_ENCODE(AuthorizationData,
2406                            ade.ad_data.data, ade.ad_data.length,
2407                            &ad, &size, ret);
2408         free_AuthorizationData(&ad);
2409         if (ret) {
2410             krb5_set_error_message(context, ret, "ASN.1 encode of "
2411                                    "AuthorizationData failed");
2412             return ret;
2413         }
2414         if (ade.ad_data.length != size)
2415             krb5_abortx(context, "internal asn.1 encoder error");
2416
2417         ret = add_AuthorizationData(tkt->authorization_data, &ade);
2418         der_free_octet_string(&ade.ad_data);
2419         if (ret) {
2420             krb5_set_error_message(context, ret, "add AuthorizationData failed");
2421             return ret;
2422         }
2423     }
2424
2425     return 0;
2426 }
2427
2428 krb5_boolean
2429 _kdc_is_anon_request(const KDC_REQ_BODY *b)
2430 {
2431         /* some versions of heimdal use bit 14 instead of 16 for
2432            request_anonymous, as indicated in the anonymous draft prior to
2433            version 11. Bit 14 is assigned to S4U2Proxy, but all S4U2Proxy
2434            requests will have a second ticket; don't consider those anonymous */
2435         return (b->kdc_options.request_anonymous ||
2436                 (b->kdc_options.constrained_delegation && !b->additional_tickets));
2437 }