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