r10191: Return the right error code in the case of a time skew. Windows will now
[ira/wip.git] / source4 / heimdal / kdc / kerberos5.c
1 /*
2  * Copyright (c) 1997-2005 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 #ifdef _SAMBA_BUILD_
36 #include "kdc/pac-glue.h"
37 #endif
38
39 RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
40
41 #define MAX_TIME ((time_t)((1U << 31) - 1))
42
43 static void
44 fix_time(time_t **t)
45 {
46     if(*t == NULL){
47         ALLOC(*t);
48         **t = MAX_TIME;
49     }
50     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
51 }
52
53 static int
54 realloc_method_data(METHOD_DATA *md)
55 {
56     PA_DATA *pa;
57     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
58     if(pa == NULL)
59         return ENOMEM;
60     md->val = pa;
61     md->len++;
62     return 0;
63 }
64
65 static void
66 set_salt_padata (METHOD_DATA *md, Salt *salt)
67 {
68     if (salt) {
69         realloc_method_data(md);
70         md->val[md->len - 1].padata_type = salt->type;
71         copy_octet_string(&salt->salt,
72                           &md->val[md->len - 1].padata_value);
73     }
74 }
75
76 static PA_DATA*
77 find_padata(KDC_REQ *req, int *start, int type)
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  * return the first appropriate key of `princ' in `ret_key'.  Look for
89  * all the etypes in (`etypes', `len'), stopping as soon as we find
90  * one, but preferring one that has default salt
91  */
92
93 static krb5_error_code
94 find_etype(krb5_context context, hdb_entry *princ, 
95            krb5_enctype *etypes, unsigned len, 
96            Key **ret_key, krb5_enctype *ret_etype)
97 {
98     int i;
99     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
100
101     for(i = 0; ret != 0 && i < len ; i++) {
102         Key *key = NULL;
103
104         if (krb5_enctype_valid(context, etypes[i]) != 0)
105             continue;
106
107         while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
108             if (key->key.keyvalue.length == 0) {
109                 ret = KRB5KDC_ERR_NULL_KEY;
110                 continue;
111             }
112             *ret_key   = key;
113             *ret_etype = etypes[i];
114             ret = 0;
115             if (key->salt == NULL)
116                 return ret;
117         }
118     }
119     return ret;
120 }
121
122 static krb5_error_code
123 find_keys(krb5_context context, 
124           krb5_kdc_configuration *config,
125           hdb_entry *client,
126           hdb_entry *server, 
127           Key **ckey,
128           krb5_enctype *cetype,
129           Key **skey,
130           krb5_enctype *setype, 
131           krb5_enctype *etypes,
132           unsigned num_etypes)
133 {
134     char unparse_name[] = "krb5_unparse_name failed";
135     krb5_error_code ret;
136     char *name;
137
138     if(client){
139         /* find client key */
140         ret = find_etype(context, client, etypes, num_etypes, ckey, cetype);
141         if (ret) {
142             if (krb5_unparse_name(context, client->principal, &name) != 0)
143                 name = unparse_name;
144             kdc_log(context, config, 0, 
145                     "Client (%s) has no support for etypes", name);
146             if (name != unparse_name)
147                 free(name);
148             return ret;
149         }
150     }
151
152     if(server){
153         /* find server key */
154         ret = find_etype(context, server, etypes, num_etypes, skey, setype);
155         if (ret) {
156             if (krb5_unparse_name(context, server->principal, &name) != 0)
157                 name = unparse_name;
158             kdc_log(context, config, 0, 
159                     "Server (%s) has no support for etypes", name);
160             if (name != unparse_name)
161                 free(name);
162             return ret;
163         }
164     }
165     return 0;
166 }
167
168 static krb5_error_code
169 make_anonymous_principalname (PrincipalName *pn)
170 {
171     pn->name_type = KRB5_NT_PRINCIPAL;
172     pn->name_string.len = 1;
173     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
174     if (pn->name_string.val == NULL)
175         return ENOMEM;
176     pn->name_string.val[0] = strdup("anonymous");
177     if (pn->name_string.val[0] == NULL) {
178         free(pn->name_string.val);
179         pn->name_string.val = NULL;
180         return ENOMEM;
181     }
182     return 0;
183 }
184
185 static void
186 log_timestamp(krb5_context context, 
187               krb5_kdc_configuration *config,
188               const char *type,
189               KerberosTime authtime, KerberosTime *starttime, 
190               KerberosTime endtime, KerberosTime *renew_till)
191 {
192     char authtime_str[100], starttime_str[100], 
193         endtime_str[100], renewtime_str[100];
194     
195     krb5_format_time(context, authtime, 
196                      authtime_str, sizeof(authtime_str), TRUE); 
197     if (starttime)
198         krb5_format_time(context, *starttime, 
199                          starttime_str, sizeof(starttime_str), TRUE); 
200     else
201         strlcpy(starttime_str, "unset", sizeof(starttime_str));
202     krb5_format_time(context, endtime, 
203                      endtime_str, sizeof(endtime_str), TRUE); 
204     if (renew_till)
205         krb5_format_time(context, *renew_till, 
206                          renewtime_str, sizeof(renewtime_str), TRUE); 
207     else
208         strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
209     
210     kdc_log(context, config, 5,
211             "%s authtime: %s starttime: %s endtime: %s renew till: %s",
212             type, authtime_str, starttime_str, endtime_str, renewtime_str);
213 }
214
215 static krb5_error_code
216 encode_reply(krb5_context context,
217              krb5_kdc_configuration *config,
218              KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, 
219              krb5_enctype etype, 
220              int skvno, EncryptionKey *skey,
221              int ckvno, EncryptionKey *ckey,
222              const char **e_text,
223              krb5_data *reply)
224 {
225     unsigned char *buf;
226     size_t buf_size;
227     size_t len;
228     krb5_error_code ret;
229     krb5_crypto crypto;
230
231     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
232     if(ret) {
233         kdc_log(context, config, 0, "Failed to encode ticket: %s", 
234                 krb5_get_err_text(context, ret));
235         return ret;
236     }
237     if(buf_size != len) {
238         free(buf);
239         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
240         *e_text = "KDC internal error";
241         return KRB5KRB_ERR_GENERIC;
242     }
243
244     ret = krb5_crypto_init(context, skey, etype, &crypto);
245     if (ret) {
246         free(buf);
247         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
248                 krb5_get_err_text(context, ret));
249         return ret;
250     }
251
252     ret = krb5_encrypt_EncryptedData(context, 
253                                      crypto,
254                                      KRB5_KU_TICKET,
255                                      buf,
256                                      len,
257                                      skvno,
258                                      &rep->ticket.enc_part);
259     free(buf);
260     krb5_crypto_destroy(context, crypto);
261     if(ret) {
262         kdc_log(context, config, 0, "Failed to encrypt data: %s",
263                 krb5_get_err_text(context, ret));
264         return ret;
265     }
266     
267     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
268         ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
269     else
270         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
271     if(ret) {
272         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
273                 krb5_get_err_text(context, ret));
274         return ret;
275     }
276     if(buf_size != len) {
277         free(buf);
278         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
279         *e_text = "KDC internal error";
280         return KRB5KRB_ERR_GENERIC;
281     }
282     ret = krb5_crypto_init(context, ckey, 0, &crypto);
283     if (ret) {
284         free(buf);
285         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
286                 krb5_get_err_text(context, ret));
287         return ret;
288     }
289     if(rep->msg_type == krb_as_rep) {
290         krb5_encrypt_EncryptedData(context,
291                                    crypto,
292                                    KRB5_KU_AS_REP_ENC_PART,
293                                    buf,
294                                    len,
295                                    ckvno,
296                                    &rep->enc_part);
297         free(buf);
298         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
299     } else {
300         krb5_encrypt_EncryptedData(context,
301                                    crypto,
302                                    KRB5_KU_TGS_REP_ENC_PART_SESSION,
303                                    buf,
304                                    len,
305                                    ckvno,
306                                    &rep->enc_part);
307         free(buf);
308         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
309     }
310     krb5_crypto_destroy(context, crypto);
311     if(ret) {
312         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 
313                 krb5_get_err_text(context, ret));
314         return ret;
315     }
316     if(buf_size != len) {
317         free(buf);
318         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
319         *e_text = "KDC internal error";
320         return KRB5KRB_ERR_GENERIC;
321     }
322     reply->data = buf;
323     reply->length = buf_size;
324     return 0;
325 }
326
327 static krb5_error_code
328 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
329 {
330     ent->etype = key->key.keytype;
331     if(key->salt){
332 #if 0
333         ALLOC(ent->salttype);
334
335         if(key->salt->type == hdb_pw_salt)
336             *ent->salttype = 0; /* or 1? or NULL? */
337         else if(key->salt->type == hdb_afs3_salt)
338             *ent->salttype = 2;
339         else {
340             kdc_log(context, config, 0, "unknown salt-type: %d", 
341                     key->salt->type);
342             return KRB5KRB_ERR_GENERIC;
343         }
344         /* according to `the specs', we can't send a salt if
345            we have AFS3 salted key, but that requires that you
346            *know* what cell you are using (e.g by assuming
347            that the cell is the same as the realm in lower
348            case) */
349 #elif 0
350         ALLOC(ent->salttype);
351         *ent->salttype = key->salt->type;
352 #else
353         /* 
354          * We shouldn't sent salttype since its incompatible with the
355          * specification and its break windows clients.  The afs
356          * salting problem is solved by using KRB5-PADATA-AFS3-SALT
357          * implemented in Heimdal 0.7 and later.
358          */
359         ent->salttype = NULL;
360 #endif
361         krb5_copy_data(context, &key->salt->salt,
362                        &ent->salt);
363     } else {
364         /* we return no salt type at all, as that should indicate
365          * the default salt type and make everybody happy.  some
366          * systems (like w2k) dislike being told the salt type
367          * here. */
368
369         ent->salttype = NULL;
370         ent->salt = NULL;
371     }
372     return 0;
373 }
374
375 static krb5_error_code
376 get_pa_etype_info(krb5_context context, 
377                   krb5_kdc_configuration *config,
378                   METHOD_DATA *md, hdb_entry *client, 
379                   ENCTYPE *etypes, unsigned int etypes_len)
380 {
381     krb5_error_code ret = 0;
382     int i, j;
383     unsigned int n = 0;
384     ETYPE_INFO pa;
385     unsigned char *buf;
386     size_t len;
387     
388
389     pa.len = client->keys.len;
390     if(pa.len > UINT_MAX/sizeof(*pa.val))
391         return ERANGE;
392     pa.val = malloc(pa.len * sizeof(*pa.val));
393     if(pa.val == NULL)
394         return ENOMEM;
395     memset(pa.val, 0, pa.len * sizeof(*pa.val));
396
397     for(j = 0; j < etypes_len; j++) {
398         for (i = 0; i < n; i++)
399             if (pa.val[i].etype == etypes[j])
400                 goto skip1;
401         for(i = 0; i < client->keys.len; i++) {
402             if(client->keys.val[i].key.keytype == etypes[j]) {
403                 if (krb5_enctype_valid(context, etypes[j]) != 0)
404                     continue;
405                 if((ret = make_etype_info_entry(context, 
406                                                 &pa.val[n++], 
407                                                 &client->keys.val[i])) != 0) {
408                     free_ETYPE_INFO(&pa);
409                     return ret;
410                 }
411             }
412         }
413     skip1:;
414     }
415     for(i = 0; i < client->keys.len; i++) {
416         for(j = 0; j < etypes_len; j++) {
417             if(client->keys.val[i].key.keytype == etypes[j])
418                 goto skip2;
419         }
420         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
421             continue;
422         if((ret = make_etype_info_entry(context, 
423                                         &pa.val[n++], 
424                                         &client->keys.val[i])) != 0) {
425             free_ETYPE_INFO(&pa);
426             return ret;
427         }
428     skip2:;
429     }
430     
431     if(n != pa.len) {
432         char *name;
433         ret = krb5_unparse_name(context, client->principal, &name);
434         if (ret)
435             name = "<unparse_name failed>";
436         kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d", 
437                 name, n, pa.len);
438         if (ret == 0)
439             free(name);
440         pa.len = n;
441     }
442
443     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
444     free_ETYPE_INFO(&pa);
445     if(ret)
446         return ret;
447     ret = realloc_method_data(md);
448     if(ret) {
449         free(buf);
450         return ret;
451     }
452     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
453     md->val[md->len - 1].padata_value.length = len;
454     md->val[md->len - 1].padata_value.data = buf;
455     return 0;
456 }
457
458 /*
459  *
460  */
461
462 extern int _krb5_AES_string_to_default_iterator;
463
464 static krb5_error_code
465 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
466 {
467     ent->etype = key->key.keytype;
468     if(key->salt) {
469         ALLOC(ent->salt);
470         if (ent->salt == NULL)
471             return ENOMEM;
472         *ent->salt = malloc(key->salt->salt.length + 1);
473         if (*ent->salt == NULL) {
474             free(ent->salt);
475             ent->salt = NULL;
476             return ENOMEM;
477         }
478         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
479         (*ent->salt)[key->salt->salt.length] = '\0';
480     } else
481         ent->salt = NULL;
482
483     ent->s2kparams = NULL;
484
485     switch (key->key.keytype) {
486     case KEYTYPE_AES128:
487     case KEYTYPE_AES256:
488         ALLOC(ent->s2kparams);
489         if (ent->s2kparams == NULL)
490             return ENOMEM;
491         ent->s2kparams->length = 4;
492         ent->s2kparams->data = malloc(ent->s2kparams->length);
493         if (ent->s2kparams->data == NULL) {
494             free(ent->s2kparams);
495             ent->s2kparams = NULL;
496             return ENOMEM;
497         }
498         _krb5_put_int(ent->s2kparams->data, 
499                       _krb5_AES_string_to_default_iterator, 
500                       ent->s2kparams->length);
501         break;
502     default:
503         break;
504     }
505     return 0;
506 }
507
508 /*
509  * Return 1 if the client have only older enctypes, this is for
510  * determining if the server should send ETYPE_INFO2 or not.
511  */
512
513 static int
514 only_older_enctype_p(const KDC_REQ *req)
515 {
516     int i;
517
518     for(i = 0; i < req->req_body.etype.len; i++) {
519         switch (req->req_body.etype.val[i]) {
520         case ETYPE_DES_CBC_CRC:
521         case ETYPE_DES_CBC_MD4:
522         case ETYPE_DES_CBC_MD5:
523         case ETYPE_DES3_CBC_SHA1:
524         case ETYPE_ARCFOUR_HMAC_MD5:
525         case ETYPE_ARCFOUR_HMAC_MD5_56:
526             break;
527         default:
528             return 0;
529         }
530     }
531     return 1;
532 }
533
534 /*
535  *
536  */
537
538 static krb5_error_code
539 get_pa_etype_info2(krb5_context context, 
540                    krb5_kdc_configuration *config,
541                    METHOD_DATA *md, hdb_entry *client, 
542                    ENCTYPE *etypes, unsigned int etypes_len)
543 {
544     krb5_error_code ret = 0;
545     int i, j;
546     unsigned int n = 0;
547     ETYPE_INFO2 pa;
548     unsigned char *buf;
549     size_t len;
550
551     pa.len = client->keys.len;
552     if(pa.len > UINT_MAX/sizeof(*pa.val))
553         return ERANGE;
554     pa.val = malloc(pa.len * sizeof(*pa.val));
555     if(pa.val == NULL)
556         return ENOMEM;
557     memset(pa.val, 0, pa.len * sizeof(*pa.val));
558
559     for(j = 0; j < etypes_len; j++) {
560         for (i = 0; i < n; i++)
561             if (pa.val[i].etype == etypes[j])
562                 goto skip1;
563         for(i = 0; i < client->keys.len; i++) {
564             if(client->keys.val[i].key.keytype == etypes[j]) {
565                 if (krb5_enctype_valid(context, etypes[j]) != 0)
566                     continue;
567                 if((ret = make_etype_info2_entry(&pa.val[n++], 
568                                                  &client->keys.val[i])) != 0) {
569                     free_ETYPE_INFO2(&pa);
570                     return ret;
571                 }
572             }
573         }
574     skip1:;
575     }
576     for(i = 0; i < client->keys.len; i++) {
577         for(j = 0; j < etypes_len; j++) {
578             if(client->keys.val[i].key.keytype == etypes[j])
579                 goto skip2;
580         }
581         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
582             continue;
583         if((ret = make_etype_info2_entry(&pa.val[n++],
584                                          &client->keys.val[i])) != 0) {
585             free_ETYPE_INFO2(&pa);
586             return ret;
587         }
588       skip2:;
589     }
590     
591     if(n != pa.len) {
592         char *name;
593         ret = krb5_unparse_name(context, client->principal, &name);
594         if (ret)
595             name = "<unparse_name failed>";
596         kdc_log(context, config, 0,
597                 "internal error in get_pa_etype_info2(%s): %d != %d", 
598                 name, n, pa.len);
599         if (ret == 0)
600             free(name);
601         pa.len = n;
602     }
603
604     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
605     free_ETYPE_INFO2(&pa);
606     if(ret)
607         return ret;
608     ret = realloc_method_data(md);
609     if(ret) {
610         free(buf);
611         return ret;
612     }
613     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
614     md->val[md->len - 1].padata_value.length = len;
615     md->val[md->len - 1].padata_value.data = buf;
616     return 0;
617 }
618
619 /*
620  * verify the flags on `client' and `server', returning 0
621  * if they are OK and generating an error messages and returning
622  * and error code otherwise.
623  */
624
625 krb5_error_code
626 _kdc_check_flags(krb5_context context, 
627                  krb5_kdc_configuration *config,
628                  hdb_entry *client, const char *client_name,
629                  hdb_entry *server, const char *server_name,
630                  krb5_boolean is_as_req)
631 {
632     if(client != NULL) {
633         /* check client */
634         if (client->flags.invalid) {
635             kdc_log(context, config, 0, 
636                     "Client (%s) has invalid bit set", client_name);
637             return KRB5KDC_ERR_POLICY;
638         }
639         
640         if(!client->flags.client){
641             kdc_log(context, config, 0,
642                     "Principal may not act as client -- %s", client_name);
643             return KRB5KDC_ERR_POLICY;
644         }
645         
646         if (client->valid_start && *client->valid_start > kdc_time) {
647             kdc_log(context, config, 0,
648                     "Client not yet valid -- %s", client_name);
649             return KRB5KDC_ERR_CLIENT_NOTYET;
650         }
651         
652         if (client->valid_end && *client->valid_end < kdc_time) {
653             kdc_log(context, config, 0,
654                     "Client expired -- %s", client_name);
655             return KRB5KDC_ERR_NAME_EXP;
656         }
657         
658         if (client->pw_end && *client->pw_end < kdc_time
659             && !server->flags.change_pw) {
660             kdc_log(context, config, 0,
661                     "Client's key has expired -- %s", client_name);
662             return KRB5KDC_ERR_KEY_EXPIRED;
663         }
664     }
665
666     /* check server */
667     
668     if (server != NULL) {
669         if (server->flags.invalid) {
670             kdc_log(context, config, 0,
671                     "Server has invalid flag set -- %s", server_name);
672             return KRB5KDC_ERR_POLICY;
673         }
674
675         if(!server->flags.server){
676             kdc_log(context, config, 0,
677                     "Principal may not act as server -- %s", server_name);
678             return KRB5KDC_ERR_POLICY;
679         }
680
681         if(!is_as_req && server->flags.initial) {
682             kdc_log(context, config, 0,
683                     "AS-REQ is required for server -- %s", server_name);
684             return KRB5KDC_ERR_POLICY;
685         }
686
687         if (server->valid_start && *server->valid_start > kdc_time) {
688             kdc_log(context, config, 0,
689                     "Server not yet valid -- %s", server_name);
690             return KRB5KDC_ERR_SERVICE_NOTYET;
691         }
692
693         if (server->valid_end && *server->valid_end < kdc_time) {
694             kdc_log(context, config, 0,
695                     "Server expired -- %s", server_name);
696             return KRB5KDC_ERR_SERVICE_EXP;
697         }
698
699         if (server->pw_end && *server->pw_end < kdc_time) {
700             kdc_log(context, config, 0,
701                     "Server's key has expired -- %s", server_name);
702             return KRB5KDC_ERR_KEY_EXPIRED;
703         }
704     }
705     return 0;
706 }
707
708 /*
709  * Return TRUE if `from' is part of `addresses' taking into consideration
710  * the configuration variables that tells us how strict we should be about
711  * these checks
712  */
713
714 static krb5_boolean
715 check_addresses(krb5_context context,        
716                 krb5_kdc_configuration *config,
717                 HostAddresses *addresses, const struct sockaddr *from)
718 {
719     krb5_error_code ret;
720     krb5_address addr;
721     krb5_boolean result;
722     
723     if(config->check_ticket_addresses == 0)
724         return TRUE;
725
726     if(addresses == NULL)
727         return config->allow_null_ticket_addresses;
728     
729     ret = krb5_sockaddr2address (context, from, &addr);
730     if(ret)
731         return FALSE;
732
733     result = krb5_address_search(context, &addr, addresses);
734     krb5_free_address (context, &addr);
735     return result;
736 }
737
738 krb5_error_code
739 _kdc_as_rep(krb5_context context, 
740             krb5_kdc_configuration *config,
741             KDC_REQ *req, 
742             const krb5_data *req_buffer, 
743             krb5_data *reply,
744             const char *from,
745             struct sockaddr *from_addr)
746 {
747     KDC_REQ_BODY *b = &req->req_body;
748     AS_REP rep;
749     KDCOptions f = b->kdc_options;
750     hdb_entry *client = NULL, *server = NULL;
751     krb5_enctype cetype, setype;
752     EncTicketPart et;
753     EncKDCRepPart ek;
754     krb5_principal client_princ = NULL, server_princ = NULL;
755     char *client_name = NULL, *server_name = NULL;
756     krb5_error_code ret = 0;
757     const char *e_text = NULL;
758     krb5_crypto crypto;
759     Key *ckey, *skey;
760     EncryptionKey *reply_key;
761 #ifdef PKINIT
762     pk_client_params *pkp = NULL;
763 #endif
764
765     memset(&rep, 0, sizeof(rep));
766
767     if(b->sname == NULL){
768         ret = KRB5KRB_ERR_GENERIC;
769         e_text = "No server in request";
770     } else{
771         _krb5_principalname2krb5_principal (&server_princ,
772                                             *(b->sname), b->realm);
773         ret = krb5_unparse_name(context, server_princ, &server_name);
774     }
775     if (ret) {
776         kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from);
777         goto out;
778     }
779     
780     if(b->cname == NULL){
781         ret = KRB5KRB_ERR_GENERIC;
782         e_text = "No client in request";
783     } else {
784         _krb5_principalname2krb5_principal (&client_princ,
785                                             *(b->cname), b->realm);
786         ret = krb5_unparse_name(context, client_princ, &client_name);
787     }
788     if (ret) {
789         kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from);
790         goto out;
791     }
792
793     kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 
794             client_name, from, server_name);
795
796     ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client);
797     if(ret){
798         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
799                 krb5_get_err_text(context, ret));
800         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
801         goto out;
802     }
803
804     ret = _kdc_db_fetch(context, config, server_princ, HDB_ENT_TYPE_SERVER, &server);
805     if(ret){
806         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
807                 krb5_get_err_text(context, ret));
808         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
809         goto out;
810     }
811
812     ret = _kdc_check_flags(context, config, 
813                            client, client_name,
814                            server, server_name,
815                            TRUE);
816     if(ret)
817         goto out;
818
819     memset(&et, 0, sizeof(et));
820     memset(&ek, 0, sizeof(ek));
821
822     if(req->padata){
823         int i = 0;
824         PA_DATA *pa;
825         int found_pa = 0;
826
827 #ifdef PKINIT
828         kdc_log(context, config, 5, 
829                 "Looking for PKINIT pa-data -- %s", client_name);
830
831         e_text = "No PKINIT PA found";
832
833         i = 0;
834         if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
835             ;
836         if (pa == NULL) {
837             i = 0;
838             if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
839                 ;
840         }
841         if (pa == NULL) {
842             i = 0;
843             if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
844                 ;
845         }
846         if (pa) {
847             char *client_cert = NULL;
848
849             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
850             if (ret) {
851                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
852                 kdc_log(context, config, 5, 
853                         "Failed to decode PKINIT PA-DATA -- %s", 
854                         client_name);
855                 goto ts_enc;
856             }
857             if (ret == 0 && pkp == NULL)
858                 goto ts_enc;
859
860             ret = _kdc_pk_check_client(context,
861                                        config,
862                                        client_princ, 
863                                        client,
864                                        pkp,
865                                        &client_cert);
866             if (ret) {
867                 e_text = "PKINIT certificate not allowed to "
868                     "impersonate principal";
869                 _kdc_pk_free_client_param(context, pkp);
870                 pkp = NULL;
871                 goto ts_enc;
872             }
873             found_pa = 1;
874             et.flags.pre_authent = 1;
875             kdc_log(context, config, 2,
876                     "PKINIT pre-authentication succeeded -- %s using %s", 
877                     client_name, client_cert);
878             free(client_cert);
879             if (pkp)
880                 goto preauth_done;
881         }
882     ts_enc:
883 #endif
884         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 
885                 client_name);
886
887         i = 0;
888         e_text = "No ENC-TS found";
889         while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
890             krb5_data ts_data;
891             PA_ENC_TS_ENC p;
892             size_t len;
893             EncryptedData enc_data;
894             Key *pa_key;
895             char *str;
896             
897             found_pa = 1;
898             
899             ret = decode_EncryptedData(pa->padata_value.data,
900                                        pa->padata_value.length,
901                                        &enc_data,
902                                        &len);
903             if (ret) {
904                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
905                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 
906                         client_name);
907                 goto out;
908             }
909             
910             ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
911             if(ret){
912                 char *estr;
913                 e_text = "No key matches pa-data";
914                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
915                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
916                     estr = NULL;
917                 if(estr == NULL)
918                     kdc_log(context, config, 5, 
919                             "No client key matching pa-data (%d) -- %s", 
920                             enc_data.etype, client_name);
921                 else
922                     kdc_log(context, config, 5,
923                             "No client key matching pa-data (%s) -- %s", 
924                             estr, client_name);
925                 free(estr);
926                     
927                 free_EncryptedData(&enc_data);
928                 continue;
929             }
930
931         try_next_key:
932             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
933             if (ret) {
934                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
935                         krb5_get_err_text(context, ret));
936                 free_EncryptedData(&enc_data);
937                 continue;
938             }
939
940             ret = krb5_decrypt_EncryptedData (context,
941                                               crypto,
942                                               KRB5_KU_PA_ENC_TIMESTAMP,
943                                               &enc_data,
944                                               &ts_data);
945             krb5_crypto_destroy(context, crypto);
946             if(ret){
947                 krb5_error_code ret2;
948                 ret2 = krb5_enctype_to_string(context, 
949                                              pa_key->key.keytype, &str);
950                 if (ret2)
951                     str = NULL;
952                 kdc_log(context, config, 5, 
953                         "Failed to decrypt PA-DATA -- %s "
954                         "(enctype %s) error %s",
955                         client_name,
956                         str ? str : "unknown enctype", 
957                         krb5_get_err_text(context, ret));
958                 free(str);
959
960                 if(hdb_next_enctype2key(context, client, 
961                                         enc_data.etype, &pa_key) == 0)
962                     goto try_next_key;
963                 e_text = "Failed to decrypt PA-DATA";
964
965                 free_EncryptedData(&enc_data);
966                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
967                 continue;
968             }
969             free_EncryptedData(&enc_data);
970             ret = decode_PA_ENC_TS_ENC(ts_data.data,
971                                        ts_data.length,
972                                        &p,
973                                        &len);
974             krb5_data_free(&ts_data);
975             if(ret){
976                 e_text = "Failed to decode PA-ENC-TS-ENC";
977                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
978                 kdc_log(context, config, 
979                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
980                         client_name);
981                 continue;
982             }
983             free_PA_ENC_TS_ENC(&p);
984             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
985                 ret = KRB5KRB_AP_ERR_SKEW;
986                 e_text = "Too large time skew";
987                 kdc_log(context, config, 0,
988                         "Too large time skew -- %s", client_name);
989                 goto out;
990             }
991             et.flags.pre_authent = 1;
992
993             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
994             if (ret)
995                 str = NULL;
996
997             kdc_log(context, config, 2,
998                     "ENC-TS Pre-authentication succeeded -- %s using %s", 
999                     client_name, str ? str : "unknown enctype");
1000             free(str);
1001             break;
1002         }
1003 #ifdef PKINIT
1004     preauth_done:
1005 #endif
1006         if(found_pa == 0 && config->require_preauth)
1007             goto use_pa;
1008         /* We come here if we found a pa-enc-timestamp, but if there
1009            was some problem with it, other than too large skew */
1010         if(found_pa && et.flags.pre_authent == 0){
1011             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1012             e_text = NULL;
1013             goto out;
1014         }
1015     }else if (config->require_preauth
1016               || client->flags.require_preauth
1017               || server->flags.require_preauth) {
1018         METHOD_DATA method_data;
1019         PA_DATA *pa;
1020         unsigned char *buf;
1021         size_t len;
1022         krb5_data foo_data;
1023
1024     use_pa: 
1025         method_data.len = 0;
1026         method_data.val = NULL;
1027
1028         ret = realloc_method_data(&method_data);
1029         pa = &method_data.val[method_data.len-1];
1030         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1031         pa->padata_value.length = 0;
1032         pa->padata_value.data   = NULL;
1033
1034 #ifdef PKINIT
1035         ret = realloc_method_data(&method_data);
1036         pa = &method_data.val[method_data.len-1];
1037         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1038         pa->padata_value.length = 0;
1039         pa->padata_value.data   = NULL;
1040
1041         ret = realloc_method_data(&method_data);
1042         pa = &method_data.val[method_data.len-1];
1043         pa->padata_type         = KRB5_PADATA_PK_AS_REQ_19;
1044         pa->padata_value.length = 0;
1045         pa->padata_value.data   = NULL;
1046 #endif
1047
1048         /* XXX check ret */
1049         if (only_older_enctype_p(req))
1050             ret = get_pa_etype_info(context, config, &method_data, client, 
1051                                     b->etype.val, b->etype.len); 
1052         /* XXX check ret */
1053         ret = get_pa_etype_info2(context, config, &method_data, client, 
1054                                  b->etype.val, b->etype.len);
1055
1056         
1057         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1058         free_METHOD_DATA(&method_data);
1059         foo_data.data   = buf;
1060         foo_data.length = len;
1061         
1062         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1063         krb5_mk_error(context,
1064                       ret,
1065                       "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1066                       &foo_data,
1067                       client_princ,
1068                       server_princ,
1069                       NULL,
1070                       NULL,
1071                       reply);
1072         free(buf);
1073         kdc_log(context, config, 0,
1074                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1075                 client_name);
1076         ret = 0;
1077         goto out2;
1078     }
1079     
1080     ret = find_keys(context, config, 
1081                     client, server, &ckey, &cetype, &skey, &setype,
1082                     b->etype.val, b->etype.len);
1083     if(ret) {
1084         kdc_log(context, config, 0, "Server/client has no support for etypes");
1085         goto out;
1086     }
1087         
1088     {
1089         struct rk_strpool *p = NULL;
1090         char *str;
1091         int i;
1092
1093         for (i = 0; i < b->etype.len; i++) {
1094             ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1095             if (ret == 0) {
1096                 p = rk_strpoolprintf(p, "%s", str);
1097                 free(str);
1098             } else
1099                 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1100             if (p && i + 1 < b->etype.len)
1101                 p = rk_strpoolprintf(p, ", ");
1102             if (p == NULL) {
1103                 kdc_log(context, config, 0, "out of meory");
1104                 goto out;
1105             }
1106         }
1107         str = rk_strpoolcollect(p);
1108         kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1109         free(str);
1110     }
1111     {
1112         char *cet;
1113         char *set;
1114
1115         ret = krb5_enctype_to_string(context, cetype, &cet);
1116         if(ret == 0) {
1117             ret = krb5_enctype_to_string(context, setype, &set);
1118             if (ret == 0) {
1119                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
1120                 free(set);
1121             }
1122             free(cet);
1123         }
1124         if (ret != 0)
1125             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1126     }
1127     
1128     {
1129         char str[128];
1130         unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(), 
1131                       str, sizeof(str));
1132         if(*str)
1133             kdc_log(context, config, 2, "Requested flags: %s", str);
1134     }
1135     
1136
1137     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1138        || (f.request_anonymous && !config->allow_anonymous)) {
1139         ret = KRB5KDC_ERR_BADOPTION;
1140         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1141         goto out;
1142     }
1143     
1144     rep.pvno = 5;
1145     rep.msg_type = krb_as_rep;
1146     copy_Realm(&client->principal->realm, &rep.crealm);
1147     if (f.request_anonymous)
1148         make_anonymous_principalname (&rep.cname);
1149     else
1150         _krb5_principal2principalname(&rep.cname, 
1151                                       client->principal);
1152     rep.ticket.tkt_vno = 5;
1153     copy_Realm(&server->principal->realm, &rep.ticket.realm);
1154     _krb5_principal2principalname(&rep.ticket.sname, 
1155                                   server->principal);
1156
1157     et.flags.initial = 1;
1158     if(client->flags.forwardable && server->flags.forwardable)
1159         et.flags.forwardable = f.forwardable;
1160     else if (f.forwardable) {
1161         ret = KRB5KDC_ERR_POLICY;
1162         kdc_log(context, config, 0,
1163                 "Ticket may not be forwardable -- %s", client_name);
1164         goto out;
1165     }
1166     if(client->flags.proxiable && server->flags.proxiable)
1167         et.flags.proxiable = f.proxiable;
1168     else if (f.proxiable) {
1169         ret = KRB5KDC_ERR_POLICY;
1170         kdc_log(context, config, 0, 
1171                 "Ticket may not be proxiable -- %s", client_name);
1172         goto out;
1173     }
1174     if(client->flags.postdate && server->flags.postdate)
1175         et.flags.may_postdate = f.allow_postdate;
1176     else if (f.allow_postdate){
1177         ret = KRB5KDC_ERR_POLICY;
1178         kdc_log(context, config, 0,
1179                 "Ticket may not be postdatable -- %s", client_name);
1180         goto out;
1181     }
1182
1183     /* check for valid set of addresses */
1184     if(!check_addresses(context, config, b->addresses, from_addr)) {
1185         ret = KRB5KRB_AP_ERR_BADADDR;
1186         kdc_log(context, config, 0,
1187                 "Bad address list requested -- %s", client_name);
1188         goto out;
1189     }
1190
1191     krb5_generate_random_keyblock(context, setype, &et.key);
1192     copy_PrincipalName(&rep.cname, &et.cname);
1193     copy_Realm(&rep.crealm, &et.crealm);
1194     
1195     {
1196         time_t start;
1197         time_t t;
1198         
1199         start = et.authtime = kdc_time;
1200     
1201         if(f.postdated && req->req_body.from){
1202             ALLOC(et.starttime);
1203             start = *et.starttime = *req->req_body.from;
1204             et.flags.invalid = 1;
1205             et.flags.postdated = 1; /* XXX ??? */
1206         }
1207         fix_time(&b->till);
1208         t = *b->till;
1209
1210         /* be careful not overflowing */
1211
1212         if(client->max_life)
1213             t = start + min(t - start, *client->max_life);
1214         if(server->max_life)
1215             t = start + min(t - start, *server->max_life);
1216 #if 0
1217         t = min(t, start + realm->max_life);
1218 #endif
1219         et.endtime = t;
1220         if(f.renewable_ok && et.endtime < *b->till){
1221             f.renewable = 1;
1222             if(b->rtime == NULL){
1223                 ALLOC(b->rtime);
1224                 *b->rtime = 0;
1225             }
1226             if(*b->rtime < *b->till)
1227                 *b->rtime = *b->till;
1228         }
1229         if(f.renewable && b->rtime){
1230             t = *b->rtime;
1231             if(t == 0)
1232                 t = MAX_TIME;
1233             if(client->max_renew)
1234                 t = start + min(t - start, *client->max_renew);
1235             if(server->max_renew)
1236                 t = start + min(t - start, *server->max_renew);
1237 #if 0
1238             t = min(t, start + realm->max_renew);
1239 #endif
1240             ALLOC(et.renew_till);
1241             *et.renew_till = t;
1242             et.flags.renewable = 1;
1243         }
1244     }
1245
1246     if (f.request_anonymous)
1247         et.flags.anonymous = 1;
1248     
1249     if(b->addresses){
1250         ALLOC(et.caddr);
1251         copy_HostAddresses(b->addresses, et.caddr);
1252     }
1253     
1254     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1255     krb5_data_zero(&et.transited.contents); 
1256      
1257     copy_EncryptionKey(&et.key, &ek.key);
1258
1259     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1260      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1261      * incapable of correctly decoding SEQUENCE OF's of zero length.
1262      *
1263      * To fix this, always send at least one no-op last_req
1264      *
1265      * If there's a pw_end or valid_end we will use that,
1266      * otherwise just a dummy lr.
1267      */
1268     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1269     ek.last_req.len = 0;
1270     if (client->pw_end
1271         && (config->kdc_warn_pwexpire == 0
1272             || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) {
1273         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1274         ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
1275         ++ek.last_req.len;
1276     }
1277     if (client->valid_end) {
1278         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1279         ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
1280         ++ek.last_req.len;
1281     }
1282     if (ek.last_req.len == 0) {
1283         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1284         ek.last_req.val[ek.last_req.len].lr_value = 0;
1285         ++ek.last_req.len;
1286     }
1287     ek.nonce = b->nonce;
1288     if (client->valid_end || client->pw_end) {
1289         ALLOC(ek.key_expiration);
1290         if (client->valid_end) {
1291             if (client->pw_end)
1292                 *ek.key_expiration = min(*client->valid_end, *client->pw_end);
1293             else
1294                 *ek.key_expiration = *client->valid_end;
1295         } else
1296             *ek.key_expiration = *client->pw_end;
1297     } else
1298         ek.key_expiration = NULL;
1299     ek.flags = et.flags;
1300     ek.authtime = et.authtime;
1301     if (et.starttime) {
1302         ALLOC(ek.starttime);
1303         *ek.starttime = *et.starttime;
1304     }
1305     ek.endtime = et.endtime;
1306     if (et.renew_till) {
1307         ALLOC(ek.renew_till);
1308         *ek.renew_till = *et.renew_till;
1309     }
1310     copy_Realm(&rep.ticket.realm, &ek.srealm);
1311     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1312     if(et.caddr){
1313         ALLOC(ek.caddr);
1314         copy_HostAddresses(et.caddr, ek.caddr);
1315     }
1316
1317     ALLOC(rep.padata);
1318     rep.padata->len = 0;
1319     rep.padata->val = NULL;
1320
1321     reply_key = &ckey->key;
1322 #if PKINIT
1323     if (pkp) {
1324         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 
1325                                   req, req_buffer, 
1326                                   &reply_key, rep.padata);
1327         if (ret)
1328             goto out;
1329     }
1330 #endif
1331
1332     set_salt_padata (rep.padata, ckey->salt);
1333
1334     if (rep.padata->len == 0) {
1335         free(rep.padata);
1336         rep.padata = NULL;
1337     }
1338
1339     log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 
1340                   et.endtime, et.renew_till);
1341
1342     ret = encode_reply(context, config, 
1343                        &rep, &et, &ek, setype, server->kvno, &skey->key,
1344                        client->kvno, reply_key, &e_text, reply);
1345     free_EncTicketPart(&et);
1346     free_EncKDCRepPart(&ek);
1347  out:
1348     free_AS_REP(&rep);
1349     if(ret){
1350         krb5_mk_error(context,
1351                       ret,
1352                       e_text,
1353                       NULL,
1354                       client_princ,
1355                       server_princ,
1356                       NULL,
1357                       NULL,
1358                       reply);
1359         ret = 0;
1360     }
1361  out2:
1362 #ifdef PKINIT
1363     if (pkp)
1364         _kdc_pk_free_client_param(context, pkp);
1365 #endif
1366     if (client_princ)
1367         krb5_free_principal(context, client_princ);
1368     free(client_name);
1369     if (server_princ)
1370         krb5_free_principal(context, server_princ);
1371     free(server_name);
1372     if(client)
1373         _kdc_free_ent(context, client);
1374     if(server)
1375         _kdc_free_ent(context, server);
1376     return ret;
1377 }
1378
1379
1380 static krb5_error_code
1381 check_tgs_flags(krb5_context context,        
1382                 krb5_kdc_configuration *config,
1383                 KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
1384 {
1385     KDCOptions f = b->kdc_options;
1386         
1387     if(f.validate){
1388         if(!tgt->flags.invalid || tgt->starttime == NULL){
1389             kdc_log(context, config, 0,
1390                     "Bad request to validate ticket");
1391             return KRB5KDC_ERR_BADOPTION;
1392         }
1393         if(*tgt->starttime > kdc_time){
1394             kdc_log(context, config, 0,
1395                     "Early request to validate ticket");
1396             return KRB5KRB_AP_ERR_TKT_NYV;
1397         }
1398         /* XXX  tkt = tgt */
1399         et->flags.invalid = 0;
1400     }else if(tgt->flags.invalid){
1401         kdc_log(context, config, 0, 
1402                 "Ticket-granting ticket has INVALID flag set");
1403         return KRB5KRB_AP_ERR_TKT_INVALID;
1404     }
1405
1406     if(f.forwardable){
1407         if(!tgt->flags.forwardable){
1408             kdc_log(context, config, 0,
1409                     "Bad request for forwardable ticket");
1410             return KRB5KDC_ERR_BADOPTION;
1411         }
1412         et->flags.forwardable = 1;
1413     }
1414     if(f.forwarded){
1415         if(!tgt->flags.forwardable){
1416             kdc_log(context, config, 0,
1417                     "Request to forward non-forwardable ticket");
1418             return KRB5KDC_ERR_BADOPTION;
1419         }
1420         et->flags.forwarded = 1;
1421         et->caddr = b->addresses;
1422     }
1423     if(tgt->flags.forwarded)
1424         et->flags.forwarded = 1;
1425         
1426     if(f.proxiable){
1427         if(!tgt->flags.proxiable){
1428             kdc_log(context, config, 0,
1429                     "Bad request for proxiable ticket");
1430             return KRB5KDC_ERR_BADOPTION;
1431         }
1432         et->flags.proxiable = 1;
1433     }
1434     if(f.proxy){
1435         if(!tgt->flags.proxiable){
1436             kdc_log(context, config, 0,
1437                     "Request to proxy non-proxiable ticket");
1438             return KRB5KDC_ERR_BADOPTION;
1439         }
1440         et->flags.proxy = 1;
1441         et->caddr = b->addresses;
1442     }
1443     if(tgt->flags.proxy)
1444         et->flags.proxy = 1;
1445
1446     if(f.allow_postdate){
1447         if(!tgt->flags.may_postdate){
1448             kdc_log(context, config, 0,
1449                     "Bad request for post-datable ticket");
1450             return KRB5KDC_ERR_BADOPTION;
1451         }
1452         et->flags.may_postdate = 1;
1453     }
1454     if(f.postdated){
1455         if(!tgt->flags.may_postdate){
1456             kdc_log(context, config, 0,
1457                     "Bad request for postdated ticket");
1458             return KRB5KDC_ERR_BADOPTION;
1459         }
1460         if(b->from)
1461             *et->starttime = *b->from;
1462         et->flags.postdated = 1;
1463         et->flags.invalid = 1;
1464     }else if(b->from && *b->from > kdc_time + context->max_skew){
1465         kdc_log(context, config, 0, "Ticket cannot be postdated");
1466         return KRB5KDC_ERR_CANNOT_POSTDATE;
1467     }
1468
1469     if(f.renewable){
1470         if(!tgt->flags.renewable){
1471             kdc_log(context, config, 0,
1472                     "Bad request for renewable ticket");
1473             return KRB5KDC_ERR_BADOPTION;
1474         }
1475         et->flags.renewable = 1;
1476         ALLOC(et->renew_till);
1477         fix_time(&b->rtime);
1478         *et->renew_till = *b->rtime;
1479     }
1480     if(f.renew){
1481         time_t old_life;
1482         if(!tgt->flags.renewable || tgt->renew_till == NULL){
1483             kdc_log(context, config, 0,
1484                     "Request to renew non-renewable ticket");
1485             return KRB5KDC_ERR_BADOPTION;
1486         }
1487         old_life = tgt->endtime;
1488         if(tgt->starttime)
1489             old_life -= *tgt->starttime;
1490         else
1491             old_life -= tgt->authtime;
1492         et->endtime = *et->starttime + old_life;
1493         if (et->renew_till != NULL)
1494             et->endtime = min(*et->renew_till, et->endtime);
1495     }       
1496     
1497     /* checks for excess flags */
1498     if(f.request_anonymous && !config->allow_anonymous){
1499         kdc_log(context, config, 0,
1500                 "Request for anonymous ticket");
1501         return KRB5KDC_ERR_BADOPTION;
1502     }
1503     return 0;
1504 }
1505
1506 static krb5_error_code
1507 fix_transited_encoding(krb5_context context, 
1508                        krb5_kdc_configuration *config,
1509                        krb5_boolean check_policy,
1510                        TransitedEncoding *tr, 
1511                        EncTicketPart *et, 
1512                        const char *client_realm, 
1513                        const char *server_realm, 
1514                        const char *tgt_realm)
1515 {
1516     krb5_error_code ret = 0;
1517     char **realms, **tmp;
1518     int num_realms;
1519     int i;
1520
1521     switch (tr->tr_type) {
1522     case DOMAIN_X500_COMPRESS:
1523         break;
1524     case 0:
1525         /*
1526          * Allow empty content of type 0 because that is was Microsoft
1527          * generates in their TGT.
1528          */
1529         if (tr->contents.length == 0)
1530             break;
1531         kdc_log(context, config, 0,
1532                 "Transited type 0 with non empty content");
1533         return KRB5KDC_ERR_TRTYPE_NOSUPP;
1534     default:
1535         kdc_log(context, config, 0,
1536                 "Unknown transited type: %u", tr->tr_type);
1537         return KRB5KDC_ERR_TRTYPE_NOSUPP;
1538     }
1539
1540     ret = krb5_domain_x500_decode(context, 
1541                                   tr->contents,
1542                                   &realms, 
1543                                   &num_realms,
1544                                   client_realm,
1545                                   server_realm);
1546     if(ret){
1547         krb5_warn(context, ret,
1548                   "Decoding transited encoding");
1549         return ret;
1550     }
1551     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1552         /* not us, so add the previous realm to transited set */
1553         if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1554             ret = ERANGE;
1555             goto free_realms;
1556         }
1557         tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1558         if(tmp == NULL){
1559             ret = ENOMEM;
1560             goto free_realms;
1561         }
1562         realms = tmp;
1563         realms[num_realms] = strdup(tgt_realm);
1564         if(realms[num_realms] == NULL){
1565             ret = ENOMEM;
1566             goto free_realms;
1567         }
1568         num_realms++;
1569     }
1570     if(num_realms == 0) {
1571         if(strcmp(client_realm, server_realm)) 
1572             kdc_log(context, config, 0,
1573                     "cross-realm %s -> %s", client_realm, server_realm);
1574     } else {
1575         size_t l = 0;
1576         char *rs;
1577         for(i = 0; i < num_realms; i++)
1578             l += strlen(realms[i]) + 2;
1579         rs = malloc(l);
1580         if(rs != NULL) {
1581             *rs = '\0';
1582             for(i = 0; i < num_realms; i++) {
1583                 if(i > 0)
1584                     strlcat(rs, ", ", l);
1585                 strlcat(rs, realms[i], l);
1586             }
1587             kdc_log(context, config, 0,
1588                     "cross-realm %s -> %s via [%s]",
1589                     client_realm, server_realm, rs);
1590             free(rs);
1591         }
1592     }
1593     if(check_policy) {
1594         ret = krb5_check_transited(context, client_realm, 
1595                                    server_realm, 
1596                                    realms, num_realms, NULL);
1597         if(ret) {
1598             krb5_warn(context, ret, "cross-realm %s -> %s", 
1599                       client_realm, server_realm);
1600             goto free_realms;
1601         }
1602         et->flags.transited_policy_checked = 1;
1603     }
1604     et->transited.tr_type = DOMAIN_X500_COMPRESS;
1605     ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1606     if(ret)
1607         krb5_warn(context, ret, "Encoding transited encoding");
1608   free_realms:
1609     for(i = 0; i < num_realms; i++)
1610         free(realms[i]);
1611     free(realms);
1612     return ret;
1613 }
1614
1615
1616 static krb5_error_code
1617 tgs_make_reply(krb5_context context, 
1618                krb5_kdc_configuration *config,
1619                KDC_REQ_BODY *b, 
1620                EncTicketPart *tgt, 
1621                EncTicketPart *adtkt, 
1622                AuthorizationData *auth_data,
1623                krb5_ticket *tgs_ticket,
1624                hdb_entry *server, 
1625                hdb_entry *client, 
1626                krb5_principal client_principal, 
1627                hdb_entry *krbtgt,
1628                EncryptionKey *tgtkey,
1629                krb5_enctype cetype,
1630                const char **e_text,
1631                krb5_data *reply)
1632 {
1633     KDC_REP rep;
1634     EncKDCRepPart ek;
1635     EncTicketPart et;
1636     KDCOptions f = b->kdc_options;
1637     krb5_error_code ret;
1638     krb5_enctype etype;
1639     Key *skey;
1640     EncryptionKey *ekey;
1641     
1642     if(adtkt) {
1643         int i;
1644         krb5_keytype kt;
1645         ekey = &adtkt->key;
1646         for(i = 0; i < b->etype.len; i++){
1647             ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1648             if(ret)
1649                 continue;
1650             if(adtkt->key.keytype == kt)
1651                 break;
1652         }
1653         if(i == b->etype.len)
1654             return KRB5KDC_ERR_ETYPE_NOSUPP;
1655         etype = b->etype.val[i];
1656     }else{
1657         ret = find_keys(context, config, 
1658                         NULL, server, NULL, NULL, &skey, &etype, 
1659                         b->etype.val, b->etype.len);
1660         if(ret) {
1661             kdc_log(context, config, 0, "Server has no support for etypes");
1662             return ret;
1663         }
1664         ekey = &skey->key;
1665     }
1666     
1667     memset(&rep, 0, sizeof(rep));
1668     memset(&et, 0, sizeof(et));
1669     memset(&ek, 0, sizeof(ek));
1670     
1671     rep.pvno = 5;
1672     rep.msg_type = krb_tgs_rep;
1673
1674     et.authtime = tgt->authtime;
1675     fix_time(&b->till);
1676     et.endtime = min(tgt->endtime, *b->till);
1677     ALLOC(et.starttime);
1678     *et.starttime = kdc_time;
1679     
1680     ret = check_tgs_flags(context, config, b, tgt, &et);
1681     if(ret)
1682         goto out;
1683
1684     /* We should check the transited encoding if:
1685        1) the request doesn't ask not to be checked
1686        2) globally enforcing a check
1687        3) principal requires checking
1688        4) we allow non-check per-principal, but principal isn't marked as allowing this
1689        5) we don't globally allow this
1690     */
1691
1692 #define GLOBAL_FORCE_TRANSITED_CHECK            \
1693         (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
1694 #define GLOBAL_ALLOW_PER_PRINCIPAL              \
1695         (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1696 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK    \
1697         (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1698
1699 /* these will consult the database in future release */
1700 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P)              0
1701 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)      0
1702
1703     ret = fix_transited_encoding(context, config, 
1704                                  !f.disable_transited_check ||
1705                                  GLOBAL_FORCE_TRANSITED_CHECK ||
1706                                  PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1707                                  !((GLOBAL_ALLOW_PER_PRINCIPAL && 
1708                                     PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1709                                    GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1710                                  &tgt->transited, &et,
1711                                  *krb5_princ_realm(context, client_principal),
1712                                  *krb5_princ_realm(context, server->principal),
1713                                  *krb5_princ_realm(context, krbtgt->principal));
1714     if(ret)
1715         goto out;
1716
1717     copy_Realm(krb5_princ_realm(context, server->principal), 
1718                &rep.ticket.realm);
1719     _krb5_principal2principalname(&rep.ticket.sname, server->principal);
1720     copy_Realm(&tgt->crealm, &rep.crealm);
1721     if (f.request_anonymous)
1722         make_anonymous_principalname (&tgt->cname);
1723     else
1724         copy_PrincipalName(&tgt->cname, &rep.cname);
1725     rep.ticket.tkt_vno = 5;
1726
1727     ek.caddr = et.caddr;
1728     if(et.caddr == NULL)
1729         et.caddr = tgt->caddr;
1730
1731     {
1732         time_t life;
1733         life = et.endtime - *et.starttime;
1734         if(client && client->max_life)
1735             life = min(life, *client->max_life);
1736         if(server->max_life)
1737             life = min(life, *server->max_life);
1738         et.endtime = *et.starttime + life;
1739     }
1740     if(f.renewable_ok && tgt->flags.renewable && 
1741        et.renew_till == NULL && et.endtime < *b->till){
1742         et.flags.renewable = 1;
1743         ALLOC(et.renew_till);
1744         *et.renew_till = *b->till;
1745     }
1746     if(et.renew_till){
1747         time_t renew;
1748         renew = *et.renew_till - et.authtime;
1749         if(client && client->max_renew)
1750             renew = min(renew, *client->max_renew);
1751         if(server->max_renew)
1752             renew = min(renew, *server->max_renew);
1753         *et.renew_till = et.authtime + renew;
1754     }
1755             
1756     if(et.renew_till){
1757         *et.renew_till = min(*et.renew_till, *tgt->renew_till);
1758         *et.starttime = min(*et.starttime, *et.renew_till);
1759         et.endtime = min(et.endtime, *et.renew_till);
1760     }
1761     
1762     *et.starttime = min(*et.starttime, et.endtime);
1763
1764     if(*et.starttime == et.endtime){
1765         ret = KRB5KDC_ERR_NEVER_VALID;
1766         goto out;
1767     }
1768     if(et.renew_till && et.endtime == *et.renew_till){
1769         free(et.renew_till);
1770         et.renew_till = NULL;
1771         et.flags.renewable = 0;
1772     }
1773     
1774     et.flags.pre_authent = tgt->flags.pre_authent;
1775     et.flags.hw_authent  = tgt->flags.hw_authent;
1776     et.flags.anonymous   = tgt->flags.anonymous;
1777     et.flags.ok_as_delegate = server->flags.ok_as_delegate;
1778             
1779 #ifdef _SAMBA_BUILD_
1780  
1781     {
1782
1783             unsigned char *buf;
1784             size_t buf_size;
1785             size_t len;
1786
1787             krb5_data pac;
1788             AD_IF_RELEVANT *if_relevant;
1789             ALLOC(if_relevant);
1790             if_relevant->len = 1;
1791             if_relevant->val = malloc(sizeof(*if_relevant->val));
1792             if_relevant->val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
1793             if_relevant->val[0].ad_data.data = NULL;
1794             if_relevant->val[0].ad_data.length = 0;
1795
1796             /* Get PAC from Samba */
1797             ret = samba_get_pac(context, config, 
1798                                 client->principal,
1799                                 tgtkey,
1800                                 ekey,
1801                                 tgs_ticket->ticket.authtime,
1802                                 &pac);
1803             if (ret) {
1804                     free_AuthorizationData(if_relevant);
1805                     goto out;
1806             }
1807
1808             /* pac.data will be freed with this */
1809             if_relevant->val[0].ad_data.data = pac.data;
1810             if_relevant->val[0].ad_data.length = pac.length;
1811
1812             ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
1813             
1814             auth_data = NULL;
1815             ALLOC(auth_data);
1816             auth_data->len = 1;
1817             auth_data->val = malloc(sizeof(*auth_data->val));
1818             auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1819             auth_data->val[0].ad_data.length = len;
1820             auth_data->val[0].ad_data.data = buf;
1821             if (ret) {
1822                     goto out;
1823             }
1824     }
1825
1826 #endif
1827     /* XXX Check enc-authorization-data */
1828     et.authorization_data = auth_data;
1829
1830     krb5_generate_random_keyblock(context, etype, &et.key);
1831     et.crealm = tgt->crealm;
1832     et.cname = tgt->cname;
1833             
1834     ek.key = et.key;
1835     /* MIT must have at least one last_req */
1836     ek.last_req.len = 1;
1837     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1838     ek.nonce = b->nonce;
1839     ek.flags = et.flags;
1840     ek.authtime = et.authtime;
1841     ek.starttime = et.starttime;
1842     ek.endtime = et.endtime;
1843     ek.renew_till = et.renew_till;
1844     ek.srealm = rep.ticket.realm;
1845     ek.sname = rep.ticket.sname;
1846     
1847     log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, 
1848                   et.endtime, et.renew_till);
1849
1850     /* It is somewhat unclear where the etype in the following
1851        encryption should come from. What we have is a session
1852        key in the passed tgt, and a list of preferred etypes
1853        *for the new ticket*. Should we pick the best possible
1854        etype, given the keytype in the tgt, or should we look
1855        at the etype list here as well?  What if the tgt
1856        session key is DES3 and we want a ticket with a (say)
1857        CAST session key. Should the DES3 etype be added to the
1858        etype list, even if we don't want a session key with
1859        DES3? */
1860     ret = encode_reply(context, config, 
1861                        &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1862                        0, &tgt->key, e_text, reply);
1863   out:
1864     free_TGS_REP(&rep);
1865     free_TransitedEncoding(&et.transited);
1866     if(et.starttime)
1867         free(et.starttime);
1868     if(et.renew_till)
1869         free(et.renew_till);
1870     free_LastReq(&ek.last_req);
1871     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1872     free_EncryptionKey(&et.key);
1873     return ret;
1874 }
1875
1876 static krb5_error_code
1877 tgs_check_authenticator(krb5_context context, 
1878                         krb5_kdc_configuration *config,
1879                         krb5_auth_context ac,
1880                         KDC_REQ_BODY *b, 
1881                         const char **e_text,
1882                         krb5_keyblock *key)
1883 {
1884     krb5_authenticator auth;
1885     size_t len;
1886     unsigned char *buf;
1887     size_t buf_size;
1888     krb5_error_code ret;
1889     krb5_crypto crypto;
1890     
1891     krb5_auth_con_getauthenticator(context, ac, &auth);
1892     if(auth->cksum == NULL){
1893         kdc_log(context, config, 0, "No authenticator in request");
1894         ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1895         goto out;
1896     }
1897     /*
1898      * according to RFC1510 it doesn't need to be keyed,
1899      * but according to the latest draft it needs to.
1900      */
1901     if (
1902 #if 0
1903 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1904         ||
1905 #endif
1906  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1907         kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", 
1908                 auth->cksum->cksumtype);
1909         ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
1910         goto out;
1911     }
1912                 
1913     /* XXX should not re-encode this */
1914     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1915     if(ret){
1916         kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", 
1917                 krb5_get_err_text(context, ret));
1918         goto out;
1919     }
1920     if(buf_size != len) {
1921         free(buf);
1922         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1923         *e_text = "KDC internal error";
1924         ret = KRB5KRB_ERR_GENERIC;
1925         goto out;
1926     }
1927     ret = krb5_crypto_init(context, key, 0, &crypto);
1928     if (ret) {
1929         free(buf);
1930         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1931                 krb5_get_err_text(context, ret));
1932         goto out;
1933     }
1934     ret = krb5_verify_checksum(context,
1935                                crypto,
1936                                KRB5_KU_TGS_REQ_AUTH_CKSUM,
1937                                buf, 
1938                                len,
1939                                auth->cksum);
1940     free(buf);
1941     krb5_crypto_destroy(context, crypto);
1942     if(ret){
1943         kdc_log(context, config, 0,
1944                 "Failed to verify authenticator checksum: %s", 
1945                 krb5_get_err_text(context, ret));
1946     }
1947 out:
1948     free_Authenticator(auth);
1949     free(auth);
1950     return ret;
1951 }
1952
1953 /*
1954  * return the realm of a krbtgt-ticket or NULL
1955  */
1956
1957 static Realm 
1958 get_krbtgt_realm(const PrincipalName *p)
1959 {
1960     if(p->name_string.len == 2
1961        && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1962         return p->name_string.val[1];
1963     else
1964         return NULL;
1965 }
1966
1967 static const char *
1968 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1969 {
1970     const char *new_realm = krb5_config_get_string(context,
1971                                                    NULL,
1972                                                    "capaths", 
1973                                                    crealm,
1974                                                    srealm,
1975                                                    NULL);
1976     return new_realm;
1977 }
1978             
1979
1980 static krb5_boolean
1981 need_referral(krb5_context context, krb5_principal server, krb5_realm **realms)
1982 {
1983     if(server->name.name_type != KRB5_NT_SRV_INST ||
1984        server->name.name_string.len != 2)
1985         return FALSE;
1986  
1987     return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
1988                                     FALSE, realms) == 0;
1989 }
1990
1991 static krb5_error_code
1992 tgs_rep2(krb5_context context, 
1993          krb5_kdc_configuration *config,
1994          KDC_REQ_BODY *b,
1995          PA_DATA *tgs_req,
1996          krb5_data *reply,
1997          const char *from,
1998          const struct sockaddr *from_addr,
1999          time_t **csec,
2000          int **cusec)
2001 {
2002     krb5_ap_req ap_req;
2003     krb5_error_code ret;
2004     krb5_principal princ;
2005     krb5_auth_context ac = NULL;
2006     krb5_ticket *ticket = NULL;
2007     krb5_flags ap_req_options;
2008     krb5_flags verify_ap_req_flags;
2009     const char *e_text = NULL;
2010     krb5_crypto crypto;
2011
2012     hdb_entry *krbtgt = NULL;
2013     EncTicketPart *tgt;
2014     Key *tkey;
2015     krb5_enctype cetype;
2016     krb5_principal cp = NULL;
2017     krb5_principal sp = NULL;
2018     AuthorizationData *auth_data = NULL;
2019
2020     *csec  = NULL;
2021     *cusec = NULL;
2022
2023     memset(&ap_req, 0, sizeof(ap_req));
2024     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
2025     if(ret){
2026         kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", 
2027                 krb5_get_err_text(context, ret));
2028         goto out2;
2029     }
2030     
2031     if(!get_krbtgt_realm(&ap_req.ticket.sname)){
2032         /* XXX check for ticket.sname == req.sname */
2033         kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
2034         ret = KRB5KDC_ERR_POLICY; /* ? */
2035         goto out2;
2036     }
2037     
2038     _krb5_principalname2krb5_principal(&princ,
2039                                        ap_req.ticket.sname,
2040                                        ap_req.ticket.realm);
2041     
2042     ret = _kdc_db_fetch(context, config, princ, HDB_ENT_TYPE_SERVER, &krbtgt);
2043
2044     if(ret) {
2045         char *p;
2046         ret = krb5_unparse_name(context, princ, &p);
2047         if (ret != 0)
2048             p = "<unparse_name failed>";
2049         krb5_free_principal(context, princ);
2050         kdc_log(context, config, 0,
2051                 "Ticket-granting ticket not found in database: %s: %s",
2052                 p, krb5_get_err_text(context, ret));
2053         if (ret == 0)
2054             free(p);
2055         ret = KRB5KRB_AP_ERR_NOT_US;
2056         goto out2;
2057     }
2058     
2059     if(ap_req.ticket.enc_part.kvno && 
2060        *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
2061         char *p;
2062
2063         ret = krb5_unparse_name (context, princ, &p);
2064         krb5_free_principal(context, princ);
2065         if (ret != 0)
2066             p = "<unparse_name failed>";
2067         kdc_log(context, config, 0,
2068                 "Ticket kvno = %d, DB kvno = %d (%s)", 
2069                 *ap_req.ticket.enc_part.kvno,
2070                 krbtgt->kvno,
2071                 p);
2072         if (ret == 0)
2073             free (p);
2074         ret = KRB5KRB_AP_ERR_BADKEYVER;
2075         goto out2;
2076     }
2077
2078     ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
2079     if(ret){
2080         char *str;
2081         krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
2082         kdc_log(context, config, 0,
2083                 "No server key found for %s", str);
2084         free(str);
2085         ret = KRB5KRB_AP_ERR_BADKEYVER;
2086         goto out2;
2087     }
2088     
2089     if (b->kdc_options.validate)
2090         verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
2091     else
2092         verify_ap_req_flags = 0;
2093
2094     ret = krb5_verify_ap_req2(context,
2095                               &ac,
2096                               &ap_req,
2097                               princ,
2098                               &tkey->key,
2099                               verify_ap_req_flags,
2100                               &ap_req_options,
2101                               &ticket,
2102                               KRB5_KU_TGS_REQ_AUTH);
2103                              
2104     krb5_free_principal(context, princ);
2105     if(ret) {
2106         kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", 
2107                 krb5_get_err_text(context, ret));
2108         goto out2;
2109     }
2110
2111     {
2112         krb5_authenticator auth;
2113
2114         ret = krb5_auth_con_getauthenticator(context, ac, &auth);
2115         if (ret == 0) {
2116             *csec   = malloc(sizeof(**csec));
2117             if (*csec == NULL) {
2118                 krb5_free_authenticator(context, &auth);
2119                 kdc_log(context, config, 0, "malloc failed");
2120                 goto out2;
2121             }
2122             **csec  = auth->ctime;
2123             *cusec  = malloc(sizeof(**cusec));
2124             if (*cusec == NULL) {
2125                 krb5_free_authenticator(context, &auth);
2126                 kdc_log(context, config, 0, "malloc failed");
2127                 goto out2;
2128             }
2129             **csec  = auth->cusec;
2130             krb5_free_authenticator(context, &auth);
2131         }
2132     }
2133
2134     cetype = ap_req.authenticator.etype;
2135
2136     tgt = &ticket->ticket;
2137
2138     ret = tgs_check_authenticator(context, config, 
2139                                   ac, b, &e_text, &tgt->key);
2140     if (ret) {
2141         krb5_auth_con_free(context, ac);
2142         goto out2;
2143     }
2144
2145     if (b->enc_authorization_data) {
2146         krb5_keyblock *subkey;
2147         krb5_data ad;
2148         ret = krb5_auth_con_getremotesubkey(context,
2149                                             ac,
2150                                             &subkey);
2151         if(ret){
2152             krb5_auth_con_free(context, ac);
2153             kdc_log(context, config, 0, "Failed to get remote subkey: %s", 
2154                     krb5_get_err_text(context, ret));
2155             goto out2;
2156         }
2157         if(subkey == NULL){
2158             ret = krb5_auth_con_getkey(context, ac, &subkey);
2159             if(ret) {
2160                 krb5_auth_con_free(context, ac);
2161                 kdc_log(context, config, 0, "Failed to get session key: %s", 
2162                         krb5_get_err_text(context, ret));
2163                 goto out2;
2164             }
2165         }
2166         if(subkey == NULL){
2167             krb5_auth_con_free(context, ac);
2168             kdc_log(context, config, 0,
2169                     "Failed to get key for enc-authorization-data");
2170             ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2171             goto out2;
2172         }
2173         ret = krb5_crypto_init(context, subkey, 0, &crypto);
2174         if (ret) {
2175             krb5_auth_con_free(context, ac);
2176             kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
2177                     krb5_get_err_text(context, ret));
2178             goto out2;
2179         }
2180         ret = krb5_decrypt_EncryptedData (context,
2181                                           crypto,
2182                                           KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
2183                                           b->enc_authorization_data,
2184                                           &ad);
2185         krb5_crypto_destroy(context, crypto);
2186         if(ret){
2187             krb5_auth_con_free(context, ac);
2188             kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data");
2189             ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2190             goto out2;
2191         }
2192         krb5_free_keyblock(context, subkey);
2193         ALLOC(auth_data);
2194         ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
2195         if(ret){
2196             krb5_auth_con_free(context, ac);
2197             free(auth_data);
2198             auth_data = NULL;
2199             kdc_log(context, config, 0, "Failed to decode authorization data");
2200             ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
2201             goto out2;
2202         }
2203     }
2204
2205     krb5_auth_con_free(context, ac);
2206
2207     {
2208         PrincipalName *s;
2209         Realm r;
2210         char *spn = NULL, *cpn = NULL;
2211         hdb_entry *server = NULL, *client = NULL;
2212         int nloop = 0;
2213         EncTicketPart adtkt;
2214         char opt_str[128];
2215
2216         s = b->sname;
2217         r = b->realm;
2218         if(b->kdc_options.enc_tkt_in_skey){
2219             Ticket *t;
2220             hdb_entry *uu;
2221             krb5_principal p;
2222             Key *uukey;
2223             
2224             if(b->additional_tickets == NULL || 
2225                b->additional_tickets->len == 0){
2226                 ret = KRB5KDC_ERR_BADOPTION; /* ? */
2227                 kdc_log(context, config, 0,
2228                         "No second ticket present in request");
2229                 goto out;
2230             }
2231             t = &b->additional_tickets->val[0];
2232             if(!get_krbtgt_realm(&t->sname)){
2233                 kdc_log(context, config, 0,
2234                         "Additional ticket is not a ticket-granting ticket");
2235                 ret = KRB5KDC_ERR_POLICY;
2236                 goto out2;
2237             }
2238             _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
2239             ret = _kdc_db_fetch(context, config, p, HDB_ENT_TYPE_SERVER, &uu);
2240             krb5_free_principal(context, p);
2241             if(ret){
2242                 if (ret == HDB_ERR_NOENTRY)
2243                     ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2244                 goto out;
2245             }
2246             ret = hdb_enctype2key(context, uu, t->enc_part.etype, &uukey);
2247             if(ret){
2248                 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
2249                 goto out;
2250             }
2251             ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
2252
2253             if(ret)
2254                 goto out;
2255             s = &adtkt.cname;
2256             r = adtkt.crealm;
2257         }
2258
2259         _krb5_principalname2krb5_principal(&sp, *s, r);
2260         ret = krb5_unparse_name(context, sp, &spn);     
2261         if (ret)
2262             goto out;
2263         _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
2264         ret = krb5_unparse_name(context, cp, &cpn);
2265         if (ret)
2266             goto out;
2267         unparse_flags (KDCOptions2int(b->kdc_options),
2268                        asn1_KDCOptions_units(),
2269                        opt_str, sizeof(opt_str));
2270         if(*opt_str)
2271             kdc_log(context, config, 0,
2272                     "TGS-REQ %s from %s for %s [%s]", 
2273                     cpn, from, spn, opt_str);
2274         else
2275             kdc_log(context, config, 0,
2276                     "TGS-REQ %s from %s for %s", cpn, from, spn);
2277     server_lookup:
2278         ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
2279
2280         if(ret){
2281             const char *new_rlm;
2282             Realm req_rlm;
2283             krb5_realm *realms;
2284
2285             if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
2286                 if(nloop++ < 2) {
2287                     new_rlm = find_rpath(context, tgt->crealm, req_rlm);
2288                     if(new_rlm) {
2289                         kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s", 
2290                                 req_rlm, new_rlm);
2291                         krb5_free_principal(context, sp);
2292                         free(spn);
2293                         krb5_make_principal(context, &sp, r, 
2294                                             KRB5_TGS_NAME, new_rlm, NULL);
2295                         ret = krb5_unparse_name(context, sp, &spn);     
2296                         if (ret)
2297                             goto out;
2298                         goto server_lookup;
2299                     }
2300                 }
2301             } else if(need_referral(context, sp, &realms)) {
2302                 if (strcmp(realms[0], sp->realm) != 0) {
2303                     kdc_log(context, config, 5,
2304                             "Returning a referral to realm %s for "
2305                             "server %s that was not found",
2306                             realms[0], spn);
2307                     krb5_free_principal(context, sp);
2308                     free(spn);
2309                     krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
2310                                         realms[0], NULL);
2311                     ret = krb5_unparse_name(context, sp, &spn);
2312                     if (ret)
2313                         goto out;
2314                     krb5_free_host_realm(context, realms);
2315                     goto server_lookup;
2316                 }
2317                 krb5_free_host_realm(context, realms);
2318             }
2319             kdc_log(context, config, 0,
2320                     "Server not found in database: %s: %s", spn,
2321                     krb5_get_err_text(context, ret));
2322             if (ret == HDB_ERR_NOENTRY)
2323                 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2324             goto out;
2325         }
2326
2327         ret = _kdc_db_fetch(context, config, cp, HDB_ENT_TYPE_CLIENT, &client);
2328         if(ret)
2329             kdc_log(context, config, 1, "Client not found in database: %s: %s",
2330                     cpn, krb5_get_err_text(context, ret));
2331 #if 0
2332         /* XXX check client only if same realm as krbtgt-instance */
2333         if(ret){
2334             kdc_log(context, config, 0,
2335                     "Client not found in database: %s: %s",
2336                     cpn, krb5_get_err_text(context, ret));
2337             if (ret == HDB_ERR_NOENTRY)
2338                 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2339             goto out;
2340         }
2341 #endif
2342
2343         if(strcmp(krb5_principal_get_realm(context, sp),
2344                   krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
2345             char *tpn;
2346             ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
2347             kdc_log(context, config, 0,
2348                     "Request with wrong krbtgt: %s",
2349                     (ret == 0) ? tpn : "<unknown>");
2350             if(ret == 0)
2351                 free(tpn);
2352             ret = KRB5KRB_AP_ERR_NOT_US;
2353             goto out;
2354             
2355         }
2356
2357         ret = _kdc_check_flags(context, config, 
2358                                client, cpn,
2359                                server, spn,
2360                                FALSE);
2361         if(ret)
2362             goto out;
2363
2364         if((b->kdc_options.validate || b->kdc_options.renew) && 
2365            !krb5_principal_compare(context, 
2366                                    krbtgt->principal,
2367                                    server->principal)){
2368             kdc_log(context, config, 0, "Inconsistent request.");
2369             ret = KRB5KDC_ERR_SERVER_NOMATCH;
2370             goto out;
2371         }
2372
2373         /* check for valid set of addresses */
2374         if(!check_addresses(context, config, tgt->caddr, from_addr)) {
2375             ret = KRB5KRB_AP_ERR_BADADDR;
2376             kdc_log(context, config, 0, "Request from wrong address");
2377             goto out;
2378         }
2379         
2380         ret = tgs_make_reply(context, config, 
2381                              b, 
2382                              tgt, 
2383                              b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, 
2384                              auth_data,
2385                              ticket,
2386                              server, 
2387                              client, 
2388                              cp, 
2389                              krbtgt, 
2390                              &tkey->key,
2391                              cetype, 
2392                              &e_text,
2393                              reply);
2394         
2395     out:
2396         free(spn);
2397         free(cpn);
2398             
2399         if(server)
2400             _kdc_free_ent(context, server);
2401         if(client)
2402             _kdc_free_ent(context, client);
2403     }
2404  out2:
2405     if(ret) {
2406         krb5_mk_error(context,
2407                       ret,
2408                       e_text,
2409                       NULL,
2410                       cp,
2411                       sp,
2412                       NULL,
2413                       NULL,
2414                       reply);
2415         free(*csec);
2416         free(*cusec);
2417         *csec  = NULL;
2418         *cusec = NULL;
2419     }
2420     krb5_free_principal(context, cp);
2421     krb5_free_principal(context, sp);
2422     if (ticket)
2423         krb5_free_ticket(context, ticket);
2424     free_AP_REQ(&ap_req);
2425     if(auth_data){
2426         free_AuthorizationData(auth_data);
2427         free(auth_data);
2428     }
2429
2430     if(krbtgt)
2431         _kdc_free_ent(context, krbtgt);
2432
2433     return ret;
2434 }
2435
2436
2437 krb5_error_code
2438 _kdc_tgs_rep(krb5_context context, 
2439              krb5_kdc_configuration *config,
2440              KDC_REQ *req, 
2441              krb5_data *data,
2442              const char *from,
2443              struct sockaddr *from_addr)
2444 {
2445     krb5_error_code ret;
2446     int i = 0;
2447     PA_DATA *tgs_req = NULL;
2448     time_t *csec = NULL;
2449     int *cusec = NULL;
2450
2451     if(req->padata == NULL){
2452         ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2453         kdc_log(context, config, 0,
2454                 "TGS-REQ from %s without PA-DATA", from);
2455         goto out;
2456     }
2457     
2458     tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2459
2460     if(tgs_req == NULL){
2461         ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2462         
2463         kdc_log(context, config, 0, 
2464                 "TGS-REQ from %s without PA-TGS-REQ", from);
2465         goto out;
2466     }
2467     ret = tgs_rep2(context, config, 
2468                    &req->req_body, tgs_req, data, from, from_addr,
2469                    &csec, &cusec);
2470 out:
2471     if(ret && data->data == NULL){
2472         krb5_mk_error(context,
2473                       ret,
2474                       NULL,
2475                       NULL,
2476                       NULL,
2477                       NULL,
2478                       csec,
2479                       cusec,
2480                       data);
2481     }
2482     free(csec);
2483     free(cusec);
2484     return 0;
2485 }