heimdal: Add parameter to windc_plugin to allow extended return codes.
[samba.git] / source4 / heimdal / 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 RCSID("$Id: kerberos5.c 21529 2007-07-13 12:37:14Z lha $");
37
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39
40 void
41 _kdc_fix_time(time_t **t)
42 {
43     if(*t == NULL){
44         ALLOC(*t);
45         **t = MAX_TIME;
46     }
47     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
48 }
49
50 static int
51 realloc_method_data(METHOD_DATA *md)
52 {
53     PA_DATA *pa;
54     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
55     if(pa == NULL)
56         return ENOMEM;
57     md->val = pa;
58     md->len++;
59     return 0;
60 }
61
62 static void
63 set_salt_padata (METHOD_DATA *md, Salt *salt)
64 {
65     if (salt) {
66         realloc_method_data(md);
67         md->val[md->len - 1].padata_type = salt->type;
68         der_copy_octet_string(&salt->salt,
69                               &md->val[md->len - 1].padata_value);
70     }
71 }
72
73 const PA_DATA*
74 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
75 {
76     if (req->padata == NULL)
77         return NULL;
78
79     while(*start < req->padata->len){
80         (*start)++;
81         if(req->padata->val[*start - 1].padata_type == type)
82             return &req->padata->val[*start - 1];
83     }
84     return NULL;
85 }
86
87 /*
88  * Detect if `key' is the using the the precomputed `default_salt'.
89  */
90
91 static krb5_boolean
92 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
93 {
94     if (key->salt == NULL)
95         return TRUE;
96     if (default_salt->salttype != key->salt->type)
97         return FALSE;
98     if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
99         return FALSE;
100     return TRUE;
101 }
102
103 /*
104  * return the first appropriate key of `princ' in `ret_key'.  Look for
105  * all the etypes in (`etypes', `len'), stopping as soon as we find
106  * one, but preferring one that has default salt
107  */
108
109 krb5_error_code
110 _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ,
111                 krb5_enctype *etypes, unsigned len, 
112                 Key **ret_key, krb5_enctype *ret_etype)
113 {
114     int i;
115     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
116     krb5_salt def_salt;
117
118     krb5_get_pw_salt (context, princ->entry.principal, &def_salt);
119
120     for(i = 0; ret != 0 && i < len ; i++) {
121         Key *key = NULL;
122
123         if (krb5_enctype_valid(context, etypes[i]) != 0)
124             continue;
125
126         while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
127             if (key->key.keyvalue.length == 0) {
128                 ret = KRB5KDC_ERR_NULL_KEY;
129                 continue;
130             }
131             *ret_key   = key;
132             *ret_etype = etypes[i];
133             ret = 0;
134             if (is_default_salt_p(&def_salt, key)) {
135                 krb5_free_salt (context, def_salt);
136                 return ret;
137             }
138         }
139     }
140     krb5_free_salt (context, def_salt);
141     return ret;
142 }
143
144 krb5_error_code
145 _kdc_make_anonymous_principalname (PrincipalName *pn)
146 {
147     pn->name_type = KRB5_NT_PRINCIPAL;
148     pn->name_string.len = 1;
149     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
150     if (pn->name_string.val == NULL)
151         return ENOMEM;
152     pn->name_string.val[0] = strdup("anonymous");
153     if (pn->name_string.val[0] == NULL) {
154         free(pn->name_string.val);
155         pn->name_string.val = NULL;
156         return ENOMEM;
157     }
158     return 0;
159 }
160
161 void
162 _kdc_log_timestamp(krb5_context context, 
163                    krb5_kdc_configuration *config,
164                    const char *type,
165                    KerberosTime authtime, KerberosTime *starttime, 
166                    KerberosTime endtime, KerberosTime *renew_till)
167 {
168     char authtime_str[100], starttime_str[100], 
169         endtime_str[100], renewtime_str[100];
170     
171     krb5_format_time(context, authtime, 
172                      authtime_str, sizeof(authtime_str), TRUE); 
173     if (starttime)
174         krb5_format_time(context, *starttime, 
175                          starttime_str, sizeof(starttime_str), TRUE); 
176     else
177         strlcpy(starttime_str, "unset", sizeof(starttime_str));
178     krb5_format_time(context, endtime, 
179                      endtime_str, sizeof(endtime_str), TRUE); 
180     if (renew_till)
181         krb5_format_time(context, *renew_till, 
182                          renewtime_str, sizeof(renewtime_str), TRUE); 
183     else
184         strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
185     
186     kdc_log(context, config, 5,
187             "%s authtime: %s starttime: %s endtime: %s renew till: %s",
188             type, authtime_str, starttime_str, endtime_str, renewtime_str);
189 }
190
191 static void
192 log_patypes(krb5_context context, 
193             krb5_kdc_configuration *config,
194             METHOD_DATA *padata)
195 {
196     struct rk_strpool *p = NULL;
197     char *str;
198     int i;
199             
200     for (i = 0; i < padata->len; i++) {
201         switch(padata->val[i].padata_type) {
202         case KRB5_PADATA_PK_AS_REQ:
203             p = rk_strpoolprintf(p, "PK-INIT(ietf)");
204             break;
205         case KRB5_PADATA_PK_AS_REQ_WIN:
206             p = rk_strpoolprintf(p, "PK-INIT(win2k)");
207             break;
208         case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
209             p = rk_strpoolprintf(p, "OCSP");
210             break;
211         case KRB5_PADATA_ENC_TIMESTAMP:
212             p = rk_strpoolprintf(p, "encrypted-timestamp");
213             break;
214         default:
215             p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
216             break;
217         }
218         if (p && i + 1 < padata->len)
219             p = rk_strpoolprintf(p, ", ");
220         if (p == NULL) {
221             kdc_log(context, config, 0, "out of memory");
222             return;
223         }
224     }
225     if (p == NULL)
226         p = rk_strpoolprintf(p, "none");
227         
228     str = rk_strpoolcollect(p);
229     kdc_log(context, config, 0, "Client sent patypes: %s", str);
230     free(str);
231 }
232
233 /*
234  *
235  */
236
237
238 krb5_error_code
239 _kdc_encode_reply(krb5_context context,
240                   krb5_kdc_configuration *config,
241                   KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, 
242                   krb5_enctype etype, 
243                   int skvno, const EncryptionKey *skey,
244                   int ckvno, const EncryptionKey *ckey,
245                   const char **e_text,
246                   krb5_data *reply)
247 {
248     unsigned char *buf;
249     size_t buf_size;
250     size_t len;
251     krb5_error_code ret;
252     krb5_crypto crypto;
253
254     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
255     if(ret) {
256         kdc_log(context, config, 0, "Failed to encode ticket: %s", 
257                 krb5_get_err_text(context, ret));
258         return ret;
259     }
260     if(buf_size != len) {
261         free(buf);
262         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
263         *e_text = "KDC internal error";
264         return KRB5KRB_ERR_GENERIC;
265     }
266
267     ret = krb5_crypto_init(context, skey, etype, &crypto);
268     if (ret) {
269         free(buf);
270         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
271                 krb5_get_err_text(context, ret));
272         return ret;
273     }
274
275     ret = krb5_encrypt_EncryptedData(context, 
276                                      crypto,
277                                      KRB5_KU_TICKET,
278                                      buf,
279                                      len,
280                                      skvno,
281                                      &rep->ticket.enc_part);
282     free(buf);
283     krb5_crypto_destroy(context, crypto);
284     if(ret) {
285         kdc_log(context, config, 0, "Failed to encrypt data: %s",
286                 krb5_get_err_text(context, ret));
287         return ret;
288     }
289     
290     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
291         ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
292     else
293         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
294     if(ret) {
295         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
296                 krb5_get_err_text(context, ret));
297         return ret;
298     }
299     if(buf_size != len) {
300         free(buf);
301         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
302         *e_text = "KDC internal error";
303         return KRB5KRB_ERR_GENERIC;
304     }
305     ret = krb5_crypto_init(context, ckey, 0, &crypto);
306     if (ret) {
307         free(buf);
308         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
309                 krb5_get_err_text(context, ret));
310         return ret;
311     }
312     if(rep->msg_type == krb_as_rep) {
313         krb5_encrypt_EncryptedData(context,
314                                    crypto,
315                                    KRB5_KU_AS_REP_ENC_PART,
316                                    buf,
317                                    len,
318                                    ckvno,
319                                    &rep->enc_part);
320         free(buf);
321         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
322     } else {
323         krb5_encrypt_EncryptedData(context,
324                                    crypto,
325                                    KRB5_KU_TGS_REP_ENC_PART_SESSION,
326                                    buf,
327                                    len,
328                                    ckvno,
329                                    &rep->enc_part);
330         free(buf);
331         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
332     }
333     krb5_crypto_destroy(context, crypto);
334     if(ret) {
335         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
336                 krb5_get_err_text(context, ret));
337         return ret;
338     }
339     if(buf_size != len) {
340         free(buf);
341         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
342         *e_text = "KDC internal error";
343         return KRB5KRB_ERR_GENERIC;
344     }
345     reply->data = buf;
346     reply->length = buf_size;
347     return 0;
348 }
349
350 /*
351  * Return 1 if the client have only older enctypes, this is for
352  * determining if the server should send ETYPE_INFO2 or not.
353  */
354
355 static int
356 older_enctype(krb5_enctype enctype)
357 {
358     switch (enctype) {
359     case ETYPE_DES_CBC_CRC:
360     case ETYPE_DES_CBC_MD4:
361     case ETYPE_DES_CBC_MD5:
362     case ETYPE_DES3_CBC_SHA1:
363     case ETYPE_ARCFOUR_HMAC_MD5:
364     case ETYPE_ARCFOUR_HMAC_MD5_56:
365         return 1;
366     default:
367         return 0;
368     }
369 }
370
371 static int
372 only_older_enctype_p(const KDC_REQ *req)
373 {
374     int i;
375
376     for(i = 0; i < req->req_body.etype.len; i++) {
377         if (!older_enctype(req->req_body.etype.val[i]))
378             return 0;
379     }
380     return 1;
381 }
382
383 /*
384  *
385  */
386
387 static krb5_error_code
388 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
389 {
390     ent->etype = key->key.keytype;
391     if(key->salt){
392 #if 0
393         ALLOC(ent->salttype);
394
395         if(key->salt->type == hdb_pw_salt)
396             *ent->salttype = 0; /* or 1? or NULL? */
397         else if(key->salt->type == hdb_afs3_salt)
398             *ent->salttype = 2;
399         else {
400             kdc_log(context, config, 0, "unknown salt-type: %d", 
401                     key->salt->type);
402             return KRB5KRB_ERR_GENERIC;
403         }
404         /* according to `the specs', we can't send a salt if
405            we have AFS3 salted key, but that requires that you
406            *know* what cell you are using (e.g by assuming
407            that the cell is the same as the realm in lower
408            case) */
409 #elif 0
410         ALLOC(ent->salttype);
411         *ent->salttype = key->salt->type;
412 #else
413         /* 
414          * We shouldn't sent salttype since its incompatible with the
415          * specification and its break windows clients.  The afs
416          * salting problem is solved by using KRB5-PADATA-AFS3-SALT
417          * implemented in Heimdal 0.7 and later.
418          */
419         ent->salttype = NULL;
420 #endif
421         krb5_copy_data(context, &key->salt->salt,
422                        &ent->salt);
423     } else {
424         /* we return no salt type at all, as that should indicate
425          * the default salt type and make everybody happy.  some
426          * systems (like w2k) dislike being told the salt type
427          * here. */
428
429         ent->salttype = NULL;
430         ent->salt = NULL;
431     }
432     return 0;
433 }
434
435 static krb5_error_code
436 get_pa_etype_info(krb5_context context, 
437                   krb5_kdc_configuration *config,
438                   METHOD_DATA *md, hdb_entry *client, 
439                   ENCTYPE *etypes, unsigned int etypes_len)
440 {
441     krb5_error_code ret = 0;
442     int i, j;
443     unsigned int n = 0;
444     ETYPE_INFO pa;
445     unsigned char *buf;
446     size_t len;
447     
448
449     pa.len = client->keys.len;
450     if(pa.len > UINT_MAX/sizeof(*pa.val))
451         return ERANGE;
452     pa.val = malloc(pa.len * sizeof(*pa.val));
453     if(pa.val == NULL)
454         return ENOMEM;
455     memset(pa.val, 0, pa.len * sizeof(*pa.val));
456
457     for(i = 0; i < client->keys.len; i++) {
458         for (j = 0; j < n; j++)
459             if (pa.val[j].etype == client->keys.val[i].key.keytype)
460                 goto skip1;
461         for(j = 0; j < etypes_len; j++) {
462             if(client->keys.val[i].key.keytype == etypes[j]) {
463                 if (krb5_enctype_valid(context, etypes[j]) != 0)
464                     continue;
465                 if (!older_enctype(etypes[j]))
466                     continue;
467                 if (n >= pa.len)
468                     krb5_abortx(context, "internal error: n >= p.len");
469                 if((ret = make_etype_info_entry(context, 
470                                                 &pa.val[n++], 
471                                                 &client->keys.val[i])) != 0) {
472                     free_ETYPE_INFO(&pa);
473                     return ret;
474                 }
475             }
476         }
477     skip1:;
478     }
479     for(i = 0; i < client->keys.len; i++) {
480         for(j = 0; j < etypes_len; j++) {
481             if(client->keys.val[i].key.keytype == etypes[j])
482                 goto skip2;
483         }
484         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
485             continue;
486         if (!older_enctype(etypes[j]))
487             continue;
488         if (n >= pa.len)
489             krb5_abortx(context, "internal error: n >= p.len");
490         if((ret = make_etype_info_entry(context, 
491                                         &pa.val[n++], 
492                                         &client->keys.val[i])) != 0) {
493             free_ETYPE_INFO(&pa);
494             return ret;
495         }
496     skip2:;
497     }
498     
499     if(n < pa.len) {
500         /* stripped out newer enctypes */
501         pa.len = n;
502     }
503
504     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
505     free_ETYPE_INFO(&pa);
506     if(ret)
507         return ret;
508     ret = realloc_method_data(md);
509     if(ret) {
510         free(buf);
511         return ret;
512     }
513     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
514     md->val[md->len - 1].padata_value.length = len;
515     md->val[md->len - 1].padata_value.data = buf;
516     return 0;
517 }
518
519 /*
520  *
521  */
522
523 extern int _krb5_AES_string_to_default_iterator;
524
525 static krb5_error_code
526 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
527 {
528     ent->etype = key->key.keytype;
529     if(key->salt) {
530         ALLOC(ent->salt);
531         if (ent->salt == NULL)
532             return ENOMEM;
533         *ent->salt = malloc(key->salt->salt.length + 1);
534         if (*ent->salt == NULL) {
535             free(ent->salt);
536             ent->salt = NULL;
537             return ENOMEM;
538         }
539         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
540         (*ent->salt)[key->salt->salt.length] = '\0';
541     } else
542         ent->salt = NULL;
543
544     ent->s2kparams = NULL;
545
546     switch (key->key.keytype) {
547     case ETYPE_AES128_CTS_HMAC_SHA1_96:
548     case ETYPE_AES256_CTS_HMAC_SHA1_96:
549         ALLOC(ent->s2kparams);
550         if (ent->s2kparams == NULL)
551             return ENOMEM;
552         ent->s2kparams->length = 4;
553         ent->s2kparams->data = malloc(ent->s2kparams->length);
554         if (ent->s2kparams->data == NULL) {
555             free(ent->s2kparams);
556             ent->s2kparams = NULL;
557             return ENOMEM;
558         }
559         _krb5_put_int(ent->s2kparams->data, 
560                       _krb5_AES_string_to_default_iterator, 
561                       ent->s2kparams->length);
562         break;
563     case ETYPE_DES_CBC_CRC:
564     case ETYPE_DES_CBC_MD4:
565     case ETYPE_DES_CBC_MD5:
566         /* Check if this was a AFS3 salted key */
567         if(key->salt && key->salt->type == hdb_afs3_salt){
568             ALLOC(ent->s2kparams);
569             if (ent->s2kparams == NULL)
570                 return ENOMEM;
571             ent->s2kparams->length = 1;
572             ent->s2kparams->data = malloc(ent->s2kparams->length);
573             if (ent->s2kparams->data == NULL) {
574                 free(ent->s2kparams);
575                 ent->s2kparams = NULL;
576                 return ENOMEM;
577             }
578             _krb5_put_int(ent->s2kparams->data, 
579                           1,
580                           ent->s2kparams->length);
581         }
582         break;
583     default:
584         break;
585     }
586     return 0;
587 }
588
589 /*
590  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
591  * database (client supported enctypes first, then the unsupported
592  * enctypes).
593  */
594
595 static krb5_error_code
596 get_pa_etype_info2(krb5_context context, 
597                    krb5_kdc_configuration *config,
598                    METHOD_DATA *md, hdb_entry *client, 
599                    ENCTYPE *etypes, unsigned int etypes_len)
600 {
601     krb5_error_code ret = 0;
602     int i, j;
603     unsigned int n = 0;
604     ETYPE_INFO2 pa;
605     unsigned char *buf;
606     size_t len;
607
608     pa.len = client->keys.len;
609     if(pa.len > UINT_MAX/sizeof(*pa.val))
610         return ERANGE;
611     pa.val = malloc(pa.len * sizeof(*pa.val));
612     if(pa.val == NULL)
613         return ENOMEM;
614     memset(pa.val, 0, pa.len * sizeof(*pa.val));
615
616     for(i = 0; i < client->keys.len; i++) {
617         for (j = 0; j < n; j++)
618             if (pa.val[j].etype == client->keys.val[i].key.keytype)
619                 goto skip1;
620         for(j = 0; j < etypes_len; j++) {
621             if(client->keys.val[i].key.keytype == etypes[j]) {
622                 if (krb5_enctype_valid(context, etypes[j]) != 0)
623                     continue;
624                 if((ret = make_etype_info2_entry(&pa.val[n++], 
625                                                  &client->keys.val[i])) != 0) {
626                     free_ETYPE_INFO2(&pa);
627                     return ret;
628                 }
629             }
630         }
631     skip1:;
632     }
633     /* send enctypes that the cliene doesn't know about too */
634     for(i = 0; i < client->keys.len; i++) {
635         for(j = 0; j < etypes_len; j++) {
636             if(client->keys.val[i].key.keytype == etypes[j])
637                 goto skip2;
638         }
639         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
640             continue;
641         if((ret = make_etype_info2_entry(&pa.val[n++],
642                                          &client->keys.val[i])) != 0) {
643             free_ETYPE_INFO2(&pa);
644             return ret;
645         }
646       skip2:;
647     }
648     
649     if(n != pa.len) {
650         char *name;
651         ret = krb5_unparse_name(context, client->principal, &name);
652         if (ret)
653             name = rk_UNCONST("<unparse_name failed>");
654         kdc_log(context, config, 0,
655                 "internal error in get_pa_etype_info2(%s): %d != %d", 
656                 name, n, pa.len);
657         if (ret == 0)
658             free(name);
659         pa.len = n;
660     }
661
662     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
663     free_ETYPE_INFO2(&pa);
664     if(ret)
665         return ret;
666     ret = realloc_method_data(md);
667     if(ret) {
668         free(buf);
669         return ret;
670     }
671     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
672     md->val[md->len - 1].padata_value.length = len;
673     md->val[md->len - 1].padata_value.data = buf;
674     return 0;
675 }
676
677 /*
678  *
679  */
680
681 static void
682 log_as_req(krb5_context context,
683            krb5_kdc_configuration *config,
684            krb5_enctype cetype,
685            krb5_enctype setype,
686            const KDC_REQ_BODY *b)
687 {
688     krb5_error_code ret;
689     struct rk_strpool *p = NULL;
690     char *str;
691     int i;
692     
693     for (i = 0; i < b->etype.len; i++) {
694         ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
695         if (ret == 0) {
696             p = rk_strpoolprintf(p, "%s", str);
697             free(str);
698         } else
699             p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
700         if (p && i + 1 < b->etype.len)
701             p = rk_strpoolprintf(p, ", ");
702         if (p == NULL) {
703             kdc_log(context, config, 0, "out of memory");
704             return;
705         }
706     }
707     if (p == NULL)
708         p = rk_strpoolprintf(p, "no encryption types");
709     
710     str = rk_strpoolcollect(p);
711     kdc_log(context, config, 0, "Client supported enctypes: %s", str);
712     free(str);
713
714     {
715         char *cet;
716         char *set;
717
718         ret = krb5_enctype_to_string(context, cetype, &cet);
719         if(ret == 0) {
720             ret = krb5_enctype_to_string(context, setype, &set);
721             if (ret == 0) {
722                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
723                 free(set);
724             }
725             free(cet);
726         }
727         if (ret != 0)
728             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
729     }
730     
731     {
732         char fixedstr[128];
733         unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(), 
734                       fixedstr, sizeof(fixedstr));
735         if(*fixedstr)
736             kdc_log(context, config, 2, "Requested flags: %s", fixedstr);
737     }
738 }
739
740 /*
741  * verify the flags on `client' and `server', returning 0
742  * if they are OK and generating an error messages and returning
743  * and error code otherwise.
744  */
745
746 krb5_error_code
747 _kdc_check_flags(krb5_context context, 
748                  krb5_kdc_configuration *config,
749                  hdb_entry_ex *client_ex, const char *client_name,
750                  hdb_entry_ex *server_ex, const char *server_name,
751                  krb5_boolean is_as_req)
752 {
753     if(client_ex != NULL) {
754         hdb_entry *client = &client_ex->entry;
755
756         /* check client */
757         if (client->flags.invalid) {
758             kdc_log(context, config, 0, 
759                     "Client (%s) has invalid bit set", client_name);
760             return KRB5KDC_ERR_POLICY;
761         }
762         
763         if(!client->flags.client){
764             kdc_log(context, config, 0,
765                     "Principal may not act as client -- %s", client_name);
766             return KRB5KDC_ERR_POLICY;
767         }
768         
769         if (client->valid_start && *client->valid_start > kdc_time) {
770             char starttime_str[100];
771             krb5_format_time(context, *client->valid_start, 
772                              starttime_str, sizeof(starttime_str), TRUE); 
773             kdc_log(context, config, 0,
774                     "Client not yet valid until %s -- %s", 
775                     starttime_str, client_name);
776             return KRB5KDC_ERR_CLIENT_NOTYET;
777         }
778         
779         if (client->valid_end && *client->valid_end < kdc_time) {
780             char endtime_str[100];
781             krb5_format_time(context, *client->valid_end, 
782                              endtime_str, sizeof(endtime_str), TRUE); 
783             kdc_log(context, config, 0,
784                     "Client expired at %s -- %s",
785                     endtime_str, client_name);
786             return KRB5KDC_ERR_NAME_EXP;
787         }
788         
789         if (client->pw_end && *client->pw_end < kdc_time 
790             && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
791             char pwend_str[100];
792             krb5_format_time(context, *client->pw_end, 
793                              pwend_str, sizeof(pwend_str), TRUE); 
794             kdc_log(context, config, 0,
795                     "Client's key has expired at %s -- %s", 
796                     pwend_str, client_name);
797             return KRB5KDC_ERR_KEY_EXPIRED;
798         }
799     }
800
801     /* check server */
802     
803     if (server_ex != NULL) {
804         hdb_entry *server = &server_ex->entry;
805
806         if (server->flags.invalid) {
807             kdc_log(context, config, 0,
808                     "Server has invalid flag set -- %s", server_name);
809             return KRB5KDC_ERR_POLICY;
810         }
811
812         if(!server->flags.server){
813             kdc_log(context, config, 0,
814                     "Principal may not act as server -- %s", server_name);
815             return KRB5KDC_ERR_POLICY;
816         }
817
818         if(!is_as_req && server->flags.initial) {
819             kdc_log(context, config, 0,
820                     "AS-REQ is required for server -- %s", server_name);
821             return KRB5KDC_ERR_POLICY;
822         }
823
824         if (server->valid_start && *server->valid_start > kdc_time) {
825             char starttime_str[100];
826             krb5_format_time(context, *server->valid_start, 
827                              starttime_str, sizeof(starttime_str), TRUE); 
828             kdc_log(context, config, 0,
829                     "Server not yet valid until %s -- %s",
830                     starttime_str, server_name);
831             return KRB5KDC_ERR_SERVICE_NOTYET;
832         }
833
834         if (server->valid_end && *server->valid_end < kdc_time) {
835             char endtime_str[100];
836             krb5_format_time(context, *server->valid_end, 
837                              endtime_str, sizeof(endtime_str), TRUE); 
838             kdc_log(context, config, 0,
839                     "Server expired at %s -- %s", 
840                     endtime_str, server_name);
841             return KRB5KDC_ERR_SERVICE_EXP;
842         }
843
844         if (server->pw_end && *server->pw_end < kdc_time) {
845             char pwend_str[100];
846             krb5_format_time(context, *server->pw_end, 
847                              pwend_str, sizeof(pwend_str), TRUE); 
848             kdc_log(context, config, 0,
849                     "Server's key has expired at -- %s", 
850                     pwend_str, server_name);
851             return KRB5KDC_ERR_KEY_EXPIRED;
852         }
853     }
854     return 0;
855 }
856
857 /*
858  * Return TRUE if `from' is part of `addresses' taking into consideration
859  * the configuration variables that tells us how strict we should be about
860  * these checks
861  */
862
863 krb5_boolean
864 _kdc_check_addresses(krb5_context context,        
865                      krb5_kdc_configuration *config,
866                      HostAddresses *addresses, const struct sockaddr *from)
867 {
868     krb5_error_code ret;
869     krb5_address addr;
870     krb5_boolean result;
871     krb5_boolean only_netbios = TRUE;
872     int i;
873     
874     if(config->check_ticket_addresses == 0)
875         return TRUE;
876
877     if(addresses == NULL)
878         return config->allow_null_ticket_addresses;
879     
880     for (i = 0; i < addresses->len; ++i) {
881         if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
882             only_netbios = FALSE;
883         }
884     }
885
886     /* Windows sends it's netbios name, which I can only assume is
887      * used for the 'allowed workstations' check.  This is painful,
888      * but we still want to check IP addresses if they happen to be
889      * present.
890      */
891
892     if(only_netbios)
893         return config->allow_null_ticket_addresses;
894
895     ret = krb5_sockaddr2address (context, from, &addr);
896     if(ret)
897         return FALSE;
898
899     result = krb5_address_search(context, &addr, addresses);
900     krb5_free_address (context, &addr);
901     return result;
902 }
903
904 /*
905  *
906  */
907
908 static krb5_boolean
909 send_pac_p(krb5_context context, KDC_REQ *req)
910 {
911     krb5_error_code ret;
912     PA_PAC_REQUEST pacreq;
913     const PA_DATA *pa;
914     int i = 0;
915     
916     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
917     if (pa == NULL)
918         return TRUE;
919
920     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
921                                 pa->padata_value.length,
922                                 &pacreq,
923                                 NULL);
924     if (ret)
925         return TRUE;
926     i = pacreq.include_pac;
927     free_PA_PAC_REQUEST(&pacreq);
928     if (i == 0)
929         return FALSE;
930     return TRUE;
931 }
932
933 /*
934  *
935  */
936
937 krb5_error_code
938 _kdc_as_rep(krb5_context context, 
939             krb5_kdc_configuration *config,
940             KDC_REQ *req, 
941             const krb5_data *req_buffer, 
942             krb5_data *reply,
943             const char *from,
944             struct sockaddr *from_addr,
945             int datagram_reply)
946 {
947     KDC_REQ_BODY *b = &req->req_body;
948     AS_REP rep;
949     KDCOptions f = b->kdc_options;
950     hdb_entry_ex *client = NULL, *server = NULL;
951     krb5_enctype cetype, setype, sessionetype;
952     krb5_data e_data;
953     EncTicketPart et;
954     EncKDCRepPart ek;
955     krb5_principal client_princ = NULL, server_princ = NULL;
956     char *client_name = NULL, *server_name = NULL;
957     krb5_error_code ret = 0;
958     const char *e_text = NULL;
959     krb5_crypto crypto;
960     Key *ckey, *skey;
961     EncryptionKey *reply_key;
962     int flags = 0;
963 #ifdef PKINIT
964     pk_client_params *pkp = NULL;
965 #endif
966
967     memset(&rep, 0, sizeof(rep));
968     krb5_data_zero(&e_data);
969
970     if (f.canonicalize)
971         flags |= HDB_F_CANON;
972
973     if(b->sname == NULL){
974         ret = KRB5KRB_ERR_GENERIC;
975         e_text = "No server in request";
976     } else{
977         ret = _krb5_principalname2krb5_principal (context,
978                                                   &server_princ,
979                                                   *(b->sname),
980                                                   b->realm);
981         if (ret == 0)
982             ret = krb5_unparse_name(context, server_princ, &server_name);
983     }
984     if (ret) {
985         kdc_log(context, config, 0, 
986                 "AS-REQ malformed server name from %s", from);
987         goto out;
988     }
989     
990     if(b->cname == NULL){
991         ret = KRB5KRB_ERR_GENERIC;
992         e_text = "No client in request";
993     } else {
994
995         if (b->cname->name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
996             if (b->cname->name_string.len != 1) {
997                 kdc_log(context, config, 0,
998                         "AS-REQ malformed canon request from %s, "
999                         "enterprise name with %d name components", 
1000                         from, b->cname->name_string.len);
1001                 ret = KRB5_PARSE_MALFORMED;
1002                 goto out;
1003             }
1004             ret = krb5_parse_name(context, b->cname->name_string.val[0],
1005                                   &client_princ);
1006             if (ret)
1007                 goto out;
1008         } else {
1009             ret = _krb5_principalname2krb5_principal (context,
1010                                                       &client_princ,
1011                                                       *(b->cname),
1012                                                       b->realm);
1013             if (ret)
1014                 goto out;
1015         }
1016         ret = krb5_unparse_name(context, client_princ, &client_name);
1017     }
1018     if (ret) {
1019         kdc_log(context, config, 0,
1020                 "AS-REQ malformed client name from %s", from);
1021         goto out;
1022     }
1023
1024     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
1025             client_name, from, server_name);
1026
1027     ret = _kdc_db_fetch(context, config, client_princ, 
1028                         HDB_F_GET_CLIENT | flags, NULL, &client);
1029     if(ret){
1030         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
1031                 krb5_get_err_text(context, ret));
1032         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1033         goto out;
1034     }
1035
1036     ret = _kdc_db_fetch(context, config, server_princ,
1037                         HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
1038                         NULL, &server);
1039     if(ret){
1040         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
1041                 krb5_get_err_text(context, ret));
1042         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1043         goto out;
1044     }
1045
1046     ret = _kdc_windc_client_access(context, client, req, &e_data);
1047     if(ret)
1048         goto out;
1049
1050     ret = _kdc_check_flags(context, config, 
1051                            client, client_name,
1052                            server, server_name,
1053                            TRUE);
1054     if(ret)
1055         goto out;
1056
1057     memset(&et, 0, sizeof(et));
1058     memset(&ek, 0, sizeof(ek));
1059
1060     if(req->padata){
1061         int i;
1062         const PA_DATA *pa;
1063         int found_pa = 0;
1064
1065         log_patypes(context, config, req->padata);
1066
1067 #ifdef PKINIT
1068         kdc_log(context, config, 5, 
1069                 "Looking for PKINIT pa-data -- %s", client_name);
1070
1071         e_text = "No PKINIT PA found";
1072
1073         i = 0;
1074         if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
1075             ;
1076         if (pa == NULL) {
1077             i = 0;
1078             if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
1079                 ;
1080         }
1081         if (pa) {
1082             char *client_cert = NULL;
1083
1084             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
1085             if (ret) {
1086                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1087                 kdc_log(context, config, 5, 
1088                         "Failed to decode PKINIT PA-DATA -- %s", 
1089                         client_name);
1090                 goto ts_enc;
1091             }
1092             if (ret == 0 && pkp == NULL)
1093                 goto ts_enc;
1094
1095             ret = _kdc_pk_check_client(context,
1096                                        config,
1097                                        client,
1098                                        pkp,
1099                                        &client_cert);
1100             if (ret) {
1101                 e_text = "PKINIT certificate not allowed to "
1102                     "impersonate principal";
1103                 _kdc_pk_free_client_param(context, pkp);
1104
1105                 kdc_log(context, config, 0, "%s", e_text);
1106                 pkp = NULL;
1107                 goto out;
1108             }
1109             found_pa = 1;
1110             et.flags.pre_authent = 1;
1111             kdc_log(context, config, 0,
1112                     "PKINIT pre-authentication succeeded -- %s using %s", 
1113                     client_name, client_cert);
1114             free(client_cert);
1115             if (pkp)
1116                 goto preauth_done;
1117         }
1118     ts_enc:
1119 #endif
1120         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
1121                 client_name);
1122
1123         i = 0;
1124         e_text = "No ENC-TS found";
1125         while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1126             krb5_data ts_data;
1127             PA_ENC_TS_ENC p;
1128             size_t len;
1129             EncryptedData enc_data;
1130             Key *pa_key;
1131             char *str;
1132             
1133             found_pa = 1;
1134             
1135             ret = decode_EncryptedData(pa->padata_value.data,
1136                                        pa->padata_value.length,
1137                                        &enc_data,
1138                                        &len);
1139             if (ret) {
1140                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1141                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
1142                         client_name);
1143                 goto out;
1144             }
1145             
1146             ret = hdb_enctype2key(context, &client->entry, 
1147                                   enc_data.etype, &pa_key);
1148             if(ret){
1149                 char *estr;
1150                 e_text = "No key matches pa-data";
1151                 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1152                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1153                     estr = NULL;
1154                 if(estr == NULL)
1155                     kdc_log(context, config, 5, 
1156                             "No client key matching pa-data (%d) -- %s", 
1157                             enc_data.etype, client_name);
1158                 else
1159                     kdc_log(context, config, 5,
1160                             "No client key matching pa-data (%s) -- %s", 
1161                             estr, client_name);
1162                 free(estr);
1163                     
1164                 free_EncryptedData(&enc_data);
1165                 continue;
1166             }
1167
1168         try_next_key:
1169             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1170             if (ret) {
1171                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1172                         krb5_get_err_text(context, ret));
1173                 free_EncryptedData(&enc_data);
1174                 continue;
1175             }
1176
1177             ret = krb5_decrypt_EncryptedData (context,
1178                                               crypto,
1179                                               KRB5_KU_PA_ENC_TIMESTAMP,
1180                                               &enc_data,
1181                                               &ts_data);
1182             krb5_crypto_destroy(context, crypto);
1183             if(ret){
1184                 krb5_error_code ret2;
1185                 ret2 = krb5_enctype_to_string(context, 
1186                                               pa_key->key.keytype, &str);
1187                 if (ret2)
1188                     str = NULL;
1189                 kdc_log(context, config, 5, 
1190                         "Failed to decrypt PA-DATA -- %s "
1191                         "(enctype %s) error %s",
1192                         client_name,
1193                         str ? str : "unknown enctype", 
1194                         krb5_get_err_text(context, ret));
1195                 free(str);
1196
1197                 if(hdb_next_enctype2key(context, &client->entry, 
1198                                         enc_data.etype, &pa_key) == 0)
1199                     goto try_next_key;
1200                 e_text = "Failed to decrypt PA-DATA";
1201
1202                 free_EncryptedData(&enc_data);
1203                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1204                 continue;
1205             }
1206             free_EncryptedData(&enc_data);
1207             ret = decode_PA_ENC_TS_ENC(ts_data.data,
1208                                        ts_data.length,
1209                                        &p,
1210                                        &len);
1211             krb5_data_free(&ts_data);
1212             if(ret){
1213                 e_text = "Failed to decode PA-ENC-TS-ENC";
1214                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1215                 kdc_log(context, config, 
1216                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
1217                         client_name);
1218                 continue;
1219             }
1220             free_PA_ENC_TS_ENC(&p);
1221             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1222                 char client_time[100];
1223                 
1224                 krb5_format_time(context, p.patimestamp, 
1225                                  client_time, sizeof(client_time), TRUE); 
1226
1227                 ret = KRB5KRB_AP_ERR_SKEW;
1228                 kdc_log(context, config, 0,
1229                         "Too large time skew, "
1230                         "client time %s is out by %u > %u seconds -- %s", 
1231                         client_time, 
1232                         (unsigned)abs(kdc_time - p.patimestamp), 
1233                         context->max_skew,
1234                         client_name);
1235 #if 1
1236                 /* This code is from samba, needs testing */
1237                 /* 
1238                  * the following is needed to make windows clients
1239                  * to retry using the timestamp in the error message
1240                  *
1241                  * this is maybe a bug in windows to not trying when e_text
1242                  * is present...
1243                  */
1244                 e_text = NULL;
1245 #else
1246                 e_text = "Too large time skew";
1247 #endif
1248                 goto out;
1249             }
1250             et.flags.pre_authent = 1;
1251
1252             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1253             if (ret)
1254                 str = NULL;
1255
1256             kdc_log(context, config, 2,
1257                     "ENC-TS Pre-authentication succeeded -- %s using %s", 
1258                     client_name, str ? str : "unknown enctype");
1259             free(str);
1260             break;
1261         }
1262 #ifdef PKINIT
1263     preauth_done:
1264 #endif
1265         if(found_pa == 0 && config->require_preauth)
1266             goto use_pa;
1267         /* We come here if we found a pa-enc-timestamp, but if there
1268            was some problem with it, other than too large skew */
1269         if(found_pa && et.flags.pre_authent == 0){
1270             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1271             e_text = NULL;
1272             goto out;
1273         }
1274     }else if (config->require_preauth
1275               || client->entry.flags.require_preauth
1276               || server->entry.flags.require_preauth) {
1277         METHOD_DATA method_data;
1278         PA_DATA *pa;
1279         unsigned char *buf;
1280         size_t len;
1281
1282     use_pa: 
1283         method_data.len = 0;
1284         method_data.val = NULL;
1285
1286         ret = realloc_method_data(&method_data);
1287         pa = &method_data.val[method_data.len-1];
1288         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1289         pa->padata_value.length = 0;
1290         pa->padata_value.data   = NULL;
1291
1292 #ifdef PKINIT
1293         ret = realloc_method_data(&method_data);
1294         pa = &method_data.val[method_data.len-1];
1295         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1296         pa->padata_value.length = 0;
1297         pa->padata_value.data   = NULL;
1298
1299         ret = realloc_method_data(&method_data);
1300         pa = &method_data.val[method_data.len-1];
1301         pa->padata_type         = KRB5_PADATA_PK_AS_REQ_WIN;
1302         pa->padata_value.length = 0;
1303         pa->padata_value.data   = NULL;
1304 #endif
1305
1306         /* 
1307          * RFC4120 requires: 
1308          * - If the client only knows about old enctypes, then send
1309          *   both info replies (we send 'info' first in the list).
1310          * - If the client is 'modern', because it knows about 'new'
1311          *   enctype types, then only send the 'info2' reply.
1312          */
1313
1314         /* XXX check ret */
1315         if (only_older_enctype_p(req))
1316             ret = get_pa_etype_info(context, config,
1317                                     &method_data, &client->entry, 
1318                                     b->etype.val, b->etype.len); 
1319         /* XXX check ret */
1320         ret = get_pa_etype_info2(context, config, &method_data, 
1321                                  &client->entry, b->etype.val, b->etype.len);
1322
1323         
1324         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1325         free_METHOD_DATA(&method_data);
1326
1327         e_data.data   = buf;
1328         e_data.length = len;
1329         e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1330
1331         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1332
1333         kdc_log(context, config, 0,
1334                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1335                 client_name);
1336         goto out;
1337     }
1338     
1339     /*
1340      * Find the client key (for preauth ENC-TS verification and reply
1341      * encryption).  Then the best encryption type for the KDC and
1342      * last the best session key that shared between the client and
1343      * KDC runtime enctypes.
1344      */
1345
1346     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1347                           &ckey, &cetype);
1348     if (ret) {
1349         kdc_log(context, config, 0, 
1350                 "Client (%s) has no support for etypes", client_name);
1351         goto out;
1352     }
1353         
1354     ret = _kdc_get_preferred_key(context, config,
1355                                  server, server_name,
1356                                  &setype, &skey);
1357     if(ret)
1358         goto out;
1359
1360     /* 
1361      * Select a session enctype from the list of the crypto systems
1362      * supported enctype, is supported by the client and is one of the
1363      * enctype of the enctype of the krbtgt.
1364      *
1365      * The later is used as a hint what enctype all KDC are supporting
1366      * to make sure a newer version of KDC wont generate a session
1367      * enctype that and older version of a KDC in the same realm can't
1368      * decrypt.
1369      *
1370      * But if the KDC admin is paranoid and doesn't want to have "no
1371      * the best" enctypes on the krbtgt, lets save the best pick from
1372      * the client list and hope that that will work for any other
1373      * KDCs.
1374      */
1375     {
1376         const krb5_enctype *p;
1377         krb5_enctype clientbest = ETYPE_NULL;
1378         int i, j;
1379
1380         p = krb5_kerberos_enctypes(context);
1381
1382         sessionetype = ETYPE_NULL;
1383
1384         for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1385             if (krb5_enctype_valid(context, p[i]) != 0)
1386                 continue;
1387
1388             for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {
1389                 Key *dummy;
1390                 /* check with client */
1391                 if (p[i] != b->etype.val[j])
1392                     continue; 
1393                 /* save best of union of { client, crypto system } */
1394                 if (clientbest == ETYPE_NULL)
1395                     clientbest = p[i];
1396                 /* check with krbtgt */
1397                 ret = hdb_enctype2key(context, &server->entry, p[i], &dummy);
1398                 if (ret) 
1399                     continue;
1400                 sessionetype = p[i];
1401             }
1402         }
1403         /* if krbtgt had no shared keys with client, pick clients best */
1404         if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) {
1405             sessionetype = clientbest;
1406         } else if (sessionetype == ETYPE_NULL) {
1407             kdc_log(context, config, 0,
1408                     "Client (%s) from %s has no common enctypes with KDC"
1409                     "to use for the session key", 
1410                     client_name, from); 
1411             goto out;
1412         }
1413     }
1414
1415     log_as_req(context, config, cetype, setype, b);
1416
1417     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1418        || (f.request_anonymous && !config->allow_anonymous)) {
1419         ret = KRB5KDC_ERR_BADOPTION;
1420         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1421         goto out;
1422     }
1423     
1424     rep.pvno = 5;
1425     rep.msg_type = krb_as_rep;
1426     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1427     if (f.request_anonymous)
1428         _kdc_make_anonymous_principalname (&rep.cname);
1429     else
1430         _krb5_principal2principalname(&rep.cname, 
1431                                       client->entry.principal);
1432     rep.ticket.tkt_vno = 5;
1433     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1434     _krb5_principal2principalname(&rep.ticket.sname, 
1435                                   server->entry.principal);
1436     /* java 1.6 expects the name to be the same type, lets allow that
1437      * uncomplicated name-types. */
1438 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
1439     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
1440         rep.ticket.sname.name_type = b->sname->name_type;
1441 #undef CNT
1442
1443     et.flags.initial = 1;
1444     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1445         et.flags.forwardable = f.forwardable;
1446     else if (f.forwardable) {
1447         ret = KRB5KDC_ERR_POLICY;
1448         kdc_log(context, config, 0,
1449                 "Ticket may not be forwardable -- %s", client_name);
1450         goto out;
1451     }
1452     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1453         et.flags.proxiable = f.proxiable;
1454     else if (f.proxiable) {
1455         ret = KRB5KDC_ERR_POLICY;
1456         kdc_log(context, config, 0, 
1457                 "Ticket may not be proxiable -- %s", client_name);
1458         goto out;
1459     }
1460     if(client->entry.flags.postdate && server->entry.flags.postdate)
1461         et.flags.may_postdate = f.allow_postdate;
1462     else if (f.allow_postdate){
1463         ret = KRB5KDC_ERR_POLICY;
1464         kdc_log(context, config, 0,
1465                 "Ticket may not be postdatable -- %s", client_name);
1466         goto out;
1467     }
1468
1469     /* check for valid set of addresses */
1470     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1471         ret = KRB5KRB_AP_ERR_BADADDR;
1472         kdc_log(context, config, 0,
1473                 "Bad address list requested -- %s", client_name);
1474         goto out;
1475     }
1476
1477     ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1478     if (ret)
1479         goto out;
1480     copy_PrincipalName(&rep.cname, &et.cname);
1481     copy_Realm(&rep.crealm, &et.crealm);
1482     
1483     {
1484         time_t start;
1485         time_t t;
1486         
1487         start = et.authtime = kdc_time;
1488     
1489         if(f.postdated && req->req_body.from){
1490             ALLOC(et.starttime);
1491             start = *et.starttime = *req->req_body.from;
1492             et.flags.invalid = 1;
1493             et.flags.postdated = 1; /* XXX ??? */
1494         }
1495         _kdc_fix_time(&b->till);
1496         t = *b->till;
1497
1498         /* be careful not overflowing */
1499
1500         if(client->entry.max_life)
1501             t = start + min(t - start, *client->entry.max_life);
1502         if(server->entry.max_life)
1503             t = start + min(t - start, *server->entry.max_life);
1504 #if 0
1505         t = min(t, start + realm->max_life);
1506 #endif
1507         et.endtime = t;
1508         if(f.renewable_ok && et.endtime < *b->till){
1509             f.renewable = 1;
1510             if(b->rtime == NULL){
1511                 ALLOC(b->rtime);
1512                 *b->rtime = 0;
1513             }
1514             if(*b->rtime < *b->till)
1515                 *b->rtime = *b->till;
1516         }
1517         if(f.renewable && b->rtime){
1518             t = *b->rtime;
1519             if(t == 0)
1520                 t = MAX_TIME;
1521             if(client->entry.max_renew)
1522                 t = start + min(t - start, *client->entry.max_renew);
1523             if(server->entry.max_renew)
1524                 t = start + min(t - start, *server->entry.max_renew);
1525 #if 0
1526             t = min(t, start + realm->max_renew);
1527 #endif
1528             ALLOC(et.renew_till);
1529             *et.renew_till = t;
1530             et.flags.renewable = 1;
1531         }
1532     }
1533
1534     if (f.request_anonymous)
1535         et.flags.anonymous = 1;
1536     
1537     if(b->addresses){
1538         ALLOC(et.caddr);
1539         copy_HostAddresses(b->addresses, et.caddr);
1540     }
1541     
1542     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1543     krb5_data_zero(&et.transited.contents); 
1544      
1545     copy_EncryptionKey(&et.key, &ek.key);
1546
1547     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1548      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1549      * incapable of correctly decoding SEQUENCE OF's of zero length.
1550      *
1551      * To fix this, always send at least one no-op last_req
1552      *
1553      * If there's a pw_end or valid_end we will use that,
1554      * otherwise just a dummy lr.
1555      */
1556     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1557     ek.last_req.len = 0;
1558     if (client->entry.pw_end
1559         && (config->kdc_warn_pwexpire == 0
1560             || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1561         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1562         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1563         ++ek.last_req.len;
1564     }
1565     if (client->entry.valid_end) {
1566         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1567         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1568         ++ek.last_req.len;
1569     }
1570     if (ek.last_req.len == 0) {
1571         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1572         ek.last_req.val[ek.last_req.len].lr_value = 0;
1573         ++ek.last_req.len;
1574     }
1575     ek.nonce = b->nonce;
1576     if (client->entry.valid_end || client->entry.pw_end) {
1577         ALLOC(ek.key_expiration);
1578         if (client->entry.valid_end) {
1579             if (client->entry.pw_end)
1580                 *ek.key_expiration = min(*client->entry.valid_end, 
1581                                          *client->entry.pw_end);
1582             else
1583                 *ek.key_expiration = *client->entry.valid_end;
1584         } else
1585             *ek.key_expiration = *client->entry.pw_end;
1586     } else
1587         ek.key_expiration = NULL;
1588     ek.flags = et.flags;
1589     ek.authtime = et.authtime;
1590     if (et.starttime) {
1591         ALLOC(ek.starttime);
1592         *ek.starttime = *et.starttime;
1593     }
1594     ek.endtime = et.endtime;
1595     if (et.renew_till) {
1596         ALLOC(ek.renew_till);
1597         *ek.renew_till = *et.renew_till;
1598     }
1599     copy_Realm(&rep.ticket.realm, &ek.srealm);
1600     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1601     if(et.caddr){
1602         ALLOC(ek.caddr);
1603         copy_HostAddresses(et.caddr, ek.caddr);
1604     }
1605
1606     ALLOC(rep.padata);
1607     rep.padata->len = 0;
1608     rep.padata->val = NULL;
1609
1610     reply_key = &ckey->key;
1611 #if PKINIT
1612     if (pkp) {
1613         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 
1614                                   req, req_buffer, 
1615                                   &reply_key, rep.padata);
1616         if (ret)
1617             goto out;
1618         ret = _kdc_add_inital_verified_cas(context,
1619                                            config,
1620                                            pkp,
1621                                            &et);
1622         if (ret)
1623             goto out;
1624     }
1625 #endif
1626
1627     set_salt_padata (rep.padata, ckey->salt);
1628
1629     /* Add signing of alias referral */
1630     if (f.canonicalize) {
1631         PA_ClientCanonicalized canon;
1632         krb5_data data;
1633         PA_DATA pa;
1634         krb5_crypto crypto;
1635         size_t len;
1636
1637         memset(&canon, 0, sizeof(canon));
1638
1639         canon.names.requested_name = *b->cname;
1640         canon.names.real_name = client->entry.principal->name;
1641
1642         ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
1643                            &canon.names, &len, ret);
1644         if (ret) 
1645             goto out;
1646         if (data.length != len)
1647             krb5_abortx(context, "internal asn.1 error");
1648
1649         /* sign using "returned session key" */
1650         ret = krb5_crypto_init(context, &et.key, 0, &crypto);
1651         if (ret) {
1652             free(data.data);
1653             goto out;
1654         }
1655
1656         ret = krb5_create_checksum(context, crypto, 
1657                                    KRB5_KU_CANONICALIZED_NAMES, 0,
1658                                    data.data, data.length,
1659                                    &canon.canon_checksum);
1660         free(data.data);
1661         krb5_crypto_destroy(context, crypto);
1662         if (ret)
1663             goto out;
1664           
1665         ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
1666                            &canon, &len, ret);
1667         free_Checksum(&canon.canon_checksum);
1668         if (ret) 
1669             goto out;
1670         if (data.length != len)
1671             krb5_abortx(context, "internal asn.1 error");
1672
1673         pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
1674         pa.padata_value = data;
1675         ret = add_METHOD_DATA(rep.padata, &pa);
1676         free(data.data);
1677         if (ret)
1678             goto out;
1679     }
1680
1681     if (rep.padata->len == 0) {
1682         free(rep.padata);
1683         rep.padata = NULL;
1684     }
1685
1686     /* Add the PAC */
1687     if (send_pac_p(context, req)) {
1688         krb5_pac p = NULL;
1689         krb5_data data;
1690
1691         ret = _kdc_pac_generate(context, client, &p);
1692         if (ret) {
1693             kdc_log(context, config, 0, "PAC generation failed for -- %s", 
1694                     client_name);
1695             goto out;
1696         }
1697         if (p != NULL) {
1698             ret = _krb5_pac_sign(context, p, et.authtime,
1699                                  client->entry.principal,
1700                                  &skey->key, /* Server key */ 
1701                                  &skey->key, /* FIXME: should be krbtgt key */
1702                                  &data);
1703             krb5_pac_free(context, p);
1704             if (ret) {
1705                 kdc_log(context, config, 0, "PAC signing failed for -- %s", 
1706                         client_name);
1707                 goto out;
1708             }
1709
1710             ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1711                                               KRB5_AUTHDATA_WIN2K_PAC,
1712                                               &data);
1713             krb5_data_free(&data);
1714             if (ret)
1715                 goto out;
1716         }
1717     }
1718
1719     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1720                        et.endtime, et.renew_till);
1721
1722     /* do this as the last thing since this signs the EncTicketPart */
1723     ret = _kdc_add_KRB5SignedPath(context,
1724                                   config,
1725                                   server,
1726                                   setype,
1727                                   NULL,
1728                                   NULL,
1729                                   &et);
1730     if (ret)
1731         goto out;
1732
1733     ret = _kdc_encode_reply(context, config, 
1734                             &rep, &et, &ek, setype, server->entry.kvno, 
1735                             &skey->key, client->entry.kvno, 
1736                             reply_key, &e_text, reply);
1737     free_EncTicketPart(&et);
1738     free_EncKDCRepPart(&ek);
1739     if (ret)
1740         goto out;
1741
1742     /* */
1743     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1744         krb5_data_free(reply);
1745         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1746         e_text = "Reply packet too large";
1747     }
1748
1749 out:
1750     free_AS_REP(&rep);
1751     if(ret){
1752         krb5_mk_error(context,
1753                       ret,
1754                       e_text,
1755                       (e_data.data ? &e_data : NULL),
1756                       client_princ,
1757                       server_princ,
1758                       NULL,
1759                       NULL,
1760                       reply);
1761         ret = 0;
1762     }
1763 #ifdef PKINIT
1764     if (pkp)
1765         _kdc_pk_free_client_param(context, pkp);
1766 #endif
1767     if (e_data.data)
1768         free(e_data.data);
1769     if (client_princ)
1770         krb5_free_principal(context, client_princ);
1771     free(client_name);
1772     if (server_princ)
1773         krb5_free_principal(context, server_princ);
1774     free(server_name);
1775     if(client)
1776         _kdc_free_ent(context, client);
1777     if(server)
1778         _kdc_free_ent(context, server);
1779     return ret;
1780 }
1781
1782 /*
1783  * Add the AuthorizationData `data´ of `type´ to the last element in
1784  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1785  */
1786
1787 krb5_error_code
1788 _kdc_tkt_add_if_relevant_ad(krb5_context context,
1789                             EncTicketPart *tkt,
1790                             int type,
1791                             const krb5_data *data)
1792 {
1793     krb5_error_code ret;
1794     size_t size;
1795
1796     if (tkt->authorization_data == NULL) {
1797         tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1798         if (tkt->authorization_data == NULL) {
1799             krb5_set_error_string(context, "out of memory");
1800             return ENOMEM;
1801         }
1802     }
1803         
1804     /* add the entry to the last element */
1805     {
1806         AuthorizationData ad = { 0, NULL };
1807         AuthorizationDataElement ade;
1808
1809         ade.ad_type = type;
1810         ade.ad_data = *data;
1811
1812         ret = add_AuthorizationData(&ad, &ade);
1813         if (ret) {
1814             krb5_set_error_string(context, "add AuthorizationData failed");
1815             return ret;
1816         }
1817
1818         ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1819
1820         ASN1_MALLOC_ENCODE(AuthorizationData, 
1821                            ade.ad_data.data, ade.ad_data.length, 
1822                            &ad, &size, ret);
1823         free_AuthorizationData(&ad);
1824         if (ret) {
1825             krb5_set_error_string(context, "ASN.1 encode of "
1826                                   "AuthorizationData failed");
1827             return ret;
1828         }
1829         if (ade.ad_data.length != size)
1830             krb5_abortx(context, "internal asn.1 encoder error");
1831         
1832         ret = add_AuthorizationData(tkt->authorization_data, &ade);
1833         der_free_octet_string(&ade.ad_data);
1834         if (ret) {
1835             krb5_set_error_string(context, "add AuthorizationData failed");
1836             return ret;
1837         }
1838     }
1839
1840     return 0;
1841 }