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