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