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