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