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