Home | History | Annotate | Line # | Download | only in kdc
krb5tgs.c revision 1.3
      1  1.1     elric /*	$NetBSD: krb5tgs.c,v 1.3 2019/12/15 22:50:46 christos Exp $	*/
      2  1.1     elric 
      3  1.1     elric /*
      4  1.1     elric  * Copyright (c) 1997-2008 Kungliga Tekniska Hgskolan
      5  1.1     elric  * (Royal Institute of Technology, Stockholm, Sweden).
      6  1.1     elric  * All rights reserved.
      7  1.1     elric  *
      8  1.1     elric  * Redistribution and use in source and binary forms, with or without
      9  1.1     elric  * modification, are permitted provided that the following conditions
     10  1.1     elric  * are met:
     11  1.1     elric  *
     12  1.1     elric  * 1. Redistributions of source code must retain the above copyright
     13  1.1     elric  *    notice, this list of conditions and the following disclaimer.
     14  1.1     elric  *
     15  1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17  1.1     elric  *    documentation and/or other materials provided with the distribution.
     18  1.1     elric  *
     19  1.1     elric  * 3. Neither the name of the Institute nor the names of its contributors
     20  1.1     elric  *    may be used to endorse or promote products derived from this software
     21  1.1     elric  *    without specific prior written permission.
     22  1.1     elric  *
     23  1.1     elric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  1.1     elric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1     elric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.1     elric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  1.1     elric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.1     elric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.1     elric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1     elric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1     elric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1     elric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1     elric  * SUCH DAMAGE.
     34  1.1     elric  */
     35  1.1     elric 
     36  1.1     elric #include "kdc_locl.h"
     37  1.1     elric 
     38  1.1     elric /*
     39  1.1     elric  * return the realm of a krbtgt-ticket or NULL
     40  1.1     elric  */
     41  1.1     elric 
     42  1.1     elric static Realm
     43  1.1     elric get_krbtgt_realm(const PrincipalName *p)
     44  1.1     elric {
     45  1.1     elric     if(p->name_string.len == 2
     46  1.1     elric        && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
     47  1.1     elric 	return p->name_string.val[1];
     48  1.1     elric     else
     49  1.1     elric 	return NULL;
     50  1.1     elric }
     51  1.1     elric 
     52  1.1     elric /*
     53  1.1     elric  * The KDC might add a signed path to the ticket authorization data
     54  1.1     elric  * field. This is to avoid server impersonating clients and the
     55  1.1     elric  * request constrained delegation.
     56  1.1     elric  *
     57  1.1     elric  * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
     58  1.1     elric  * entry of type KRB5SignedPath.
     59  1.1     elric  */
     60  1.1     elric 
     61  1.1     elric static krb5_error_code
     62  1.1     elric find_KRB5SignedPath(krb5_context context,
     63  1.1     elric 		    const AuthorizationData *ad,
     64  1.1     elric 		    krb5_data *data)
     65  1.1     elric {
     66  1.1     elric     AuthorizationData child;
     67  1.1     elric     krb5_error_code ret;
     68  1.1     elric     int pos;
     69  1.2  christos 
     70  1.1     elric     if (ad == NULL || ad->len == 0)
     71  1.1     elric 	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
     72  1.1     elric 
     73  1.1     elric     pos = ad->len - 1;
     74  1.1     elric 
     75  1.1     elric     if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
     76  1.1     elric 	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
     77  1.1     elric 
     78  1.1     elric     ret = decode_AuthorizationData(ad->val[pos].ad_data.data,
     79  1.1     elric 				   ad->val[pos].ad_data.length,
     80  1.1     elric 				   &child,
     81  1.1     elric 				   NULL);
     82  1.1     elric     if (ret) {
     83  1.1     elric 	krb5_set_error_message(context, ret, "Failed to decode "
     84  1.1     elric 			       "IF_RELEVANT with %d", ret);
     85  1.1     elric 	return ret;
     86  1.1     elric     }
     87  1.1     elric 
     88  1.1     elric     if (child.len != 1) {
     89  1.1     elric 	free_AuthorizationData(&child);
     90  1.1     elric 	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
     91  1.1     elric     }
     92  1.1     elric 
     93  1.1     elric     if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) {
     94  1.1     elric 	free_AuthorizationData(&child);
     95  1.1     elric 	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
     96  1.1     elric     }
     97  1.1     elric 
     98  1.1     elric     if (data)
     99  1.1     elric 	ret = der_copy_octet_string(&child.val[0].ad_data, data);
    100  1.1     elric     free_AuthorizationData(&child);
    101  1.1     elric     return ret;
    102  1.1     elric }
    103  1.1     elric 
    104  1.1     elric krb5_error_code
    105  1.1     elric _kdc_add_KRB5SignedPath(krb5_context context,
    106  1.1     elric 			krb5_kdc_configuration *config,
    107  1.1     elric 			hdb_entry_ex *krbtgt,
    108  1.1     elric 			krb5_enctype enctype,
    109  1.3  christos 			krb5_const_principal client,
    110  1.1     elric 			krb5_const_principal server,
    111  1.1     elric 			krb5_principals principals,
    112  1.1     elric 			EncTicketPart *tkt)
    113  1.1     elric {
    114  1.1     elric     krb5_error_code ret;
    115  1.1     elric     KRB5SignedPath sp;
    116  1.1     elric     krb5_data data;
    117  1.1     elric     krb5_crypto crypto = NULL;
    118  1.2  christos     size_t size = 0;
    119  1.1     elric 
    120  1.1     elric     if (server && principals) {
    121  1.1     elric 	ret = add_Principals(principals, server);
    122  1.1     elric 	if (ret)
    123  1.1     elric 	    return ret;
    124  1.1     elric     }
    125  1.1     elric 
    126  1.1     elric     {
    127  1.1     elric 	KRB5SignedPathData spd;
    128  1.2  christos 
    129  1.3  christos 	spd.client = rk_UNCONST(client);
    130  1.1     elric 	spd.authtime = tkt->authtime;
    131  1.1     elric 	spd.delegated = principals;
    132  1.1     elric 	spd.method_data = NULL;
    133  1.2  christos 
    134  1.1     elric 	ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
    135  1.1     elric 			   &spd, &size, ret);
    136  1.1     elric 	if (ret)
    137  1.1     elric 	    return ret;
    138  1.1     elric 	if (data.length != size)
    139  1.1     elric 	    krb5_abortx(context, "internal asn.1 encoder error");
    140  1.1     elric     }
    141  1.1     elric 
    142  1.1     elric     {
    143  1.1     elric 	Key *key;
    144  1.2  christos 	ret = hdb_enctype2key(context, &krbtgt->entry, NULL, enctype, &key);
    145  1.1     elric 	if (ret == 0)
    146  1.1     elric 	    ret = krb5_crypto_init(context, &key->key, 0, &crypto);
    147  1.1     elric 	if (ret) {
    148  1.1     elric 	    free(data.data);
    149  1.1     elric 	    return ret;
    150  1.1     elric 	}
    151  1.1     elric     }
    152  1.1     elric 
    153  1.1     elric     /*
    154  1.1     elric      * Fill in KRB5SignedPath
    155  1.1     elric      */
    156  1.1     elric 
    157  1.1     elric     sp.etype = enctype;
    158  1.1     elric     sp.delegated = principals;
    159  1.1     elric     sp.method_data = NULL;
    160  1.1     elric 
    161  1.1     elric     ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
    162  1.1     elric 			       data.data, data.length, &sp.cksum);
    163  1.1     elric     krb5_crypto_destroy(context, crypto);
    164  1.1     elric     free(data.data);
    165  1.1     elric     if (ret)
    166  1.1     elric 	return ret;
    167  1.1     elric 
    168  1.1     elric     ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
    169  1.1     elric     free_Checksum(&sp.cksum);
    170  1.1     elric     if (ret)
    171  1.1     elric 	return ret;
    172  1.1     elric     if (data.length != size)
    173  1.1     elric 	krb5_abortx(context, "internal asn.1 encoder error");
    174  1.1     elric 
    175  1.1     elric 
    176  1.1     elric     /*
    177  1.1     elric      * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
    178  1.1     elric      * authorization data field.
    179  1.1     elric      */
    180  1.1     elric 
    181  1.1     elric     ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
    182  1.1     elric 				      KRB5_AUTHDATA_SIGNTICKET, &data);
    183  1.1     elric     krb5_data_free(&data);
    184  1.1     elric 
    185  1.1     elric     return ret;
    186  1.1     elric }
    187  1.1     elric 
    188  1.1     elric static krb5_error_code
    189  1.1     elric check_KRB5SignedPath(krb5_context context,
    190  1.1     elric 		     krb5_kdc_configuration *config,
    191  1.1     elric 		     hdb_entry_ex *krbtgt,
    192  1.1     elric 		     krb5_principal cp,
    193  1.1     elric 		     EncTicketPart *tkt,
    194  1.1     elric 		     krb5_principals *delegated,
    195  1.1     elric 		     int *signedpath)
    196  1.1     elric {
    197  1.1     elric     krb5_error_code ret;
    198  1.1     elric     krb5_data data;
    199  1.1     elric     krb5_crypto crypto = NULL;
    200  1.1     elric 
    201  1.1     elric     if (delegated)
    202  1.1     elric 	*delegated = NULL;
    203  1.1     elric 
    204  1.1     elric     ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
    205  1.1     elric     if (ret == 0) {
    206  1.1     elric 	KRB5SignedPathData spd;
    207  1.1     elric 	KRB5SignedPath sp;
    208  1.2  christos 	size_t size = 0;
    209  1.1     elric 
    210  1.1     elric 	ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
    211  1.1     elric 	krb5_data_free(&data);
    212  1.1     elric 	if (ret)
    213  1.1     elric 	    return ret;
    214  1.1     elric 
    215  1.1     elric 	spd.client = cp;
    216  1.1     elric 	spd.authtime = tkt->authtime;
    217  1.1     elric 	spd.delegated = sp.delegated;
    218  1.1     elric 	spd.method_data = sp.method_data;
    219  1.1     elric 
    220  1.1     elric 	ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
    221  1.1     elric 			   &spd, &size, ret);
    222  1.1     elric 	if (ret) {
    223  1.1     elric 	    free_KRB5SignedPath(&sp);
    224  1.1     elric 	    return ret;
    225  1.1     elric 	}
    226  1.1     elric 	if (data.length != size)
    227  1.1     elric 	    krb5_abortx(context, "internal asn.1 encoder error");
    228  1.1     elric 
    229  1.1     elric 	{
    230  1.1     elric 	    Key *key;
    231  1.2  christos 	    ret = hdb_enctype2key(context, &krbtgt->entry, NULL, /* XXX use correct kvno! */
    232  1.2  christos 				  sp.etype, &key);
    233  1.1     elric 	    if (ret == 0)
    234  1.1     elric 		ret = krb5_crypto_init(context, &key->key, 0, &crypto);
    235  1.1     elric 	    if (ret) {
    236  1.1     elric 		free(data.data);
    237  1.1     elric 		free_KRB5SignedPath(&sp);
    238  1.1     elric 		return ret;
    239  1.1     elric 	    }
    240  1.1     elric 	}
    241  1.1     elric 	ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
    242  1.1     elric 				   data.data, data.length,
    243  1.1     elric 				   &sp.cksum);
    244  1.1     elric 	krb5_crypto_destroy(context, crypto);
    245  1.1     elric 	free(data.data);
    246  1.1     elric 	if (ret) {
    247  1.1     elric 	    free_KRB5SignedPath(&sp);
    248  1.1     elric 	    kdc_log(context, config, 5,
    249  1.1     elric 		    "KRB5SignedPath not signed correctly, not marking as signed");
    250  1.1     elric 	    return 0;
    251  1.1     elric 	}
    252  1.1     elric 
    253  1.1     elric 	if (delegated && sp.delegated) {
    254  1.1     elric 
    255  1.1     elric 	    *delegated = malloc(sizeof(*sp.delegated));
    256  1.1     elric 	    if (*delegated == NULL) {
    257  1.1     elric 		free_KRB5SignedPath(&sp);
    258  1.1     elric 		return ENOMEM;
    259  1.1     elric 	    }
    260  1.1     elric 
    261  1.1     elric 	    ret = copy_Principals(*delegated, sp.delegated);
    262  1.1     elric 	    if (ret) {
    263  1.1     elric 		free_KRB5SignedPath(&sp);
    264  1.1     elric 		free(*delegated);
    265  1.1     elric 		*delegated = NULL;
    266  1.1     elric 		return ret;
    267  1.1     elric 	    }
    268  1.1     elric 	}
    269  1.1     elric 	free_KRB5SignedPath(&sp);
    270  1.1     elric 
    271  1.1     elric 	*signedpath = 1;
    272  1.1     elric     }
    273  1.1     elric 
    274  1.1     elric     return 0;
    275  1.1     elric }
    276  1.1     elric 
    277  1.1     elric /*
    278  1.1     elric  *
    279  1.1     elric  */
    280  1.1     elric 
    281  1.1     elric static krb5_error_code
    282  1.1     elric check_PAC(krb5_context context,
    283  1.1     elric 	  krb5_kdc_configuration *config,
    284  1.1     elric 	  const krb5_principal client_principal,
    285  1.2  christos 	  const krb5_principal delegated_proxy_principal,
    286  1.1     elric 	  hdb_entry_ex *client,
    287  1.1     elric 	  hdb_entry_ex *server,
    288  1.1     elric 	  hdb_entry_ex *krbtgt,
    289  1.2  christos 	  const EncryptionKey *server_check_key,
    290  1.2  christos 	  const EncryptionKey *server_sign_key,
    291  1.1     elric 	  const EncryptionKey *krbtgt_sign_key,
    292  1.1     elric 	  EncTicketPart *tkt,
    293  1.1     elric 	  krb5_data *rspac,
    294  1.1     elric 	  int *signedpath)
    295  1.1     elric {
    296  1.1     elric     AuthorizationData *ad = tkt->authorization_data;
    297  1.1     elric     unsigned i, j;
    298  1.1     elric     krb5_error_code ret;
    299  1.1     elric 
    300  1.1     elric     if (ad == NULL || ad->len == 0)
    301  1.1     elric 	return 0;
    302  1.1     elric 
    303  1.1     elric     for (i = 0; i < ad->len; i++) {
    304  1.1     elric 	AuthorizationData child;
    305  1.1     elric 
    306  1.1     elric 	if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
    307  1.1     elric 	    continue;
    308  1.1     elric 
    309  1.1     elric 	ret = decode_AuthorizationData(ad->val[i].ad_data.data,
    310  1.1     elric 				       ad->val[i].ad_data.length,
    311  1.1     elric 				       &child,
    312  1.1     elric 				       NULL);
    313  1.1     elric 	if (ret) {
    314  1.1     elric 	    krb5_set_error_message(context, ret, "Failed to decode "
    315  1.1     elric 				   "IF_RELEVANT with %d", ret);
    316  1.1     elric 	    return ret;
    317  1.1     elric 	}
    318  1.1     elric 	for (j = 0; j < child.len; j++) {
    319  1.1     elric 
    320  1.1     elric 	    if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
    321  1.1     elric 		int signed_pac = 0;
    322  1.1     elric 		krb5_pac pac;
    323  1.1     elric 
    324  1.1     elric 		/* Found PAC */
    325  1.1     elric 		ret = krb5_pac_parse(context,
    326  1.1     elric 				     child.val[j].ad_data.data,
    327  1.1     elric 				     child.val[j].ad_data.length,
    328  1.1     elric 				     &pac);
    329  1.1     elric 		free_AuthorizationData(&child);
    330  1.1     elric 		if (ret)
    331  1.1     elric 		    return ret;
    332  1.1     elric 
    333  1.1     elric 		ret = krb5_pac_verify(context, pac, tkt->authtime,
    334  1.1     elric 				      client_principal,
    335  1.2  christos 				      server_check_key, NULL);
    336  1.1     elric 		if (ret) {
    337  1.1     elric 		    krb5_pac_free(context, pac);
    338  1.1     elric 		    return ret;
    339  1.1     elric 		}
    340  1.1     elric 
    341  1.1     elric 		ret = _kdc_pac_verify(context, client_principal,
    342  1.2  christos 				      delegated_proxy_principal,
    343  1.1     elric 				      client, server, krbtgt, &pac, &signed_pac);
    344  1.1     elric 		if (ret) {
    345  1.1     elric 		    krb5_pac_free(context, pac);
    346  1.1     elric 		    return ret;
    347  1.1     elric 		}
    348  1.1     elric 
    349  1.1     elric 		/*
    350  1.1     elric 		 * Only re-sign PAC if we could verify it with the PAC
    351  1.1     elric 		 * function. The no-verify case happens when we get in
    352  1.1     elric 		 * a PAC from cross realm from a Windows domain and
    353  1.1     elric 		 * that there is no PAC verification function.
    354  1.1     elric 		 */
    355  1.1     elric 		if (signed_pac) {
    356  1.1     elric 		    *signedpath = 1;
    357  1.1     elric 		    ret = _krb5_pac_sign(context, pac, tkt->authtime,
    358  1.1     elric 					 client_principal,
    359  1.2  christos 					 server_sign_key, krbtgt_sign_key, rspac);
    360  1.1     elric 		}
    361  1.1     elric 		krb5_pac_free(context, pac);
    362  1.2  christos 
    363  1.1     elric 		return ret;
    364  1.1     elric 	    }
    365  1.1     elric 	}
    366  1.1     elric 	free_AuthorizationData(&child);
    367  1.1     elric     }
    368  1.1     elric     return 0;
    369  1.1     elric }
    370  1.1     elric 
    371  1.3  christos static krb5_boolean
    372  1.3  christos is_anon_tgs_request_p(const KDC_REQ_BODY *b,
    373  1.3  christos 		      const EncTicketPart *tgt)
    374  1.3  christos {
    375  1.3  christos     KDCOptions f = b->kdc_options;
    376  1.3  christos 
    377  1.3  christos     /*
    378  1.3  christos      * Versions of Heimdal from 1.0 to 7.6, inclusive, send both the
    379  1.3  christos      * request-anonymous and cname-in-addl-tkt flags for constrained
    380  1.3  christos      * delegation requests. A true anonymous TGS request will only
    381  1.3  christos      * have the request-anonymous flag set. (A corollary of this is
    382  1.3  christos      * that it is not possible to support anonymous constrained
    383  1.3  christos      * delegation requests, although they would be of limited utility.)
    384  1.3  christos      */
    385  1.3  christos     return tgt->flags.anonymous ||
    386  1.3  christos 	(f.request_anonymous && !f.cname_in_addl_tkt && !b->additional_tickets);
    387  1.3  christos }
    388  1.3  christos 
    389  1.1     elric /*
    390  1.1     elric  *
    391  1.1     elric  */
    392  1.1     elric 
    393  1.1     elric static krb5_error_code
    394  1.1     elric check_tgs_flags(krb5_context context,
    395  1.1     elric 		krb5_kdc_configuration *config,
    396  1.3  christos 		KDC_REQ_BODY *b,
    397  1.3  christos 		krb5_const_principal tgt_name,
    398  1.3  christos 		const EncTicketPart *tgt,
    399  1.3  christos 		EncTicketPart *et)
    400  1.1     elric {
    401  1.1     elric     KDCOptions f = b->kdc_options;
    402  1.2  christos 
    403  1.1     elric     if(f.validate){
    404  1.1     elric 	if(!tgt->flags.invalid || tgt->starttime == NULL){
    405  1.1     elric 	    kdc_log(context, config, 0,
    406  1.1     elric 		    "Bad request to validate ticket");
    407  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    408  1.1     elric 	}
    409  1.1     elric 	if(*tgt->starttime > kdc_time){
    410  1.1     elric 	    kdc_log(context, config, 0,
    411  1.1     elric 		    "Early request to validate ticket");
    412  1.1     elric 	    return KRB5KRB_AP_ERR_TKT_NYV;
    413  1.1     elric 	}
    414  1.1     elric 	/* XXX  tkt = tgt */
    415  1.1     elric 	et->flags.invalid = 0;
    416  1.1     elric     }else if(tgt->flags.invalid){
    417  1.1     elric 	kdc_log(context, config, 0,
    418  1.1     elric 		"Ticket-granting ticket has INVALID flag set");
    419  1.1     elric 	return KRB5KRB_AP_ERR_TKT_INVALID;
    420  1.1     elric     }
    421  1.1     elric 
    422  1.1     elric     if(f.forwardable){
    423  1.1     elric 	if(!tgt->flags.forwardable){
    424  1.1     elric 	    kdc_log(context, config, 0,
    425  1.1     elric 		    "Bad request for forwardable ticket");
    426  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    427  1.1     elric 	}
    428  1.1     elric 	et->flags.forwardable = 1;
    429  1.1     elric     }
    430  1.1     elric     if(f.forwarded){
    431  1.1     elric 	if(!tgt->flags.forwardable){
    432  1.1     elric 	    kdc_log(context, config, 0,
    433  1.1     elric 		    "Request to forward non-forwardable ticket");
    434  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    435  1.1     elric 	}
    436  1.1     elric 	et->flags.forwarded = 1;
    437  1.1     elric 	et->caddr = b->addresses;
    438  1.1     elric     }
    439  1.1     elric     if(tgt->flags.forwarded)
    440  1.1     elric 	et->flags.forwarded = 1;
    441  1.2  christos 
    442  1.1     elric     if(f.proxiable){
    443  1.1     elric 	if(!tgt->flags.proxiable){
    444  1.1     elric 	    kdc_log(context, config, 0,
    445  1.1     elric 		    "Bad request for proxiable ticket");
    446  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    447  1.1     elric 	}
    448  1.1     elric 	et->flags.proxiable = 1;
    449  1.1     elric     }
    450  1.1     elric     if(f.proxy){
    451  1.1     elric 	if(!tgt->flags.proxiable){
    452  1.1     elric 	    kdc_log(context, config, 0,
    453  1.1     elric 		    "Request to proxy non-proxiable ticket");
    454  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    455  1.1     elric 	}
    456  1.1     elric 	et->flags.proxy = 1;
    457  1.1     elric 	et->caddr = b->addresses;
    458  1.1     elric     }
    459  1.1     elric     if(tgt->flags.proxy)
    460  1.1     elric 	et->flags.proxy = 1;
    461  1.1     elric 
    462  1.1     elric     if(f.allow_postdate){
    463  1.1     elric 	if(!tgt->flags.may_postdate){
    464  1.1     elric 	    kdc_log(context, config, 0,
    465  1.1     elric 		    "Bad request for post-datable ticket");
    466  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    467  1.1     elric 	}
    468  1.1     elric 	et->flags.may_postdate = 1;
    469  1.1     elric     }
    470  1.1     elric     if(f.postdated){
    471  1.1     elric 	if(!tgt->flags.may_postdate){
    472  1.1     elric 	    kdc_log(context, config, 0,
    473  1.1     elric 		    "Bad request for postdated ticket");
    474  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    475  1.1     elric 	}
    476  1.1     elric 	if(b->from)
    477  1.1     elric 	    *et->starttime = *b->from;
    478  1.1     elric 	et->flags.postdated = 1;
    479  1.1     elric 	et->flags.invalid = 1;
    480  1.1     elric     }else if(b->from && *b->from > kdc_time + context->max_skew){
    481  1.1     elric 	kdc_log(context, config, 0, "Ticket cannot be postdated");
    482  1.1     elric 	return KRB5KDC_ERR_CANNOT_POSTDATE;
    483  1.1     elric     }
    484  1.1     elric 
    485  1.1     elric     if(f.renewable){
    486  1.1     elric 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
    487  1.1     elric 	    kdc_log(context, config, 0,
    488  1.1     elric 		    "Bad request for renewable ticket");
    489  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    490  1.1     elric 	}
    491  1.1     elric 	et->flags.renewable = 1;
    492  1.1     elric 	ALLOC(et->renew_till);
    493  1.1     elric 	_kdc_fix_time(&b->rtime);
    494  1.1     elric 	*et->renew_till = *b->rtime;
    495  1.1     elric     }
    496  1.1     elric     if(f.renew){
    497  1.1     elric 	time_t old_life;
    498  1.1     elric 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
    499  1.1     elric 	    kdc_log(context, config, 0,
    500  1.1     elric 		    "Request to renew non-renewable ticket");
    501  1.1     elric 	    return KRB5KDC_ERR_BADOPTION;
    502  1.1     elric 	}
    503  1.1     elric 	old_life = tgt->endtime;
    504  1.1     elric 	if(tgt->starttime)
    505  1.1     elric 	    old_life -= *tgt->starttime;
    506  1.1     elric 	else
    507  1.1     elric 	    old_life -= tgt->authtime;
    508  1.1     elric 	et->endtime = *et->starttime + old_life;
    509  1.1     elric 	if (et->renew_till != NULL)
    510  1.1     elric 	    et->endtime = min(*et->renew_till, et->endtime);
    511  1.2  christos     }
    512  1.1     elric 
    513  1.3  christos     /*
    514  1.3  christos      * RFC 8062 section 3 defines an anonymous ticket as one containing
    515  1.3  christos      * the anonymous principal and the anonymous ticket flag.
    516  1.3  christos      */
    517  1.3  christos     if (tgt->flags.anonymous &&
    518  1.3  christos 	!_kdc_is_anonymous(context, tgt_name)) {
    519  1.1     elric 	kdc_log(context, config, 0,
    520  1.3  christos 		"Anonymous ticket flag set without anonymous principal");
    521  1.1     elric 	return KRB5KDC_ERR_BADOPTION;
    522  1.1     elric     }
    523  1.3  christos 
    524  1.3  christos     /*
    525  1.3  christos      * RFC 8062 section 4.2 states that if the TGT is anonymous, the
    526  1.3  christos      * anonymous KDC option SHOULD be set, but it is not required.
    527  1.3  christos      * Treat an anonymous TGT as if the anonymous flag was set.
    528  1.3  christos      */
    529  1.3  christos     if (is_anon_tgs_request_p(b, tgt))
    530  1.3  christos 	et->flags.anonymous = 1;
    531  1.3  christos 
    532  1.1     elric     return 0;
    533  1.1     elric }
    534  1.1     elric 
    535  1.1     elric /*
    536  1.1     elric  * Determine if constrained delegation is allowed from this client to this server
    537  1.1     elric  */
    538  1.1     elric 
    539  1.1     elric static krb5_error_code
    540  1.1     elric check_constrained_delegation(krb5_context context,
    541  1.1     elric 			     krb5_kdc_configuration *config,
    542  1.1     elric 			     HDB *clientdb,
    543  1.1     elric 			     hdb_entry_ex *client,
    544  1.2  christos 			     hdb_entry_ex *server,
    545  1.2  christos 			     krb5_const_principal target)
    546  1.1     elric {
    547  1.1     elric     const HDB_Ext_Constrained_delegation_acl *acl;
    548  1.1     elric     krb5_error_code ret;
    549  1.2  christos     size_t i;
    550  1.1     elric 
    551  1.2  christos     /*
    552  1.2  christos      * constrained_delegation (S4U2Proxy) only works within
    553  1.2  christos      * the same realm. We use the already canonicalized version
    554  1.2  christos      * of the principals here, while "target" is the principal
    555  1.2  christos      * provided by the client.
    556  1.2  christos      */
    557  1.2  christos     if(!krb5_realm_compare(context, client->entry.principal, server->entry.principal)) {
    558  1.2  christos 	ret = KRB5KDC_ERR_BADOPTION;
    559  1.2  christos 	kdc_log(context, config, 0,
    560  1.2  christos 	    "Bad request for constrained delegation");
    561  1.2  christos 	return ret;
    562  1.2  christos     }
    563  1.1     elric 
    564  1.1     elric     if (clientdb->hdb_check_constrained_delegation) {
    565  1.2  christos 	ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target);
    566  1.1     elric 	if (ret == 0)
    567  1.1     elric 	    return 0;
    568  1.1     elric     } else {
    569  1.2  christos 	/* if client delegates to itself, that ok */
    570  1.2  christos 	if (krb5_principal_compare(context, client->entry.principal, server->entry.principal) == TRUE)
    571  1.2  christos 	    return 0;
    572  1.2  christos 
    573  1.1     elric 	ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
    574  1.1     elric 	if (ret) {
    575  1.1     elric 	    krb5_clear_error_message(context);
    576  1.1     elric 	    return ret;
    577  1.1     elric 	}
    578  1.2  christos 
    579  1.1     elric 	if (acl) {
    580  1.1     elric 	    for (i = 0; i < acl->len; i++) {
    581  1.2  christos 		if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE)
    582  1.1     elric 		    return 0;
    583  1.1     elric 	    }
    584  1.1     elric 	}
    585  1.1     elric 	ret = KRB5KDC_ERR_BADOPTION;
    586  1.1     elric     }
    587  1.1     elric     kdc_log(context, config, 0,
    588  1.1     elric 	    "Bad request for constrained delegation");
    589  1.1     elric     return ret;
    590  1.1     elric }
    591  1.1     elric 
    592  1.1     elric /*
    593  1.1     elric  * Determine if s4u2self is allowed from this client to this server
    594  1.1     elric  *
    595  1.1     elric  * For example, regardless of the principal being impersonated, if the
    596  1.1     elric  * 'client' and 'server' are the same, then it's safe.
    597  1.1     elric  */
    598  1.1     elric 
    599  1.1     elric static krb5_error_code
    600  1.1     elric check_s4u2self(krb5_context context,
    601  1.1     elric 	       krb5_kdc_configuration *config,
    602  1.1     elric 	       HDB *clientdb,
    603  1.1     elric 	       hdb_entry_ex *client,
    604  1.1     elric 	       krb5_const_principal server)
    605  1.1     elric {
    606  1.1     elric     krb5_error_code ret;
    607  1.1     elric 
    608  1.1     elric     /* if client does a s4u2self to itself, that ok */
    609  1.1     elric     if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
    610  1.1     elric 	return 0;
    611  1.1     elric 
    612  1.1     elric     if (clientdb->hdb_check_s4u2self) {
    613  1.1     elric 	ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server);
    614  1.1     elric 	if (ret == 0)
    615  1.1     elric 	    return 0;
    616  1.1     elric     } else {
    617  1.1     elric 	ret = KRB5KDC_ERR_BADOPTION;
    618  1.1     elric     }
    619  1.1     elric     return ret;
    620  1.1     elric }
    621  1.1     elric 
    622  1.1     elric /*
    623  1.1     elric  *
    624  1.1     elric  */
    625  1.1     elric 
    626  1.1     elric static krb5_error_code
    627  1.1     elric verify_flags (krb5_context context,
    628  1.1     elric 	      krb5_kdc_configuration *config,
    629  1.1     elric 	      const EncTicketPart *et,
    630  1.1     elric 	      const char *pstr)
    631  1.1     elric {
    632  1.1     elric     if(et->endtime < kdc_time){
    633  1.1     elric 	kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
    634  1.1     elric 	return KRB5KRB_AP_ERR_TKT_EXPIRED;
    635  1.1     elric     }
    636  1.1     elric     if(et->flags.invalid){
    637  1.1     elric 	kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
    638  1.1     elric 	return KRB5KRB_AP_ERR_TKT_NYV;
    639  1.1     elric     }
    640  1.1     elric     return 0;
    641  1.1     elric }
    642  1.1     elric 
    643  1.1     elric /*
    644  1.1     elric  *
    645  1.1     elric  */
    646  1.1     elric 
    647  1.1     elric static krb5_error_code
    648  1.1     elric fix_transited_encoding(krb5_context context,
    649  1.1     elric 		       krb5_kdc_configuration *config,
    650  1.1     elric 		       krb5_boolean check_policy,
    651  1.1     elric 		       const TransitedEncoding *tr,
    652  1.1     elric 		       EncTicketPart *et,
    653  1.1     elric 		       const char *client_realm,
    654  1.1     elric 		       const char *server_realm,
    655  1.1     elric 		       const char *tgt_realm)
    656  1.1     elric {
    657  1.1     elric     krb5_error_code ret = 0;
    658  1.1     elric     char **realms, **tmp;
    659  1.1     elric     unsigned int num_realms;
    660  1.2  christos     size_t i;
    661  1.1     elric 
    662  1.1     elric     switch (tr->tr_type) {
    663  1.1     elric     case DOMAIN_X500_COMPRESS:
    664  1.1     elric 	break;
    665  1.1     elric     case 0:
    666  1.1     elric 	/*
    667  1.1     elric 	 * Allow empty content of type 0 because that is was Microsoft
    668  1.1     elric 	 * generates in their TGT.
    669  1.1     elric 	 */
    670  1.1     elric 	if (tr->contents.length == 0)
    671  1.1     elric 	    break;
    672  1.1     elric 	kdc_log(context, config, 0,
    673  1.1     elric 		"Transited type 0 with non empty content");
    674  1.1     elric 	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    675  1.1     elric     default:
    676  1.1     elric 	kdc_log(context, config, 0,
    677  1.1     elric 		"Unknown transited type: %u", tr->tr_type);
    678  1.1     elric 	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    679  1.1     elric     }
    680  1.1     elric 
    681  1.1     elric     ret = krb5_domain_x500_decode(context,
    682  1.1     elric 				  tr->contents,
    683  1.1     elric 				  &realms,
    684  1.1     elric 				  &num_realms,
    685  1.1     elric 				  client_realm,
    686  1.1     elric 				  server_realm);
    687  1.1     elric     if(ret){
    688  1.1     elric 	krb5_warn(context, ret,
    689  1.1     elric 		  "Decoding transited encoding");
    690  1.1     elric 	return ret;
    691  1.1     elric     }
    692  1.3  christos 
    693  1.3  christos     /*
    694  1.3  christos      * If the realm of the presented tgt is neither the client nor the server
    695  1.3  christos      * realm, it is a transit realm and must be added to transited set.
    696  1.3  christos      */
    697  1.1     elric     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
    698  1.1     elric 	if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
    699  1.1     elric 	    ret = ERANGE;
    700  1.1     elric 	    goto free_realms;
    701  1.1     elric 	}
    702  1.1     elric 	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
    703  1.1     elric 	if(tmp == NULL){
    704  1.1     elric 	    ret = ENOMEM;
    705  1.1     elric 	    goto free_realms;
    706  1.1     elric 	}
    707  1.1     elric 	realms = tmp;
    708  1.1     elric 	realms[num_realms] = strdup(tgt_realm);
    709  1.1     elric 	if(realms[num_realms] == NULL){
    710  1.1     elric 	    ret = ENOMEM;
    711  1.1     elric 	    goto free_realms;
    712  1.1     elric 	}
    713  1.1     elric 	num_realms++;
    714  1.1     elric     }
    715  1.1     elric     if(num_realms == 0) {
    716  1.1     elric 	if(strcmp(client_realm, server_realm))
    717  1.1     elric 	    kdc_log(context, config, 0,
    718  1.1     elric 		    "cross-realm %s -> %s", client_realm, server_realm);
    719  1.1     elric     } else {
    720  1.1     elric 	size_t l = 0;
    721  1.1     elric 	char *rs;
    722  1.1     elric 	for(i = 0; i < num_realms; i++)
    723  1.1     elric 	    l += strlen(realms[i]) + 2;
    724  1.1     elric 	rs = malloc(l);
    725  1.1     elric 	if(rs != NULL) {
    726  1.1     elric 	    *rs = '\0';
    727  1.1     elric 	    for(i = 0; i < num_realms; i++) {
    728  1.1     elric 		if(i > 0)
    729  1.1     elric 		    strlcat(rs, ", ", l);
    730  1.1     elric 		strlcat(rs, realms[i], l);
    731  1.1     elric 	    }
    732  1.1     elric 	    kdc_log(context, config, 0,
    733  1.1     elric 		    "cross-realm %s -> %s via [%s]",
    734  1.1     elric 		    client_realm, server_realm, rs);
    735  1.1     elric 	    free(rs);
    736  1.1     elric 	}
    737  1.1     elric     }
    738  1.1     elric     if(check_policy) {
    739  1.1     elric 	ret = krb5_check_transited(context, client_realm,
    740  1.1     elric 				   server_realm,
    741  1.1     elric 				   realms, num_realms, NULL);
    742  1.1     elric 	if(ret) {
    743  1.1     elric 	    krb5_warn(context, ret, "cross-realm %s -> %s",
    744  1.1     elric 		      client_realm, server_realm);
    745  1.1     elric 	    goto free_realms;
    746  1.1     elric 	}
    747  1.1     elric 	et->flags.transited_policy_checked = 1;
    748  1.1     elric     }
    749  1.1     elric     et->transited.tr_type = DOMAIN_X500_COMPRESS;
    750  1.1     elric     ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
    751  1.1     elric     if(ret)
    752  1.1     elric 	krb5_warn(context, ret, "Encoding transited encoding");
    753  1.1     elric   free_realms:
    754  1.1     elric     for(i = 0; i < num_realms; i++)
    755  1.1     elric 	free(realms[i]);
    756  1.1     elric     free(realms);
    757  1.1     elric     return ret;
    758  1.1     elric }
    759  1.1     elric 
    760  1.1     elric 
    761  1.1     elric static krb5_error_code
    762  1.1     elric tgs_make_reply(krb5_context context,
    763  1.1     elric 	       krb5_kdc_configuration *config,
    764  1.1     elric 	       KDC_REQ_BODY *b,
    765  1.1     elric 	       krb5_const_principal tgt_name,
    766  1.1     elric 	       const EncTicketPart *tgt,
    767  1.1     elric 	       const krb5_keyblock *replykey,
    768  1.1     elric 	       int rk_is_subkey,
    769  1.1     elric 	       const EncryptionKey *serverkey,
    770  1.1     elric 	       const krb5_keyblock *sessionkey,
    771  1.1     elric 	       krb5_kvno kvno,
    772  1.1     elric 	       AuthorizationData *auth_data,
    773  1.1     elric 	       hdb_entry_ex *server,
    774  1.1     elric 	       krb5_principal server_principal,
    775  1.1     elric 	       const char *server_name,
    776  1.1     elric 	       hdb_entry_ex *client,
    777  1.1     elric 	       krb5_principal client_principal,
    778  1.3  christos                const char *tgt_realm,
    779  1.1     elric 	       hdb_entry_ex *krbtgt,
    780  1.1     elric 	       krb5_enctype krbtgt_etype,
    781  1.1     elric 	       krb5_principals spp,
    782  1.1     elric 	       const krb5_data *rspac,
    783  1.1     elric 	       const METHOD_DATA *enc_pa_data,
    784  1.1     elric 	       const char **e_text,
    785  1.1     elric 	       krb5_data *reply)
    786  1.1     elric {
    787  1.1     elric     KDC_REP rep;
    788  1.1     elric     EncKDCRepPart ek;
    789  1.1     elric     EncTicketPart et;
    790  1.1     elric     KDCOptions f = b->kdc_options;
    791  1.1     elric     krb5_error_code ret;
    792  1.1     elric     int is_weak = 0;
    793  1.1     elric 
    794  1.1     elric     memset(&rep, 0, sizeof(rep));
    795  1.1     elric     memset(&et, 0, sizeof(et));
    796  1.1     elric     memset(&ek, 0, sizeof(ek));
    797  1.1     elric 
    798  1.1     elric     rep.pvno = 5;
    799  1.1     elric     rep.msg_type = krb_tgs_rep;
    800  1.1     elric 
    801  1.1     elric     et.authtime = tgt->authtime;
    802  1.1     elric     _kdc_fix_time(&b->till);
    803  1.1     elric     et.endtime = min(tgt->endtime, *b->till);
    804  1.1     elric     ALLOC(et.starttime);
    805  1.1     elric     *et.starttime = kdc_time;
    806  1.1     elric 
    807  1.3  christos     ret = check_tgs_flags(context, config, b, tgt_name, tgt, &et);
    808  1.1     elric     if(ret)
    809  1.1     elric 	goto out;
    810  1.1     elric 
    811  1.1     elric     /* We should check the transited encoding if:
    812  1.1     elric        1) the request doesn't ask not to be checked
    813  1.1     elric        2) globally enforcing a check
    814  1.1     elric        3) principal requires checking
    815  1.1     elric        4) we allow non-check per-principal, but principal isn't marked as allowing this
    816  1.1     elric        5) we don't globally allow this
    817  1.1     elric     */
    818  1.1     elric 
    819  1.1     elric #define GLOBAL_FORCE_TRANSITED_CHECK		\
    820  1.1     elric     (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
    821  1.1     elric #define GLOBAL_ALLOW_PER_PRINCIPAL			\
    822  1.1     elric     (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
    823  1.1     elric #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK			\
    824  1.1     elric     (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
    825  1.1     elric 
    826  1.1     elric /* these will consult the database in future release */
    827  1.1     elric #define PRINCIPAL_FORCE_TRANSITED_CHECK(P)		0
    828  1.1     elric #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)	0
    829  1.1     elric 
    830  1.1     elric     ret = fix_transited_encoding(context, config,
    831  1.1     elric 				 !f.disable_transited_check ||
    832  1.1     elric 				 GLOBAL_FORCE_TRANSITED_CHECK ||
    833  1.1     elric 				 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
    834  1.1     elric 				 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
    835  1.1     elric 				    PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
    836  1.1     elric 				   GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
    837  1.1     elric 				 &tgt->transited, &et,
    838  1.1     elric 				 krb5_principal_get_realm(context, client_principal),
    839  1.1     elric 				 krb5_principal_get_realm(context, server->entry.principal),
    840  1.3  christos 				 tgt_realm);
    841  1.1     elric     if(ret)
    842  1.1     elric 	goto out;
    843  1.1     elric 
    844  1.3  christos     ret = copy_Realm(&server_principal->realm, &rep.ticket.realm);
    845  1.3  christos     if (ret)
    846  1.3  christos 	goto out;
    847  1.1     elric     _krb5_principal2principalname(&rep.ticket.sname, server_principal);
    848  1.3  christos     ret = copy_Realm(&tgt_name->realm, &rep.crealm);
    849  1.3  christos     if (ret)
    850  1.3  christos 	goto out;
    851  1.1     elric 
    852  1.3  christos     /*
    853  1.3  christos      * RFC 8062 states "if the ticket in the TGS request is an anonymous
    854  1.3  christos      * one, the client and client realm are copied from that ticket". So
    855  1.3  christos      * whilst the TGT flag check below is superfluous, it is included in
    856  1.3  christos      * order to follow the specification to its letter.
    857  1.3  christos      */
    858  1.3  christos     if (et.flags.anonymous && !tgt->flags.anonymous)
    859  1.3  christos 	_kdc_make_anonymous_principalname(&rep.cname);
    860  1.3  christos     else
    861  1.3  christos 	ret = copy_PrincipalName(&tgt_name->name, &rep.cname);
    862  1.3  christos     if (ret)
    863  1.3  christos 	goto out;
    864  1.1     elric     rep.ticket.tkt_vno = 5;
    865  1.1     elric 
    866  1.1     elric     ek.caddr = et.caddr;
    867  1.1     elric 
    868  1.1     elric     {
    869  1.1     elric 	time_t life;
    870  1.1     elric 	life = et.endtime - *et.starttime;
    871  1.1     elric 	if(client && client->entry.max_life)
    872  1.1     elric 	    life = min(life, *client->entry.max_life);
    873  1.1     elric 	if(server->entry.max_life)
    874  1.1     elric 	    life = min(life, *server->entry.max_life);
    875  1.1     elric 	et.endtime = *et.starttime + life;
    876  1.1     elric     }
    877  1.1     elric     if(f.renewable_ok && tgt->flags.renewable &&
    878  1.1     elric        et.renew_till == NULL && et.endtime < *b->till &&
    879  1.1     elric        tgt->renew_till != NULL)
    880  1.1     elric     {
    881  1.1     elric 	et.flags.renewable = 1;
    882  1.1     elric 	ALLOC(et.renew_till);
    883  1.1     elric 	*et.renew_till = *b->till;
    884  1.1     elric     }
    885  1.1     elric     if(et.renew_till){
    886  1.1     elric 	time_t renew;
    887  1.2  christos 	renew = *et.renew_till - *et.starttime;
    888  1.1     elric 	if(client && client->entry.max_renew)
    889  1.1     elric 	    renew = min(renew, *client->entry.max_renew);
    890  1.1     elric 	if(server->entry.max_renew)
    891  1.1     elric 	    renew = min(renew, *server->entry.max_renew);
    892  1.2  christos 	*et.renew_till = *et.starttime + renew;
    893  1.1     elric     }
    894  1.2  christos 
    895  1.1     elric     if(et.renew_till){
    896  1.1     elric 	*et.renew_till = min(*et.renew_till, *tgt->renew_till);
    897  1.1     elric 	*et.starttime = min(*et.starttime, *et.renew_till);
    898  1.1     elric 	et.endtime = min(et.endtime, *et.renew_till);
    899  1.1     elric     }
    900  1.1     elric 
    901  1.1     elric     *et.starttime = min(*et.starttime, et.endtime);
    902  1.1     elric 
    903  1.1     elric     if(*et.starttime == et.endtime){
    904  1.1     elric 	ret = KRB5KDC_ERR_NEVER_VALID;
    905  1.1     elric 	goto out;
    906  1.1     elric     }
    907  1.1     elric     if(et.renew_till && et.endtime == *et.renew_till){
    908  1.1     elric 	free(et.renew_till);
    909  1.1     elric 	et.renew_till = NULL;
    910  1.1     elric 	et.flags.renewable = 0;
    911  1.1     elric     }
    912  1.1     elric 
    913  1.1     elric     et.flags.pre_authent = tgt->flags.pre_authent;
    914  1.1     elric     et.flags.hw_authent  = tgt->flags.hw_authent;
    915  1.1     elric     et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
    916  1.1     elric 
    917  1.3  christos     /*
    918  1.3  christos      * For anonymous tickets, we should filter out positive authorization data
    919  1.3  christos      * that could reveal the client's identity, and return a policy error for
    920  1.3  christos      * restrictive authorization data. Policy for unknown authorization types
    921  1.3  christos      * is implementation dependent.
    922  1.3  christos      */
    923  1.3  christos     if (rspac->length && !et.flags.anonymous) {
    924  1.1     elric 	/*
    925  1.1     elric 	 * No not need to filter out the any PAC from the
    926  1.1     elric 	 * auth_data since it's signed by the KDC.
    927  1.1     elric 	 */
    928  1.1     elric 	ret = _kdc_tkt_add_if_relevant_ad(context, &et,
    929  1.1     elric 					  KRB5_AUTHDATA_WIN2K_PAC, rspac);
    930  1.1     elric 	if (ret)
    931  1.1     elric 	    goto out;
    932  1.1     elric     }
    933  1.2  christos 
    934  1.1     elric     if (auth_data) {
    935  1.1     elric 	unsigned int i = 0;
    936  1.1     elric 
    937  1.1     elric 	/* XXX check authdata */
    938  1.1     elric 
    939  1.1     elric 	if (et.authorization_data == NULL) {
    940  1.1     elric 	    et.authorization_data = calloc(1, sizeof(*et.authorization_data));
    941  1.1     elric 	    if (et.authorization_data == NULL) {
    942  1.1     elric 		ret = ENOMEM;
    943  1.1     elric 		krb5_set_error_message(context, ret, "malloc: out of memory");
    944  1.1     elric 		goto out;
    945  1.1     elric 	    }
    946  1.1     elric 	}
    947  1.1     elric 	for(i = 0; i < auth_data->len ; i++) {
    948  1.1     elric 	    ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
    949  1.1     elric 	    if (ret) {
    950  1.1     elric 		krb5_set_error_message(context, ret, "malloc: out of memory");
    951  1.1     elric 		goto out;
    952  1.1     elric 	    }
    953  1.1     elric 	}
    954  1.1     elric 
    955  1.1     elric 	/* Filter out type KRB5SignedPath */
    956  1.1     elric 	ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
    957  1.1     elric 	if (ret == 0) {
    958  1.1     elric 	    if (et.authorization_data->len == 1) {
    959  1.1     elric 		free_AuthorizationData(et.authorization_data);
    960  1.1     elric 		free(et.authorization_data);
    961  1.1     elric 		et.authorization_data = NULL;
    962  1.1     elric 	    } else {
    963  1.1     elric 		AuthorizationData *ad = et.authorization_data;
    964  1.1     elric 		free_AuthorizationDataElement(&ad->val[ad->len - 1]);
    965  1.1     elric 		ad->len--;
    966  1.1     elric 	    }
    967  1.1     elric 	}
    968  1.1     elric     }
    969  1.1     elric 
    970  1.1     elric     ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
    971  1.1     elric     if (ret)
    972  1.1     elric 	goto out;
    973  1.3  christos     et.crealm = rep.crealm;
    974  1.3  christos     et.cname = rep.cname;
    975  1.2  christos 
    976  1.1     elric     ek.key = et.key;
    977  1.1     elric     /* MIT must have at least one last_req */
    978  1.1     elric     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
    979  1.1     elric     if (ek.last_req.val == NULL) {
    980  1.1     elric 	ret = ENOMEM;
    981  1.1     elric 	goto out;
    982  1.1     elric     }
    983  1.2  christos     ek.last_req.len = 1; /* set after alloc to avoid null deref on cleanup */
    984  1.1     elric     ek.nonce = b->nonce;
    985  1.1     elric     ek.flags = et.flags;
    986  1.1     elric     ek.authtime = et.authtime;
    987  1.1     elric     ek.starttime = et.starttime;
    988  1.1     elric     ek.endtime = et.endtime;
    989  1.1     elric     ek.renew_till = et.renew_till;
    990  1.1     elric     ek.srealm = rep.ticket.realm;
    991  1.1     elric     ek.sname = rep.ticket.sname;
    992  1.1     elric 
    993  1.1     elric     _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
    994  1.1     elric 		       et.endtime, et.renew_till);
    995  1.1     elric 
    996  1.1     elric     /* Don't sign cross realm tickets, they can't be checked anyway */
    997  1.1     elric     {
    998  1.1     elric 	char *r = get_krbtgt_realm(&ek.sname);
    999  1.1     elric 
   1000  1.1     elric 	if (r == NULL || strcmp(r, ek.srealm) == 0) {
   1001  1.1     elric 	    ret = _kdc_add_KRB5SignedPath(context,
   1002  1.1     elric 					  config,
   1003  1.1     elric 					  krbtgt,
   1004  1.1     elric 					  krbtgt_etype,
   1005  1.1     elric 					  client_principal,
   1006  1.1     elric 					  NULL,
   1007  1.1     elric 					  spp,
   1008  1.1     elric 					  &et);
   1009  1.1     elric 	    if (ret)
   1010  1.1     elric 		goto out;
   1011  1.1     elric 	}
   1012  1.1     elric     }
   1013  1.1     elric 
   1014  1.1     elric     if (enc_pa_data->len) {
   1015  1.1     elric 	rep.padata = calloc(1, sizeof(*rep.padata));
   1016  1.1     elric 	if (rep.padata == NULL) {
   1017  1.1     elric 	    ret = ENOMEM;
   1018  1.1     elric 	    goto out;
   1019  1.1     elric 	}
   1020  1.1     elric 	ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
   1021  1.1     elric 	if (ret)
   1022  1.1     elric 	    goto out;
   1023  1.1     elric     }
   1024  1.1     elric 
   1025  1.2  christos     if (krb5_enctype_valid(context, serverkey->keytype) != 0
   1026  1.2  christos 	&& _kdc_is_weak_exception(server->entry.principal, serverkey->keytype))
   1027  1.1     elric     {
   1028  1.2  christos 	krb5_enctype_enable(context, serverkey->keytype);
   1029  1.1     elric 	is_weak = 1;
   1030  1.1     elric     }
   1031  1.1     elric 
   1032  1.1     elric 
   1033  1.1     elric     /* It is somewhat unclear where the etype in the following
   1034  1.1     elric        encryption should come from. What we have is a session
   1035  1.1     elric        key in the passed tgt, and a list of preferred etypes
   1036  1.1     elric        *for the new ticket*. Should we pick the best possible
   1037  1.1     elric        etype, given the keytype in the tgt, or should we look
   1038  1.1     elric        at the etype list here as well?  What if the tgt
   1039  1.1     elric        session key is DES3 and we want a ticket with a (say)
   1040  1.1     elric        CAST session key. Should the DES3 etype be added to the
   1041  1.1     elric        etype list, even if we don't want a session key with
   1042  1.1     elric        DES3? */
   1043  1.2  christos     ret = _kdc_encode_reply(context, config, NULL, 0,
   1044  1.2  christos 			    &rep, &et, &ek, serverkey->keytype,
   1045  1.1     elric 			    kvno,
   1046  1.1     elric 			    serverkey, 0, replykey, rk_is_subkey,
   1047  1.1     elric 			    e_text, reply);
   1048  1.1     elric     if (is_weak)
   1049  1.2  christos 	krb5_enctype_disable(context, serverkey->keytype);
   1050  1.1     elric 
   1051  1.1     elric out:
   1052  1.1     elric     free_TGS_REP(&rep);
   1053  1.1     elric     free_TransitedEncoding(&et.transited);
   1054  1.1     elric     if(et.starttime)
   1055  1.1     elric 	free(et.starttime);
   1056  1.1     elric     if(et.renew_till)
   1057  1.1     elric 	free(et.renew_till);
   1058  1.1     elric     if(et.authorization_data) {
   1059  1.1     elric 	free_AuthorizationData(et.authorization_data);
   1060  1.1     elric 	free(et.authorization_data);
   1061  1.1     elric     }
   1062  1.1     elric     free_LastReq(&ek.last_req);
   1063  1.1     elric     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
   1064  1.1     elric     free_EncryptionKey(&et.key);
   1065  1.1     elric     return ret;
   1066  1.1     elric }
   1067  1.1     elric 
   1068  1.1     elric static krb5_error_code
   1069  1.1     elric tgs_check_authenticator(krb5_context context,
   1070  1.1     elric 			krb5_kdc_configuration *config,
   1071  1.1     elric 	                krb5_auth_context ac,
   1072  1.1     elric 			KDC_REQ_BODY *b,
   1073  1.1     elric 			const char **e_text,
   1074  1.1     elric 			krb5_keyblock *key)
   1075  1.1     elric {
   1076  1.1     elric     krb5_authenticator auth;
   1077  1.2  christos     size_t len = 0;
   1078  1.1     elric     unsigned char *buf;
   1079  1.1     elric     size_t buf_size;
   1080  1.1     elric     krb5_error_code ret;
   1081  1.1     elric     krb5_crypto crypto;
   1082  1.1     elric 
   1083  1.1     elric     krb5_auth_con_getauthenticator(context, ac, &auth);
   1084  1.1     elric     if(auth->cksum == NULL){
   1085  1.1     elric 	kdc_log(context, config, 0, "No authenticator in request");
   1086  1.1     elric 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
   1087  1.1     elric 	goto out;
   1088  1.1     elric     }
   1089  1.1     elric     /*
   1090  1.1     elric      * according to RFC1510 it doesn't need to be keyed,
   1091  1.1     elric      * but according to the latest draft it needs to.
   1092  1.1     elric      */
   1093  1.1     elric     if (
   1094  1.1     elric #if 0
   1095  1.1     elric !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
   1096  1.1     elric 	||
   1097  1.1     elric #endif
   1098  1.1     elric  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
   1099  1.1     elric 	kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
   1100  1.1     elric 		auth->cksum->cksumtype);
   1101  1.1     elric 	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
   1102  1.1     elric 	goto out;
   1103  1.1     elric     }
   1104  1.2  christos 
   1105  1.1     elric     /* XXX should not re-encode this */
   1106  1.1     elric     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
   1107  1.1     elric     if(ret){
   1108  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1109  1.1     elric 	kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
   1110  1.1     elric 	krb5_free_error_message(context, msg);
   1111  1.1     elric 	goto out;
   1112  1.1     elric     }
   1113  1.1     elric     if(buf_size != len) {
   1114  1.1     elric 	free(buf);
   1115  1.1     elric 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
   1116  1.1     elric 	*e_text = "KDC internal error";
   1117  1.1     elric 	ret = KRB5KRB_ERR_GENERIC;
   1118  1.1     elric 	goto out;
   1119  1.1     elric     }
   1120  1.1     elric     ret = krb5_crypto_init(context, key, 0, &crypto);
   1121  1.1     elric     if (ret) {
   1122  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1123  1.1     elric 	free(buf);
   1124  1.1     elric 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   1125  1.1     elric 	krb5_free_error_message(context, msg);
   1126  1.1     elric 	goto out;
   1127  1.1     elric     }
   1128  1.1     elric     ret = krb5_verify_checksum(context,
   1129  1.1     elric 			       crypto,
   1130  1.1     elric 			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
   1131  1.1     elric 			       buf,
   1132  1.1     elric 			       len,
   1133  1.1     elric 			       auth->cksum);
   1134  1.1     elric     free(buf);
   1135  1.1     elric     krb5_crypto_destroy(context, crypto);
   1136  1.1     elric     if(ret){
   1137  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1138  1.1     elric 	kdc_log(context, config, 0,
   1139  1.1     elric 		"Failed to verify authenticator checksum: %s", msg);
   1140  1.1     elric 	krb5_free_error_message(context, msg);
   1141  1.1     elric     }
   1142  1.1     elric out:
   1143  1.1     elric     free_Authenticator(auth);
   1144  1.1     elric     free(auth);
   1145  1.1     elric     return ret;
   1146  1.1     elric }
   1147  1.1     elric 
   1148  1.1     elric static krb5_boolean
   1149  1.1     elric need_referral(krb5_context context, krb5_kdc_configuration *config,
   1150  1.1     elric 	      const KDCOptions * const options, krb5_principal server,
   1151  1.1     elric 	      krb5_realm **realms)
   1152  1.1     elric {
   1153  1.1     elric     const char *name;
   1154  1.1     elric 
   1155  1.1     elric     if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
   1156  1.1     elric 	return FALSE;
   1157  1.1     elric 
   1158  1.1     elric     if (server->name.name_string.len == 1)
   1159  1.1     elric 	name = server->name.name_string.val[0];
   1160  1.2  christos     else if (server->name.name_string.len == 3) {
   1161  1.2  christos 	/*
   1162  1.2  christos 	  This is used to give referrals for the
   1163  1.2  christos 	  E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
   1164  1.2  christos 	  SPN form, which is used for inter-domain communication in AD
   1165  1.2  christos 	 */
   1166  1.2  christos 	name = server->name.name_string.val[2];
   1167  1.2  christos 	kdc_log(context, config, 0, "Giving 3 part referral for %s", name);
   1168  1.2  christos 	*realms = malloc(sizeof(char *)*2);
   1169  1.2  christos 	if (*realms == NULL) {
   1170  1.2  christos 	    krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
   1171  1.2  christos 	    return FALSE;
   1172  1.2  christos 	}
   1173  1.2  christos 	(*realms)[0] = strdup(name);
   1174  1.2  christos 	(*realms)[1] = NULL;
   1175  1.2  christos 	return TRUE;
   1176  1.2  christos     } else if (server->name.name_string.len > 1)
   1177  1.1     elric 	name = server->name.name_string.val[1];
   1178  1.1     elric     else
   1179  1.1     elric 	return FALSE;
   1180  1.1     elric 
   1181  1.1     elric     kdc_log(context, config, 0, "Searching referral for %s", name);
   1182  1.1     elric 
   1183  1.1     elric     return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
   1184  1.1     elric }
   1185  1.1     elric 
   1186  1.1     elric static krb5_error_code
   1187  1.1     elric tgs_parse_request(krb5_context context,
   1188  1.1     elric 		  krb5_kdc_configuration *config,
   1189  1.1     elric 		  KDC_REQ_BODY *b,
   1190  1.1     elric 		  const PA_DATA *tgs_req,
   1191  1.1     elric 		  hdb_entry_ex **krbtgt,
   1192  1.1     elric 		  krb5_enctype *krbtgt_etype,
   1193  1.1     elric 		  krb5_ticket **ticket,
   1194  1.1     elric 		  const char **e_text,
   1195  1.1     elric 		  const char *from,
   1196  1.1     elric 		  const struct sockaddr *from_addr,
   1197  1.1     elric 		  time_t **csec,
   1198  1.1     elric 		  int **cusec,
   1199  1.1     elric 		  AuthorizationData **auth_data,
   1200  1.1     elric 		  krb5_keyblock **replykey,
   1201  1.1     elric 		  int *rk_is_subkey)
   1202  1.1     elric {
   1203  1.2  christos     static char failed[] = "<unparse_name failed>";
   1204  1.1     elric     krb5_ap_req ap_req;
   1205  1.1     elric     krb5_error_code ret;
   1206  1.1     elric     krb5_principal princ;
   1207  1.1     elric     krb5_auth_context ac = NULL;
   1208  1.1     elric     krb5_flags ap_req_options;
   1209  1.1     elric     krb5_flags verify_ap_req_flags;
   1210  1.1     elric     krb5_crypto crypto;
   1211  1.2  christos     krb5uint32 krbtgt_kvno;     /* kvno used for the PA-TGS-REQ AP-REQ Ticket */
   1212  1.2  christos     krb5uint32 krbtgt_kvno_try;
   1213  1.2  christos     int kvno_search_tries = 4;  /* number of kvnos to try when tkt_vno == 0 */
   1214  1.2  christos     const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */
   1215  1.1     elric     Key *tkey;
   1216  1.1     elric     krb5_keyblock *subkey = NULL;
   1217  1.1     elric     unsigned usage;
   1218  1.1     elric 
   1219  1.1     elric     *auth_data = NULL;
   1220  1.1     elric     *csec  = NULL;
   1221  1.1     elric     *cusec = NULL;
   1222  1.1     elric     *replykey = NULL;
   1223  1.1     elric 
   1224  1.1     elric     memset(&ap_req, 0, sizeof(ap_req));
   1225  1.1     elric     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
   1226  1.1     elric     if(ret){
   1227  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1228  1.1     elric 	kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
   1229  1.1     elric 	krb5_free_error_message(context, msg);
   1230  1.1     elric 	goto out;
   1231  1.1     elric     }
   1232  1.1     elric 
   1233  1.1     elric     if(!get_krbtgt_realm(&ap_req.ticket.sname)){
   1234  1.1     elric 	/* XXX check for ticket.sname == req.sname */
   1235  1.1     elric 	kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
   1236  1.1     elric 	ret = KRB5KDC_ERR_POLICY; /* ? */
   1237  1.1     elric 	goto out;
   1238  1.1     elric     }
   1239  1.1     elric 
   1240  1.1     elric     _krb5_principalname2krb5_principal(context,
   1241  1.1     elric 				       &princ,
   1242  1.1     elric 				       ap_req.ticket.sname,
   1243  1.1     elric 				       ap_req.ticket.realm);
   1244  1.1     elric 
   1245  1.2  christos     krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0;
   1246  1.2  christos     ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT,
   1247  1.2  christos 			&krbtgt_kvno, NULL, krbtgt);
   1248  1.1     elric 
   1249  1.2  christos     if (ret == HDB_ERR_NOT_FOUND_HERE) {
   1250  1.2  christos 	/* XXX Factor out this unparsing of the same princ all over */
   1251  1.1     elric 	char *p;
   1252  1.1     elric 	ret = krb5_unparse_name(context, princ, &p);
   1253  1.1     elric 	if (ret != 0)
   1254  1.2  christos 	    p = failed;
   1255  1.1     elric 	krb5_free_principal(context, princ);
   1256  1.2  christos 	kdc_log(context, config, 5,
   1257  1.2  christos 		"Ticket-granting ticket account %s does not have secrets at "
   1258  1.2  christos 		"this KDC, need to proxy", p);
   1259  1.1     elric 	if (ret == 0)
   1260  1.1     elric 	    free(p);
   1261  1.1     elric 	ret = HDB_ERR_NOT_FOUND_HERE;
   1262  1.1     elric 	goto out;
   1263  1.2  christos     } else if (ret == HDB_ERR_KVNO_NOT_FOUND) {
   1264  1.1     elric 	char *p;
   1265  1.1     elric 	ret = krb5_unparse_name(context, princ, &p);
   1266  1.1     elric 	if (ret != 0)
   1267  1.2  christos 	    p = failed;
   1268  1.1     elric 	krb5_free_principal(context, princ);
   1269  1.2  christos 	kdc_log(context, config, 5,
   1270  1.2  christos 		"Ticket-granting ticket account %s does not have keys for "
   1271  1.2  christos 		"kvno %d at this KDC", p, krbtgt_kvno);
   1272  1.1     elric 	if (ret == 0)
   1273  1.1     elric 	    free(p);
   1274  1.2  christos 	ret = HDB_ERR_KVNO_NOT_FOUND;
   1275  1.1     elric 	goto out;
   1276  1.2  christos     } else if (ret == HDB_ERR_NO_MKEY) {
   1277  1.1     elric 	char *p;
   1278  1.2  christos 	ret = krb5_unparse_name(context, princ, &p);
   1279  1.2  christos 	if (ret != 0)
   1280  1.2  christos 	    p = failed;
   1281  1.1     elric 	krb5_free_principal(context, princ);
   1282  1.2  christos 	kdc_log(context, config, 5,
   1283  1.2  christos 		"Missing master key for decrypting keys for ticket-granting "
   1284  1.2  christos 		"ticket account %s with kvno %d at this KDC", p, krbtgt_kvno);
   1285  1.2  christos 	if (ret == 0)
   1286  1.2  christos 	    free(p);
   1287  1.2  christos 	ret = HDB_ERR_KVNO_NOT_FOUND;
   1288  1.2  christos 	goto out;
   1289  1.2  christos     } else if (ret) {
   1290  1.2  christos 	const char *msg = krb5_get_error_message(context, ret);
   1291  1.2  christos 	char *p;
   1292  1.2  christos 	ret = krb5_unparse_name(context, princ, &p);
   1293  1.1     elric 	if (ret != 0)
   1294  1.2  christos 	    p = failed;
   1295  1.2  christos 	krb5_free_principal(context, princ);
   1296  1.1     elric 	kdc_log(context, config, 0,
   1297  1.2  christos 		"Ticket-granting ticket not found in database: %s", msg);
   1298  1.2  christos 	krb5_free_error_message(context, msg);
   1299  1.1     elric 	if (ret == 0)
   1300  1.2  christos 	    free(p);
   1301  1.2  christos 	ret = KRB5KRB_AP_ERR_NOT_US;
   1302  1.1     elric 	goto out;
   1303  1.1     elric     }
   1304  1.1     elric 
   1305  1.2  christos     krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : (*krbtgt)->entry.kvno;
   1306  1.1     elric     *krbtgt_etype = ap_req.ticket.enc_part.etype;
   1307  1.1     elric 
   1308  1.2  christos next_kvno:
   1309  1.2  christos     krbtgt_keys = hdb_kvno2keys(context, &(*krbtgt)->entry, krbtgt_kvno_try);
   1310  1.2  christos     ret = hdb_enctype2key(context, &(*krbtgt)->entry, krbtgt_keys,
   1311  1.1     elric 			  ap_req.ticket.enc_part.etype, &tkey);
   1312  1.2  christos     if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) {
   1313  1.2  christos 	kvno_search_tries--;
   1314  1.2  christos 	krbtgt_kvno_try--;
   1315  1.2  christos 	goto next_kvno;
   1316  1.2  christos     } else if (ret) {
   1317  1.1     elric 	char *str = NULL, *p = NULL;
   1318  1.1     elric 
   1319  1.1     elric 	krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
   1320  1.1     elric 	krb5_unparse_name(context, princ, &p);
   1321  1.1     elric  	kdc_log(context, config, 0,
   1322  1.1     elric 		"No server key with enctype %s found for %s",
   1323  1.1     elric 		str ? str : "<unknown enctype>",
   1324  1.1     elric 		p ? p : "<unparse_name failed>");
   1325  1.1     elric 	free(str);
   1326  1.1     elric 	free(p);
   1327  1.1     elric 	ret = KRB5KRB_AP_ERR_BADKEYVER;
   1328  1.1     elric 	goto out;
   1329  1.1     elric     }
   1330  1.1     elric 
   1331  1.1     elric     if (b->kdc_options.validate)
   1332  1.1     elric 	verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
   1333  1.1     elric     else
   1334  1.1     elric 	verify_ap_req_flags = 0;
   1335  1.1     elric 
   1336  1.1     elric     ret = krb5_verify_ap_req2(context,
   1337  1.1     elric 			      &ac,
   1338  1.1     elric 			      &ap_req,
   1339  1.1     elric 			      princ,
   1340  1.1     elric 			      &tkey->key,
   1341  1.1     elric 			      verify_ap_req_flags,
   1342  1.1     elric 			      &ap_req_options,
   1343  1.1     elric 			      ticket,
   1344  1.1     elric 			      KRB5_KU_TGS_REQ_AUTH);
   1345  1.2  christos     if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) {
   1346  1.2  christos 	kvno_search_tries--;
   1347  1.2  christos 	krbtgt_kvno_try--;
   1348  1.2  christos 	goto next_kvno;
   1349  1.2  christos     }
   1350  1.2  christos 
   1351  1.1     elric     krb5_free_principal(context, princ);
   1352  1.1     elric     if(ret) {
   1353  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1354  1.1     elric 	kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
   1355  1.1     elric 	krb5_free_error_message(context, msg);
   1356  1.1     elric 	goto out;
   1357  1.1     elric     }
   1358  1.1     elric 
   1359  1.1     elric     {
   1360  1.1     elric 	krb5_authenticator auth;
   1361  1.1     elric 
   1362  1.1     elric 	ret = krb5_auth_con_getauthenticator(context, ac, &auth);
   1363  1.1     elric 	if (ret == 0) {
   1364  1.1     elric 	    *csec   = malloc(sizeof(**csec));
   1365  1.1     elric 	    if (*csec == NULL) {
   1366  1.1     elric 		krb5_free_authenticator(context, &auth);
   1367  1.1     elric 		kdc_log(context, config, 0, "malloc failed");
   1368  1.1     elric 		goto out;
   1369  1.1     elric 	    }
   1370  1.1     elric 	    **csec  = auth->ctime;
   1371  1.1     elric 	    *cusec  = malloc(sizeof(**cusec));
   1372  1.1     elric 	    if (*cusec == NULL) {
   1373  1.1     elric 		krb5_free_authenticator(context, &auth);
   1374  1.1     elric 		kdc_log(context, config, 0, "malloc failed");
   1375  1.1     elric 		goto out;
   1376  1.1     elric 	    }
   1377  1.1     elric 	    **cusec  = auth->cusec;
   1378  1.1     elric 	    krb5_free_authenticator(context, &auth);
   1379  1.1     elric 	}
   1380  1.1     elric     }
   1381  1.1     elric 
   1382  1.1     elric     ret = tgs_check_authenticator(context, config,
   1383  1.1     elric 				  ac, b, e_text, &(*ticket)->ticket.key);
   1384  1.1     elric     if (ret) {
   1385  1.1     elric 	krb5_auth_con_free(context, ac);
   1386  1.1     elric 	goto out;
   1387  1.1     elric     }
   1388  1.1     elric 
   1389  1.1     elric     usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
   1390  1.1     elric     *rk_is_subkey = 1;
   1391  1.1     elric 
   1392  1.1     elric     ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
   1393  1.1     elric     if(ret){
   1394  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1395  1.1     elric 	krb5_auth_con_free(context, ac);
   1396  1.1     elric 	kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
   1397  1.1     elric 	krb5_free_error_message(context, msg);
   1398  1.1     elric 	goto out;
   1399  1.1     elric     }
   1400  1.1     elric     if(subkey == NULL){
   1401  1.1     elric 	usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
   1402  1.1     elric 	*rk_is_subkey = 0;
   1403  1.1     elric 
   1404  1.1     elric 	ret = krb5_auth_con_getkey(context, ac, &subkey);
   1405  1.1     elric 	if(ret) {
   1406  1.1     elric 	    const char *msg = krb5_get_error_message(context, ret);
   1407  1.1     elric 	    krb5_auth_con_free(context, ac);
   1408  1.1     elric 	    kdc_log(context, config, 0, "Failed to get session key: %s", msg);
   1409  1.1     elric 	    krb5_free_error_message(context, msg);
   1410  1.1     elric 	    goto out;
   1411  1.1     elric 	}
   1412  1.1     elric     }
   1413  1.1     elric     if(subkey == NULL){
   1414  1.1     elric 	krb5_auth_con_free(context, ac);
   1415  1.1     elric 	kdc_log(context, config, 0,
   1416  1.1     elric 		"Failed to get key for enc-authorization-data");
   1417  1.1     elric 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1418  1.1     elric 	goto out;
   1419  1.1     elric     }
   1420  1.1     elric 
   1421  1.1     elric     *replykey = subkey;
   1422  1.1     elric 
   1423  1.1     elric     if (b->enc_authorization_data) {
   1424  1.1     elric 	krb5_data ad;
   1425  1.1     elric 
   1426  1.1     elric 	ret = krb5_crypto_init(context, subkey, 0, &crypto);
   1427  1.1     elric 	if (ret) {
   1428  1.1     elric 	    const char *msg = krb5_get_error_message(context, ret);
   1429  1.1     elric 	    krb5_auth_con_free(context, ac);
   1430  1.1     elric 	    kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   1431  1.1     elric 	    krb5_free_error_message(context, msg);
   1432  1.1     elric 	    goto out;
   1433  1.1     elric 	}
   1434  1.1     elric 	ret = krb5_decrypt_EncryptedData (context,
   1435  1.1     elric 					  crypto,
   1436  1.1     elric 					  usage,
   1437  1.1     elric 					  b->enc_authorization_data,
   1438  1.1     elric 					  &ad);
   1439  1.1     elric 	krb5_crypto_destroy(context, crypto);
   1440  1.1     elric 	if(ret){
   1441  1.1     elric 	    krb5_auth_con_free(context, ac);
   1442  1.1     elric 	    kdc_log(context, config, 0,
   1443  1.1     elric 		    "Failed to decrypt enc-authorization-data");
   1444  1.1     elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1445  1.1     elric 	    goto out;
   1446  1.1     elric 	}
   1447  1.1     elric 	ALLOC(*auth_data);
   1448  1.1     elric 	if (*auth_data == NULL) {
   1449  1.1     elric 	    krb5_auth_con_free(context, ac);
   1450  1.1     elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1451  1.1     elric 	    goto out;
   1452  1.1     elric 	}
   1453  1.1     elric 	ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
   1454  1.1     elric 	if(ret){
   1455  1.1     elric 	    krb5_auth_con_free(context, ac);
   1456  1.1     elric 	    free(*auth_data);
   1457  1.1     elric 	    *auth_data = NULL;
   1458  1.1     elric 	    kdc_log(context, config, 0, "Failed to decode authorization data");
   1459  1.1     elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1460  1.1     elric 	    goto out;
   1461  1.1     elric 	}
   1462  1.1     elric     }
   1463  1.1     elric 
   1464  1.1     elric     krb5_auth_con_free(context, ac);
   1465  1.1     elric 
   1466  1.1     elric out:
   1467  1.1     elric     free_AP_REQ(&ap_req);
   1468  1.1     elric 
   1469  1.1     elric     return ret;
   1470  1.1     elric }
   1471  1.1     elric 
   1472  1.1     elric static krb5_error_code
   1473  1.1     elric build_server_referral(krb5_context context,
   1474  1.1     elric 		      krb5_kdc_configuration *config,
   1475  1.1     elric 		      krb5_crypto session,
   1476  1.1     elric 		      krb5_const_realm referred_realm,
   1477  1.1     elric 		      const PrincipalName *true_principal_name,
   1478  1.1     elric 		      const PrincipalName *requested_principal,
   1479  1.1     elric 		      krb5_data *outdata)
   1480  1.2  christos {
   1481  1.1     elric     PA_ServerReferralData ref;
   1482  1.1     elric     krb5_error_code ret;
   1483  1.1     elric     EncryptedData ed;
   1484  1.1     elric     krb5_data data;
   1485  1.2  christos     size_t size = 0;
   1486  1.1     elric 
   1487  1.1     elric     memset(&ref, 0, sizeof(ref));
   1488  1.1     elric 
   1489  1.1     elric     if (referred_realm) {
   1490  1.1     elric 	ALLOC(ref.referred_realm);
   1491  1.1     elric 	if (ref.referred_realm == NULL)
   1492  1.1     elric 	    goto eout;
   1493  1.1     elric 	*ref.referred_realm = strdup(referred_realm);
   1494  1.1     elric 	if (*ref.referred_realm == NULL)
   1495  1.1     elric 	    goto eout;
   1496  1.1     elric     }
   1497  1.1     elric     if (true_principal_name) {
   1498  1.1     elric 	ALLOC(ref.true_principal_name);
   1499  1.1     elric 	if (ref.true_principal_name == NULL)
   1500  1.1     elric 	    goto eout;
   1501  1.1     elric 	ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
   1502  1.1     elric 	if (ret)
   1503  1.1     elric 	    goto eout;
   1504  1.1     elric     }
   1505  1.1     elric     if (requested_principal) {
   1506  1.1     elric 	ALLOC(ref.requested_principal_name);
   1507  1.1     elric 	if (ref.requested_principal_name == NULL)
   1508  1.1     elric 	    goto eout;
   1509  1.1     elric 	ret = copy_PrincipalName(requested_principal,
   1510  1.1     elric 				 ref.requested_principal_name);
   1511  1.1     elric 	if (ret)
   1512  1.1     elric 	    goto eout;
   1513  1.1     elric     }
   1514  1.1     elric 
   1515  1.1     elric     ASN1_MALLOC_ENCODE(PA_ServerReferralData,
   1516  1.1     elric 		       data.data, data.length,
   1517  1.1     elric 		       &ref, &size, ret);
   1518  1.1     elric     free_PA_ServerReferralData(&ref);
   1519  1.1     elric     if (ret)
   1520  1.1     elric 	return ret;
   1521  1.1     elric     if (data.length != size)
   1522  1.1     elric 	krb5_abortx(context, "internal asn.1 encoder error");
   1523  1.1     elric 
   1524  1.1     elric     ret = krb5_encrypt_EncryptedData(context, session,
   1525  1.1     elric 				     KRB5_KU_PA_SERVER_REFERRAL,
   1526  1.1     elric 				     data.data, data.length,
   1527  1.1     elric 				     0 /* kvno */, &ed);
   1528  1.1     elric     free(data.data);
   1529  1.1     elric     if (ret)
   1530  1.1     elric 	return ret;
   1531  1.1     elric 
   1532  1.1     elric     ASN1_MALLOC_ENCODE(EncryptedData,
   1533  1.1     elric 		       outdata->data, outdata->length,
   1534  1.1     elric 		       &ed, &size, ret);
   1535  1.1     elric     free_EncryptedData(&ed);
   1536  1.1     elric     if (ret)
   1537  1.1     elric 	return ret;
   1538  1.1     elric     if (outdata->length != size)
   1539  1.1     elric 	krb5_abortx(context, "internal asn.1 encoder error");
   1540  1.1     elric 
   1541  1.1     elric     return 0;
   1542  1.1     elric eout:
   1543  1.1     elric     free_PA_ServerReferralData(&ref);
   1544  1.1     elric     krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
   1545  1.1     elric     return ENOMEM;
   1546  1.1     elric }
   1547  1.1     elric 
   1548  1.1     elric static krb5_error_code
   1549  1.1     elric tgs_build_reply(krb5_context context,
   1550  1.1     elric 		krb5_kdc_configuration *config,
   1551  1.1     elric 		KDC_REQ *req,
   1552  1.1     elric 		KDC_REQ_BODY *b,
   1553  1.1     elric 		hdb_entry_ex *krbtgt,
   1554  1.1     elric 		krb5_enctype krbtgt_etype,
   1555  1.1     elric 		const krb5_keyblock *replykey,
   1556  1.1     elric 		int rk_is_subkey,
   1557  1.1     elric 		krb5_ticket *ticket,
   1558  1.1     elric 		krb5_data *reply,
   1559  1.1     elric 		const char *from,
   1560  1.1     elric 		const char **e_text,
   1561  1.1     elric 		AuthorizationData **auth_data,
   1562  1.1     elric 		const struct sockaddr *from_addr)
   1563  1.1     elric {
   1564  1.3  christos     krb5_error_code ret, ret2;
   1565  1.2  christos     krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL;
   1566  1.2  christos     krb5_principal krbtgt_out_principal = NULL;
   1567  1.2  christos     char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL, *krbtgt_out_n = NULL;
   1568  1.1     elric     hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
   1569  1.1     elric     HDB *clientdb, *s4u2self_impersonated_clientdb;
   1570  1.1     elric     krb5_realm ref_realm = NULL;
   1571  1.1     elric     EncTicketPart *tgt = &ticket->ticket;
   1572  1.1     elric     krb5_principals spp = NULL;
   1573  1.1     elric     const EncryptionKey *ekey;
   1574  1.1     elric     krb5_keyblock sessionkey;
   1575  1.1     elric     krb5_kvno kvno;
   1576  1.1     elric     krb5_data rspac;
   1577  1.3  christos     const char *tgt_realm = /* Realm of TGT issuer */
   1578  1.3  christos         krb5_principal_get_realm(context, krbtgt->entry.principal);
   1579  1.2  christos     const char *our_realm = /* Realm of this KDC */
   1580  1.2  christos         krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
   1581  1.2  christos     char **capath = NULL;
   1582  1.2  christos     size_t num_capath = 0;
   1583  1.1     elric 
   1584  1.1     elric     hdb_entry_ex *krbtgt_out = NULL;
   1585  1.1     elric 
   1586  1.1     elric     METHOD_DATA enc_pa_data;
   1587  1.1     elric 
   1588  1.1     elric     PrincipalName *s;
   1589  1.1     elric     Realm r;
   1590  1.1     elric     EncTicketPart adtkt;
   1591  1.1     elric     char opt_str[128];
   1592  1.1     elric     int signedpath = 0;
   1593  1.1     elric 
   1594  1.1     elric     Key *tkey_check;
   1595  1.1     elric     Key *tkey_sign;
   1596  1.2  christos     int flags = HDB_F_FOR_TGS_REQ;
   1597  1.1     elric 
   1598  1.1     elric     memset(&sessionkey, 0, sizeof(sessionkey));
   1599  1.1     elric     memset(&adtkt, 0, sizeof(adtkt));
   1600  1.1     elric     krb5_data_zero(&rspac);
   1601  1.1     elric     memset(&enc_pa_data, 0, sizeof(enc_pa_data));
   1602  1.1     elric 
   1603  1.1     elric     s = b->sname;
   1604  1.1     elric     r = b->realm;
   1605  1.1     elric 
   1606  1.2  christos     /*
   1607  1.2  christos      * Always to do CANON, see comment below about returned server principal (rsp).
   1608  1.2  christos      */
   1609  1.2  christos     flags |= HDB_F_CANON;
   1610  1.2  christos 
   1611  1.1     elric     if(b->kdc_options.enc_tkt_in_skey){
   1612  1.1     elric 	Ticket *t;
   1613  1.1     elric 	hdb_entry_ex *uu;
   1614  1.1     elric 	krb5_principal p;
   1615  1.1     elric 	Key *uukey;
   1616  1.2  christos 	krb5uint32 second_kvno = 0;
   1617  1.2  christos 	krb5uint32 *kvno_ptr = NULL;
   1618  1.2  christos 
   1619  1.1     elric 	if(b->additional_tickets == NULL ||
   1620  1.1     elric 	   b->additional_tickets->len == 0){
   1621  1.1     elric 	    ret = KRB5KDC_ERR_BADOPTION; /* ? */
   1622  1.1     elric 	    kdc_log(context, config, 0,
   1623  1.1     elric 		    "No second ticket present in request");
   1624  1.1     elric 	    goto out;
   1625  1.1     elric 	}
   1626  1.1     elric 	t = &b->additional_tickets->val[0];
   1627  1.1     elric 	if(!get_krbtgt_realm(&t->sname)){
   1628  1.1     elric 	    kdc_log(context, config, 0,
   1629  1.1     elric 		    "Additional ticket is not a ticket-granting ticket");
   1630  1.1     elric 	    ret = KRB5KDC_ERR_POLICY;
   1631  1.1     elric 	    goto out;
   1632  1.1     elric 	}
   1633  1.1     elric 	_krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
   1634  1.2  christos 	if(t->enc_part.kvno){
   1635  1.2  christos 	    second_kvno = *t->enc_part.kvno;
   1636  1.2  christos 	    kvno_ptr = &second_kvno;
   1637  1.2  christos 	}
   1638  1.1     elric 	ret = _kdc_db_fetch(context, config, p,
   1639  1.2  christos 			    HDB_F_GET_KRBTGT, kvno_ptr,
   1640  1.1     elric 			    NULL, &uu);
   1641  1.1     elric 	krb5_free_principal(context, p);
   1642  1.1     elric 	if(ret){
   1643  1.1     elric 	    if (ret == HDB_ERR_NOENTRY)
   1644  1.1     elric 		ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
   1645  1.1     elric 	    goto out;
   1646  1.1     elric 	}
   1647  1.2  christos 	ret = hdb_enctype2key(context, &uu->entry, NULL,
   1648  1.1     elric 			      t->enc_part.etype, &uukey);
   1649  1.1     elric 	if(ret){
   1650  1.1     elric 	    _kdc_free_ent(context, uu);
   1651  1.1     elric 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
   1652  1.1     elric 	    goto out;
   1653  1.1     elric 	}
   1654  1.1     elric 	ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
   1655  1.1     elric 	_kdc_free_ent(context, uu);
   1656  1.1     elric 	if(ret)
   1657  1.1     elric 	    goto out;
   1658  1.1     elric 
   1659  1.1     elric 	ret = verify_flags(context, config, &adtkt, spn);
   1660  1.1     elric 	if (ret)
   1661  1.1     elric 	    goto out;
   1662  1.1     elric 
   1663  1.1     elric 	s = &adtkt.cname;
   1664  1.1     elric 	r = adtkt.crealm;
   1665  1.1     elric     }
   1666  1.1     elric 
   1667  1.1     elric     _krb5_principalname2krb5_principal(context, &sp, *s, r);
   1668  1.2  christos     ret = krb5_unparse_name(context, sp, &spn);
   1669  1.1     elric     if (ret)
   1670  1.1     elric 	goto out;
   1671  1.1     elric     _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
   1672  1.1     elric     ret = krb5_unparse_name(context, cp, &cpn);
   1673  1.1     elric     if (ret)
   1674  1.1     elric 	goto out;
   1675  1.1     elric     unparse_flags (KDCOptions2int(b->kdc_options),
   1676  1.1     elric 		   asn1_KDCOptions_units(),
   1677  1.1     elric 		   opt_str, sizeof(opt_str));
   1678  1.1     elric     if(*opt_str)
   1679  1.1     elric 	kdc_log(context, config, 0,
   1680  1.1     elric 		"TGS-REQ %s from %s for %s [%s]",
   1681  1.1     elric 		cpn, from, spn, opt_str);
   1682  1.1     elric     else
   1683  1.1     elric 	kdc_log(context, config, 0,
   1684  1.1     elric 		"TGS-REQ %s from %s for %s", cpn, from, spn);
   1685  1.1     elric 
   1686  1.1     elric     /*
   1687  1.1     elric      * Fetch server
   1688  1.1     elric      */
   1689  1.1     elric 
   1690  1.1     elric server_lookup:
   1691  1.2  christos     ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags,
   1692  1.1     elric 			NULL, NULL, &server);
   1693  1.1     elric 
   1694  1.2  christos     if (ret == HDB_ERR_NOT_FOUND_HERE) {
   1695  1.1     elric 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
   1696  1.1     elric 	goto out;
   1697  1.2  christos     } else if (ret == HDB_ERR_WRONG_REALM) {
   1698  1.2  christos         free(ref_realm);
   1699  1.2  christos 	ref_realm = strdup(server->entry.principal->realm);
   1700  1.2  christos 	if (ref_realm == NULL) {
   1701  1.2  christos             ret = krb5_enomem(context);
   1702  1.2  christos 	    goto out;
   1703  1.2  christos 	}
   1704  1.2  christos 
   1705  1.2  christos 	kdc_log(context, config, 5,
   1706  1.2  christos 		"Returning a referral to realm %s for "
   1707  1.2  christos 		"server %s.",
   1708  1.2  christos 		ref_realm, spn);
   1709  1.2  christos 	krb5_free_principal(context, sp);
   1710  1.2  christos 	sp = NULL;
   1711  1.2  christos 	ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
   1712  1.2  christos 				  ref_realm, NULL);
   1713  1.2  christos 	if (ret)
   1714  1.2  christos 	    goto out;
   1715  1.2  christos 	free(spn);
   1716  1.2  christos         spn = NULL;
   1717  1.2  christos 	ret = krb5_unparse_name(context, sp, &spn);
   1718  1.2  christos 	if (ret)
   1719  1.2  christos 	    goto out;
   1720  1.2  christos 
   1721  1.2  christos 	goto server_lookup;
   1722  1.2  christos     } else if (ret) {
   1723  1.1     elric 	const char *new_rlm, *msg;
   1724  1.1     elric 	Realm req_rlm;
   1725  1.1     elric 	krb5_realm *realms;
   1726  1.1     elric 
   1727  1.1     elric 	if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
   1728  1.2  christos             if (capath == NULL) {
   1729  1.2  christos                 /* With referalls, hierarchical capaths are always enabled */
   1730  1.3  christos                 ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
   1731  1.3  christos                                          req_rlm, TRUE, &capath, &num_capath);
   1732  1.3  christos                 if (ret2) {
   1733  1.3  christos                     ret = ret2;
   1734  1.2  christos                     goto out;
   1735  1.3  christos                 }
   1736  1.2  christos             }
   1737  1.2  christos             new_rlm = num_capath > 0 ? capath[--num_capath] : NULL;
   1738  1.2  christos             if (new_rlm) {
   1739  1.2  christos                 kdc_log(context, config, 5, "krbtgt from %s via %s for "
   1740  1.2  christos                         "realm %s not found, trying %s", tgt->crealm,
   1741  1.2  christos                         our_realm, req_rlm, new_rlm);
   1742  1.2  christos 
   1743  1.2  christos                 free(ref_realm);
   1744  1.2  christos                 ref_realm = strdup(new_rlm);
   1745  1.2  christos                 if (ref_realm == NULL) {
   1746  1.2  christos                     ret = krb5_enomem(context);
   1747  1.2  christos                     goto out;
   1748  1.2  christos                 }
   1749  1.2  christos 
   1750  1.2  christos                 krb5_free_principal(context, sp);
   1751  1.2  christos                 sp = NULL;
   1752  1.2  christos                 krb5_make_principal(context, &sp, r,
   1753  1.2  christos                                     KRB5_TGS_NAME, ref_realm, NULL);
   1754  1.2  christos                 free(spn);
   1755  1.2  christos                 spn = NULL;
   1756  1.2  christos                 ret = krb5_unparse_name(context, sp, &spn);
   1757  1.2  christos                 if (ret)
   1758  1.2  christos                     goto out;
   1759  1.2  christos                 goto server_lookup;
   1760  1.2  christos             }
   1761  1.2  christos 	} else if (need_referral(context, config, &b->kdc_options, sp, &realms)) {
   1762  1.1     elric 	    if (strcmp(realms[0], sp->realm) != 0) {
   1763  1.1     elric 		kdc_log(context, config, 5,
   1764  1.1     elric 			"Returning a referral to realm %s for "
   1765  1.1     elric 			"server %s that was not found",
   1766  1.1     elric 			realms[0], spn);
   1767  1.1     elric 		krb5_free_principal(context, sp);
   1768  1.2  christos                 sp = NULL;
   1769  1.1     elric 		krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
   1770  1.1     elric 				    realms[0], NULL);
   1771  1.2  christos 		free(spn);
   1772  1.2  christos                 spn = NULL;
   1773  1.1     elric 		ret = krb5_unparse_name(context, sp, &spn);
   1774  1.2  christos 		if (ret) {
   1775  1.2  christos 		    krb5_free_host_realm(context, realms);
   1776  1.1     elric 		    goto out;
   1777  1.2  christos 		}
   1778  1.1     elric 
   1779  1.2  christos                 free(ref_realm);
   1780  1.1     elric 		ref_realm = strdup(realms[0]);
   1781  1.1     elric 
   1782  1.1     elric 		krb5_free_host_realm(context, realms);
   1783  1.1     elric 		goto server_lookup;
   1784  1.1     elric 	    }
   1785  1.1     elric 	    krb5_free_host_realm(context, realms);
   1786  1.1     elric 	}
   1787  1.1     elric 	msg = krb5_get_error_message(context, ret);
   1788  1.1     elric 	kdc_log(context, config, 0,
   1789  1.1     elric 		"Server not found in database: %s: %s", spn, msg);
   1790  1.1     elric 	krb5_free_error_message(context, msg);
   1791  1.1     elric 	if (ret == HDB_ERR_NOENTRY)
   1792  1.1     elric 	    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
   1793  1.1     elric 	goto out;
   1794  1.1     elric     }
   1795  1.1     elric 
   1796  1.2  christos     /* the name returned to the client depend on what was asked for,
   1797  1.2  christos      * return canonical name if kdc_options.canonicalize was set, the
   1798  1.2  christos      * client wants the true name of the principal, if not it just
   1799  1.2  christos      * wants the name its asked for.
   1800  1.2  christos      */
   1801  1.2  christos 
   1802  1.2  christos     if (b->kdc_options.canonicalize)
   1803  1.2  christos 	rsp = server->entry.principal;
   1804  1.2  christos     else
   1805  1.2  christos 	rsp = sp;
   1806  1.2  christos 
   1807  1.2  christos 
   1808  1.1     elric     /*
   1809  1.1     elric      * Select enctype, return key and kvno.
   1810  1.1     elric      */
   1811  1.1     elric 
   1812  1.1     elric     {
   1813  1.1     elric 	krb5_enctype etype;
   1814  1.1     elric 
   1815  1.1     elric 	if(b->kdc_options.enc_tkt_in_skey) {
   1816  1.2  christos 	    size_t i;
   1817  1.1     elric 	    ekey = &adtkt.key;
   1818  1.1     elric 	    for(i = 0; i < b->etype.len; i++)
   1819  1.1     elric 		if (b->etype.val[i] == adtkt.key.keytype)
   1820  1.1     elric 		    break;
   1821  1.1     elric 	    if(i == b->etype.len) {
   1822  1.1     elric 		kdc_log(context, config, 0,
   1823  1.1     elric 			"Addition ticket have not matching etypes");
   1824  1.1     elric 		krb5_clear_error_message(context);
   1825  1.1     elric 		ret = KRB5KDC_ERR_ETYPE_NOSUPP;
   1826  1.1     elric 		goto out;
   1827  1.1     elric 	    }
   1828  1.1     elric 	    etype = b->etype.val[i];
   1829  1.1     elric 	    kvno = 0;
   1830  1.1     elric 	} else {
   1831  1.1     elric 	    Key *skey;
   1832  1.2  christos 
   1833  1.2  christos 	    ret = _kdc_find_etype(context,
   1834  1.2  christos 				  krb5_principal_is_krbtgt(context, sp) ?
   1835  1.2  christos 				  config->tgt_use_strongest_session_key :
   1836  1.2  christos 				  config->svc_use_strongest_session_key, FALSE,
   1837  1.2  christos 				  server, b->etype.val, b->etype.len, &etype,
   1838  1.2  christos 				  NULL);
   1839  1.1     elric 	    if(ret) {
   1840  1.1     elric 		kdc_log(context, config, 0,
   1841  1.1     elric 			"Server (%s) has no support for etypes", spn);
   1842  1.1     elric 		goto out;
   1843  1.1     elric 	    }
   1844  1.2  christos 	    ret = _kdc_get_preferred_key(context, config, server, spn,
   1845  1.2  christos 					 NULL, &skey);
   1846  1.2  christos 	    if(ret) {
   1847  1.2  christos 		kdc_log(context, config, 0,
   1848  1.2  christos 			"Server (%s) has no supported etypes", spn);
   1849  1.2  christos 		goto out;
   1850  1.2  christos 	    }
   1851  1.1     elric 	    ekey = &skey->key;
   1852  1.1     elric 	    kvno = server->entry.kvno;
   1853  1.1     elric 	}
   1854  1.2  christos 
   1855  1.1     elric 	ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
   1856  1.1     elric 	if (ret)
   1857  1.1     elric 	    goto out;
   1858  1.1     elric     }
   1859  1.1     elric 
   1860  1.1     elric     /*
   1861  1.1     elric      * Check that service is in the same realm as the krbtgt. If it's
   1862  1.1     elric      * not the same, it's someone that is using a uni-directional trust
   1863  1.1     elric      * backward.
   1864  1.1     elric      */
   1865  1.1     elric 
   1866  1.1     elric     /*
   1867  1.1     elric      * Validate authoriation data
   1868  1.1     elric      */
   1869  1.1     elric 
   1870  1.2  christos     ret = hdb_enctype2key(context, &krbtgt->entry, NULL, /* XXX use the right kvno! */
   1871  1.1     elric 			  krbtgt_etype, &tkey_check);
   1872  1.1     elric     if(ret) {
   1873  1.1     elric 	kdc_log(context, config, 0,
   1874  1.1     elric 		    "Failed to find key for krbtgt PAC check");
   1875  1.1     elric 	goto out;
   1876  1.1     elric     }
   1877  1.1     elric 
   1878  1.2  christos     /*
   1879  1.2  christos      * Now refetch the primary krbtgt, and get the current kvno (the
   1880  1.1     elric      * sign check may have been on an old kvno, and the server may
   1881  1.2  christos      * have been an incoming trust)
   1882  1.2  christos      */
   1883  1.2  christos 
   1884  1.2  christos     ret = krb5_make_principal(context,
   1885  1.2  christos                               &krbtgt_out_principal,
   1886  1.2  christos                               our_realm,
   1887  1.2  christos                               KRB5_TGS_NAME,
   1888  1.2  christos                               our_realm,
   1889  1.2  christos                               NULL);
   1890  1.2  christos     if (ret) {
   1891  1.2  christos         kdc_log(context, config, 0,
   1892  1.2  christos                 "Failed to make krbtgt principal name object for "
   1893  1.2  christos                 "authz-data signatures");
   1894  1.2  christos         goto out;
   1895  1.2  christos     }
   1896  1.2  christos     ret = krb5_unparse_name(context, krbtgt_out_principal, &krbtgt_out_n);
   1897  1.2  christos     if (ret) {
   1898  1.2  christos         kdc_log(context, config, 0,
   1899  1.2  christos                 "Failed to make krbtgt principal name object for "
   1900  1.2  christos                 "authz-data signatures");
   1901  1.2  christos         goto out;
   1902  1.1     elric     }
   1903  1.1     elric 
   1904  1.2  christos     ret = _kdc_db_fetch(context, config, krbtgt_out_principal,
   1905  1.2  christos 			HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
   1906  1.1     elric     if (ret) {
   1907  1.2  christos 	char *ktpn = NULL;
   1908  1.2  christos 	ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn);
   1909  1.1     elric 	kdc_log(context, config, 0,
   1910  1.2  christos 		"No such principal %s (needed for authz-data signature keys) "
   1911  1.2  christos 		"while processing TGS-REQ for service %s with krbtg %s",
   1912  1.2  christos 		krbtgt_out_n, spn, (ret == 0) ? ktpn : "<unknown>");
   1913  1.2  christos 	free(ktpn);
   1914  1.1     elric 	ret = KRB5KRB_AP_ERR_NOT_US;
   1915  1.1     elric 	goto out;
   1916  1.1     elric     }
   1917  1.1     elric 
   1918  1.2  christos     /*
   1919  1.2  christos      * The first realm is the realm of the service, the second is
   1920  1.1     elric      * krbtgt/<this>/@REALM component of the krbtgt DN the request was
   1921  1.1     elric      * encrypted to.  The redirection via the krbtgt_out entry allows
   1922  1.1     elric      * the DB to possibly correct the case of the realm (Samba4 does
   1923  1.2  christos      * this) before the strcmp()
   1924  1.2  christos      */
   1925  1.1     elric     if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
   1926  1.1     elric 	       krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
   1927  1.2  christos 	char *ktpn;
   1928  1.2  christos 	ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn);
   1929  1.1     elric 	kdc_log(context, config, 0,
   1930  1.1     elric 		"Request with wrong krbtgt: %s",
   1931  1.2  christos 		(ret == 0) ? ktpn : "<unknown>");
   1932  1.1     elric 	if(ret == 0)
   1933  1.2  christos 	    free(ktpn);
   1934  1.1     elric 	ret = KRB5KRB_AP_ERR_NOT_US;
   1935  1.2  christos 	goto out;
   1936  1.1     elric     }
   1937  1.1     elric 
   1938  1.2  christos     ret = _kdc_get_preferred_key(context, config, krbtgt_out, krbtgt_out_n,
   1939  1.2  christos 				 NULL, &tkey_sign);
   1940  1.2  christos     if (ret) {
   1941  1.2  christos 	kdc_log(context, config, 0,
   1942  1.2  christos 		    "Failed to find key for krbtgt PAC signature");
   1943  1.2  christos 	goto out;
   1944  1.2  christos     }
   1945  1.2  christos     ret = hdb_enctype2key(context, &krbtgt_out->entry, NULL,
   1946  1.2  christos 			  tkey_sign->key.keytype, &tkey_sign);
   1947  1.1     elric     if(ret) {
   1948  1.1     elric 	kdc_log(context, config, 0,
   1949  1.1     elric 		    "Failed to find key for krbtgt PAC signature");
   1950  1.1     elric 	goto out;
   1951  1.1     elric     }
   1952  1.1     elric 
   1953  1.2  christos     ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags,
   1954  1.1     elric 			NULL, &clientdb, &client);
   1955  1.1     elric     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1956  1.1     elric 	/* This is OK, we are just trying to find out if they have
   1957  1.1     elric 	 * been disabled or deleted in the meantime, missing secrets
   1958  1.1     elric 	 * is OK */
   1959  1.1     elric     } else if(ret){
   1960  1.1     elric 	const char *krbtgt_realm, *msg;
   1961  1.1     elric 
   1962  1.1     elric 	/*
   1963  1.1     elric 	 * If the client belongs to the same realm as our krbtgt, it
   1964  1.1     elric 	 * should exist in the local database.
   1965  1.1     elric 	 *
   1966  1.1     elric 	 */
   1967  1.1     elric 
   1968  1.1     elric 	krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal);
   1969  1.1     elric 
   1970  1.1     elric 	if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
   1971  1.1     elric 	    if (ret == HDB_ERR_NOENTRY)
   1972  1.1     elric 		ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   1973  1.1     elric 	    kdc_log(context, config, 1, "Client no longer in database: %s",
   1974  1.1     elric 		    cpn);
   1975  1.1     elric 	    goto out;
   1976  1.1     elric 	}
   1977  1.1     elric 
   1978  1.1     elric 	msg = krb5_get_error_message(context, ret);
   1979  1.1     elric 	kdc_log(context, config, 1, "Client not found in database: %s", msg);
   1980  1.1     elric 	krb5_free_error_message(context, msg);
   1981  1.1     elric     }
   1982  1.1     elric 
   1983  1.2  christos     ret = check_PAC(context, config, cp, NULL,
   1984  1.2  christos 		    client, server, krbtgt,
   1985  1.2  christos 		    &tkey_check->key,
   1986  1.2  christos 		    ekey, &tkey_sign->key,
   1987  1.1     elric 		    tgt, &rspac, &signedpath);
   1988  1.1     elric     if (ret) {
   1989  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   1990  1.1     elric 	kdc_log(context, config, 0,
   1991  1.1     elric 		"Verify PAC failed for %s (%s) from %s with %s",
   1992  1.1     elric 		spn, cpn, from, msg);
   1993  1.1     elric 	krb5_free_error_message(context, msg);
   1994  1.1     elric 	goto out;
   1995  1.1     elric     }
   1996  1.1     elric 
   1997  1.1     elric     /* also check the krbtgt for signature */
   1998  1.1     elric     ret = check_KRB5SignedPath(context,
   1999  1.1     elric 			       config,
   2000  1.1     elric 			       krbtgt,
   2001  1.1     elric 			       cp,
   2002  1.1     elric 			       tgt,
   2003  1.1     elric 			       &spp,
   2004  1.1     elric 			       &signedpath);
   2005  1.1     elric     if (ret) {
   2006  1.1     elric 	const char *msg = krb5_get_error_message(context, ret);
   2007  1.1     elric 	kdc_log(context, config, 0,
   2008  1.1     elric 		"KRB5SignedPath check failed for %s (%s) from %s with %s",
   2009  1.1     elric 		spn, cpn, from, msg);
   2010  1.1     elric 	krb5_free_error_message(context, msg);
   2011  1.1     elric 	goto out;
   2012  1.1     elric     }
   2013  1.1     elric 
   2014  1.1     elric     /*
   2015  1.1     elric      * Process request
   2016  1.1     elric      */
   2017  1.1     elric 
   2018  1.2  christos     /* by default the tgt principal matches the client principal */
   2019  1.2  christos     tp = cp;
   2020  1.2  christos     tpn = cpn;
   2021  1.1     elric 
   2022  1.1     elric     if (client) {
   2023  1.1     elric 	const PA_DATA *sdata;
   2024  1.1     elric 	int i = 0;
   2025  1.1     elric 
   2026  1.1     elric 	sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
   2027  1.1     elric 	if (sdata) {
   2028  1.1     elric 	    krb5_crypto crypto;
   2029  1.1     elric 	    krb5_data datack;
   2030  1.1     elric 	    PA_S4U2Self self;
   2031  1.1     elric 	    const char *str;
   2032  1.1     elric 
   2033  1.1     elric 	    ret = decode_PA_S4U2Self(sdata->padata_value.data,
   2034  1.1     elric 				     sdata->padata_value.length,
   2035  1.1     elric 				     &self, NULL);
   2036  1.1     elric 	    if (ret) {
   2037  1.1     elric 		kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
   2038  1.1     elric 		goto out;
   2039  1.1     elric 	    }
   2040  1.1     elric 
   2041  1.3  christos 	    if (!krb5_checksum_is_keyed(context, self.cksum.cksumtype)) {
   2042  1.3  christos 		free_PA_S4U2Self(&self);
   2043  1.3  christos 		kdc_log(context, config, 0, "Reject PA-S4U2Self with unkeyed checksum");
   2044  1.3  christos 		ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
   2045  1.3  christos 		goto out;
   2046  1.3  christos 	    }
   2047  1.3  christos 
   2048  1.1     elric 	    ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
   2049  1.1     elric 	    if (ret)
   2050  1.1     elric 		goto out;
   2051  1.1     elric 
   2052  1.1     elric 	    ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
   2053  1.1     elric 	    if (ret) {
   2054  1.1     elric 		const char *msg = krb5_get_error_message(context, ret);
   2055  1.1     elric 		free_PA_S4U2Self(&self);
   2056  1.1     elric 		krb5_data_free(&datack);
   2057  1.1     elric 		kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   2058  1.1     elric 		krb5_free_error_message(context, msg);
   2059  1.1     elric 		goto out;
   2060  1.1     elric 	    }
   2061  1.1     elric 
   2062  1.3  christos 	    /* Allow HMAC_MD5 checksum with any key type */
   2063  1.3  christos 	    if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
   2064  1.3  christos 		unsigned char csdata[16];
   2065  1.3  christos 		Checksum cs;
   2066  1.3  christos 
   2067  1.3  christos 		cs.checksum.length = sizeof(csdata);
   2068  1.3  christos 		cs.checksum.data = &csdata;
   2069  1.3  christos 
   2070  1.3  christos 		ret = _krb5_HMAC_MD5_checksum(context, &crypto->key,
   2071  1.3  christos 					      datack.data, datack.length,
   2072  1.3  christos 					      KRB5_KU_OTHER_CKSUM, &cs);
   2073  1.3  christos 		if (ret == 0 &&
   2074  1.3  christos 		    krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0)
   2075  1.3  christos 		    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
   2076  1.3  christos 	    }
   2077  1.3  christos 	    else {
   2078  1.3  christos 		ret = krb5_verify_checksum(context,
   2079  1.3  christos 					   crypto,
   2080  1.3  christos 					   KRB5_KU_OTHER_CKSUM,
   2081  1.3  christos 					   datack.data,
   2082  1.3  christos 					   datack.length,
   2083  1.3  christos 					   &self.cksum);
   2084  1.3  christos 	    }
   2085  1.1     elric 	    krb5_data_free(&datack);
   2086  1.1     elric 	    krb5_crypto_destroy(context, crypto);
   2087  1.1     elric 	    if (ret) {
   2088  1.1     elric 		const char *msg = krb5_get_error_message(context, ret);
   2089  1.1     elric 		free_PA_S4U2Self(&self);
   2090  1.1     elric 		kdc_log(context, config, 0,
   2091  1.1     elric 			"krb5_verify_checksum failed for S4U2Self: %s", msg);
   2092  1.1     elric 		krb5_free_error_message(context, msg);
   2093  1.1     elric 		goto out;
   2094  1.1     elric 	    }
   2095  1.1     elric 
   2096  1.1     elric 	    ret = _krb5_principalname2krb5_principal(context,
   2097  1.2  christos 						     &tp,
   2098  1.1     elric 						     self.name,
   2099  1.1     elric 						     self.realm);
   2100  1.1     elric 	    free_PA_S4U2Self(&self);
   2101  1.1     elric 	    if (ret)
   2102  1.1     elric 		goto out;
   2103  1.1     elric 
   2104  1.2  christos 	    ret = krb5_unparse_name(context, tp, &tpn);
   2105  1.1     elric 	    if (ret)
   2106  1.1     elric 		goto out;
   2107  1.1     elric 
   2108  1.1     elric 	    /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
   2109  1.1     elric 	    if(rspac.data) {
   2110  1.1     elric 		krb5_pac p = NULL;
   2111  1.1     elric 		krb5_data_free(&rspac);
   2112  1.2  christos 		ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags,
   2113  1.1     elric 				    NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
   2114  1.1     elric 		if (ret) {
   2115  1.1     elric 		    const char *msg;
   2116  1.1     elric 
   2117  1.1     elric 		    /*
   2118  1.1     elric 		     * If the client belongs to the same realm as our krbtgt, it
   2119  1.1     elric 		     * should exist in the local database.
   2120  1.1     elric 		     *
   2121  1.1     elric 		     */
   2122  1.1     elric 
   2123  1.1     elric 		    if (ret == HDB_ERR_NOENTRY)
   2124  1.1     elric 			ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   2125  1.1     elric 		    msg = krb5_get_error_message(context, ret);
   2126  1.2  christos 		    kdc_log(context, config, 1,
   2127  1.2  christos 			    "S2U4Self principal to impersonate %s not found in database: %s",
   2128  1.2  christos 			    tpn, msg);
   2129  1.1     elric 		    krb5_free_error_message(context, msg);
   2130  1.1     elric 		    goto out;
   2131  1.1     elric 		}
   2132  1.1     elric 		ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p);
   2133  1.1     elric 		if (ret) {
   2134  1.1     elric 		    kdc_log(context, config, 0, "PAC generation failed for -- %s",
   2135  1.2  christos 			    tpn);
   2136  1.1     elric 		    goto out;
   2137  1.1     elric 		}
   2138  1.1     elric 		if (p != NULL) {
   2139  1.1     elric 		    ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
   2140  1.1     elric 					 s4u2self_impersonated_client->entry.principal,
   2141  1.1     elric 					 ekey, &tkey_sign->key,
   2142  1.1     elric 					 &rspac);
   2143  1.1     elric 		    krb5_pac_free(context, p);
   2144  1.1     elric 		    if (ret) {
   2145  1.1     elric 			kdc_log(context, config, 0, "PAC signing failed for -- %s",
   2146  1.2  christos 				tpn);
   2147  1.1     elric 			goto out;
   2148  1.1     elric 		    }
   2149  1.1     elric 		}
   2150  1.1     elric 	    }
   2151  1.1     elric 
   2152  1.1     elric 	    /*
   2153  1.1     elric 	     * Check that service doing the impersonating is
   2154  1.1     elric 	     * requesting a ticket to it-self.
   2155  1.1     elric 	     */
   2156  1.1     elric 	    ret = check_s4u2self(context, config, clientdb, client, sp);
   2157  1.1     elric 	    if (ret) {
   2158  1.1     elric 		kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
   2159  1.1     elric 			"to impersonate to service "
   2160  1.1     elric 			"(tried for user %s to service %s)",
   2161  1.2  christos 			cpn, tpn, spn);
   2162  1.1     elric 		goto out;
   2163  1.1     elric 	    }
   2164  1.1     elric 
   2165  1.1     elric 	    /*
   2166  1.1     elric 	     * If the service isn't trusted for authentication to
   2167  1.1     elric 	     * delegation, remove the forward flag.
   2168  1.1     elric 	     */
   2169  1.1     elric 
   2170  1.1     elric 	    if (client->entry.flags.trusted_for_delegation) {
   2171  1.1     elric 		str = "[forwardable]";
   2172  1.1     elric 	    } else {
   2173  1.1     elric 		b->kdc_options.forwardable = 0;
   2174  1.1     elric 		str = "";
   2175  1.1     elric 	    }
   2176  1.1     elric 	    kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
   2177  1.2  christos 		    "service %s %s", cpn, tpn, spn, str);
   2178  1.1     elric 	}
   2179  1.1     elric     }
   2180  1.1     elric 
   2181  1.1     elric     /*
   2182  1.1     elric      * Constrained delegation
   2183  1.1     elric      */
   2184  1.1     elric 
   2185  1.1     elric     if (client != NULL
   2186  1.1     elric 	&& b->additional_tickets != NULL
   2187  1.1     elric 	&& b->additional_tickets->len != 0
   2188  1.3  christos 	&& b->kdc_options.cname_in_addl_tkt
   2189  1.1     elric 	&& b->kdc_options.enc_tkt_in_skey == 0)
   2190  1.1     elric     {
   2191  1.1     elric 	int ad_signedpath = 0;
   2192  1.1     elric 	Key *clientkey;
   2193  1.1     elric 	Ticket *t;
   2194  1.1     elric 
   2195  1.1     elric 	/*
   2196  1.1     elric 	 * Require that the KDC have issued the service's krbtgt (not
   2197  1.1     elric 	 * self-issued ticket with kimpersonate(1).
   2198  1.1     elric 	 */
   2199  1.1     elric 	if (!signedpath) {
   2200  1.1     elric 	    ret = KRB5KDC_ERR_BADOPTION;
   2201  1.1     elric 	    kdc_log(context, config, 0,
   2202  1.1     elric 		    "Constrained delegation done on service ticket %s/%s",
   2203  1.1     elric 		    cpn, spn);
   2204  1.1     elric 	    goto out;
   2205  1.1     elric 	}
   2206  1.1     elric 
   2207  1.1     elric 	t = &b->additional_tickets->val[0];
   2208  1.1     elric 
   2209  1.1     elric 	ret = hdb_enctype2key(context, &client->entry,
   2210  1.2  christos 			      hdb_kvno2keys(context, &client->entry,
   2211  1.2  christos 					    t->enc_part.kvno ? * t->enc_part.kvno : 0),
   2212  1.1     elric 			      t->enc_part.etype, &clientkey);
   2213  1.1     elric 	if(ret){
   2214  1.1     elric 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
   2215  1.1     elric 	    goto out;
   2216  1.1     elric 	}
   2217  1.1     elric 
   2218  1.1     elric 	ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
   2219  1.1     elric 	if (ret) {
   2220  1.1     elric 	    kdc_log(context, config, 0,
   2221  1.1     elric 		    "failed to decrypt ticket for "
   2222  1.1     elric 		    "constrained delegation from %s to %s ", cpn, spn);
   2223  1.1     elric 	    goto out;
   2224  1.1     elric 	}
   2225  1.1     elric 
   2226  1.2  christos 	ret = _krb5_principalname2krb5_principal(context,
   2227  1.2  christos 						 &tp,
   2228  1.2  christos 						 adtkt.cname,
   2229  1.2  christos 						 adtkt.crealm);
   2230  1.2  christos 	if (ret)
   2231  1.2  christos 	    goto out;
   2232  1.2  christos 
   2233  1.2  christos 	ret = krb5_unparse_name(context, tp, &tpn);
   2234  1.2  christos 	if (ret)
   2235  1.2  christos 	    goto out;
   2236  1.2  christos 
   2237  1.2  christos 	ret = _krb5_principalname2krb5_principal(context,
   2238  1.2  christos 						 &dp,
   2239  1.2  christos 						 t->sname,
   2240  1.2  christos 						 t->realm);
   2241  1.2  christos 	if (ret)
   2242  1.2  christos 	    goto out;
   2243  1.2  christos 
   2244  1.2  christos 	ret = krb5_unparse_name(context, dp, &dpn);
   2245  1.2  christos 	if (ret)
   2246  1.2  christos 	    goto out;
   2247  1.2  christos 
   2248  1.1     elric 	/* check that ticket is valid */
   2249  1.1     elric 	if (adtkt.flags.forwardable == 0) {
   2250  1.1     elric 	    kdc_log(context, config, 0,
   2251  1.1     elric 		    "Missing forwardable flag on ticket for "
   2252  1.2  christos 		    "constrained delegation from %s (%s) as %s to %s ",
   2253  1.2  christos 		    cpn, dpn, tpn, spn);
   2254  1.1     elric 	    ret = KRB5KDC_ERR_BADOPTION;
   2255  1.1     elric 	    goto out;
   2256  1.1     elric 	}
   2257  1.1     elric 
   2258  1.2  christos 	ret = check_constrained_delegation(context, config, clientdb,
   2259  1.2  christos 					   client, server, sp);
   2260  1.1     elric 	if (ret) {
   2261  1.1     elric 	    kdc_log(context, config, 0,
   2262  1.2  christos 		    "constrained delegation from %s (%s) as %s to %s not allowed",
   2263  1.2  christos 		    cpn, dpn, tpn, spn);
   2264  1.1     elric 	    goto out;
   2265  1.1     elric 	}
   2266  1.1     elric 
   2267  1.2  christos 	ret = verify_flags(context, config, &adtkt, tpn);
   2268  1.2  christos 	if (ret) {
   2269  1.1     elric 	    goto out;
   2270  1.2  christos 	}
   2271  1.1     elric 
   2272  1.2  christos 	krb5_data_free(&rspac);
   2273  1.1     elric 
   2274  1.2  christos 	/*
   2275  1.2  christos 	 * generate the PAC for the user.
   2276  1.2  christos 	 *
   2277  1.2  christos 	 * TODO: pass in t->sname and t->realm and build
   2278  1.2  christos 	 * a S4U_DELEGATION_INFO blob to the PAC.
   2279  1.2  christos 	 */
   2280  1.2  christos 	ret = check_PAC(context, config, tp, dp,
   2281  1.2  christos 			client, server, krbtgt,
   2282  1.2  christos 			&clientkey->key,
   2283  1.2  christos 			ekey, &tkey_sign->key,
   2284  1.2  christos 			&adtkt, &rspac, &ad_signedpath);
   2285  1.1     elric 	if (ret) {
   2286  1.2  christos 	    const char *msg = krb5_get_error_message(context, ret);
   2287  1.2  christos 	    kdc_log(context, config, 0,
   2288  1.2  christos 		    "Verify delegated PAC failed to %s for client"
   2289  1.2  christos 		    "%s (%s) as %s from %s with %s",
   2290  1.2  christos 		    spn, cpn, dpn, tpn, from, msg);
   2291  1.2  christos 	    krb5_free_error_message(context, msg);
   2292  1.1     elric 	    goto out;
   2293  1.1     elric 	}
   2294  1.1     elric 
   2295  1.1     elric 	/*
   2296  1.1     elric 	 * Check that the KDC issued the user's ticket.
   2297  1.1     elric 	 */
   2298  1.1     elric 	ret = check_KRB5SignedPath(context,
   2299  1.1     elric 				   config,
   2300  1.1     elric 				   krbtgt,
   2301  1.1     elric 				   cp,
   2302  1.1     elric 				   &adtkt,
   2303  1.1     elric 				   NULL,
   2304  1.1     elric 				   &ad_signedpath);
   2305  1.1     elric 	if (ret) {
   2306  1.1     elric 	    const char *msg = krb5_get_error_message(context, ret);
   2307  1.1     elric 	    kdc_log(context, config, 0,
   2308  1.1     elric 		    "KRB5SignedPath check from service %s failed "
   2309  1.2  christos 		    "for delegation to %s for client %s (%s)"
   2310  1.1     elric 		    "from %s failed with %s",
   2311  1.2  christos 		    spn, tpn, dpn, cpn, from, msg);
   2312  1.1     elric 	    krb5_free_error_message(context, msg);
   2313  1.2  christos 	    goto out;
   2314  1.2  christos 	}
   2315  1.2  christos 
   2316  1.2  christos 	if (!ad_signedpath) {
   2317  1.2  christos 	    ret = KRB5KDC_ERR_BADOPTION;
   2318  1.2  christos 	    kdc_log(context, config, 0,
   2319  1.2  christos 		    "Ticket not signed with PAC nor SignedPath service %s failed "
   2320  1.2  christos 		    "for delegation to %s for client %s (%s)"
   2321  1.2  christos 		    "from %s",
   2322  1.2  christos 		    spn, tpn, dpn, cpn, from);
   2323  1.1     elric 	    goto out;
   2324  1.1     elric 	}
   2325  1.1     elric 
   2326  1.1     elric 	kdc_log(context, config, 0, "constrained delegation for %s "
   2327  1.2  christos 		"from %s (%s) to %s", tpn, cpn, dpn, spn);
   2328  1.1     elric     }
   2329  1.1     elric 
   2330  1.1     elric     /*
   2331  1.1     elric      * Check flags
   2332  1.1     elric      */
   2333  1.1     elric 
   2334  1.1     elric     ret = kdc_check_flags(context, config,
   2335  1.1     elric 			  client, cpn,
   2336  1.1     elric 			  server, spn,
   2337  1.1     elric 			  FALSE);
   2338  1.1     elric     if(ret)
   2339  1.1     elric 	goto out;
   2340  1.1     elric 
   2341  1.1     elric     if((b->kdc_options.validate || b->kdc_options.renew) &&
   2342  1.1     elric        !krb5_principal_compare(context,
   2343  1.1     elric 			       krbtgt->entry.principal,
   2344  1.1     elric 			       server->entry.principal)){
   2345  1.1     elric 	kdc_log(context, config, 0, "Inconsistent request.");
   2346  1.1     elric 	ret = KRB5KDC_ERR_SERVER_NOMATCH;
   2347  1.1     elric 	goto out;
   2348  1.1     elric     }
   2349  1.1     elric 
   2350  1.1     elric     /* check for valid set of addresses */
   2351  1.1     elric     if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
   2352  1.1     elric 	ret = KRB5KRB_AP_ERR_BADADDR;
   2353  1.1     elric 	kdc_log(context, config, 0, "Request from wrong address");
   2354  1.1     elric 	goto out;
   2355  1.1     elric     }
   2356  1.2  christos 
   2357  1.3  christos     /* check local and per-principal anonymous ticket issuance policy */
   2358  1.3  christos     if (is_anon_tgs_request_p(b, tgt)) {
   2359  1.3  christos 	ret = _kdc_check_anon_policy(context, config, client, server);
   2360  1.3  christos 	if (ret)
   2361  1.3  christos 	    goto out;
   2362  1.3  christos     }
   2363  1.3  christos 
   2364  1.1     elric     /*
   2365  1.1     elric      * If this is an referral, add server referral data to the
   2366  1.1     elric      * auth_data reply .
   2367  1.1     elric      */
   2368  1.1     elric     if (ref_realm) {
   2369  1.1     elric 	PA_DATA pa;
   2370  1.1     elric 	krb5_crypto crypto;
   2371  1.1     elric 
   2372  1.1     elric 	kdc_log(context, config, 0,
   2373  1.1     elric 		"Adding server referral to %s", ref_realm);
   2374  1.1     elric 
   2375  1.1     elric 	ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
   2376  1.1     elric 	if (ret)
   2377  1.1     elric 	    goto out;
   2378  1.1     elric 
   2379  1.1     elric 	ret = build_server_referral(context, config, crypto, ref_realm,
   2380  1.1     elric 				    NULL, s, &pa.padata_value);
   2381  1.1     elric 	krb5_crypto_destroy(context, crypto);
   2382  1.1     elric 	if (ret) {
   2383  1.1     elric 	    kdc_log(context, config, 0,
   2384  1.1     elric 		    "Failed building server referral");
   2385  1.1     elric 	    goto out;
   2386  1.1     elric 	}
   2387  1.1     elric 	pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
   2388  1.1     elric 
   2389  1.1     elric 	ret = add_METHOD_DATA(&enc_pa_data, &pa);
   2390  1.1     elric 	krb5_data_free(&pa.padata_value);
   2391  1.1     elric 	if (ret) {
   2392  1.1     elric 	    kdc_log(context, config, 0,
   2393  1.1     elric 		    "Add server referral METHOD-DATA failed");
   2394  1.1     elric 	    goto out;
   2395  1.1     elric 	}
   2396  1.1     elric     }
   2397  1.1     elric 
   2398  1.1     elric     /*
   2399  1.1     elric      *
   2400  1.1     elric      */
   2401  1.1     elric 
   2402  1.1     elric     ret = tgs_make_reply(context,
   2403  1.1     elric 			 config,
   2404  1.1     elric 			 b,
   2405  1.2  christos 			 tp,
   2406  1.1     elric 			 tgt,
   2407  1.1     elric 			 replykey,
   2408  1.1     elric 			 rk_is_subkey,
   2409  1.1     elric 			 ekey,
   2410  1.1     elric 			 &sessionkey,
   2411  1.1     elric 			 kvno,
   2412  1.1     elric 			 *auth_data,
   2413  1.1     elric 			 server,
   2414  1.2  christos 			 rsp,
   2415  1.1     elric 			 spn,
   2416  1.1     elric 			 client,
   2417  1.1     elric 			 cp,
   2418  1.3  christos                          tgt_realm,
   2419  1.1     elric 			 krbtgt_out,
   2420  1.2  christos 			 tkey_sign->key.keytype,
   2421  1.1     elric 			 spp,
   2422  1.1     elric 			 &rspac,
   2423  1.1     elric 			 &enc_pa_data,
   2424  1.1     elric 			 e_text,
   2425  1.1     elric 			 reply);
   2426  1.2  christos 
   2427  1.1     elric out:
   2428  1.2  christos     if (tpn != cpn)
   2429  1.2  christos 	    free(tpn);
   2430  1.1     elric     free(spn);
   2431  1.1     elric     free(cpn);
   2432  1.2  christos     free(dpn);
   2433  1.2  christos     free(krbtgt_out_n);
   2434  1.2  christos     _krb5_free_capath(context, capath);
   2435  1.2  christos 
   2436  1.1     elric     krb5_data_free(&rspac);
   2437  1.1     elric     krb5_free_keyblock_contents(context, &sessionkey);
   2438  1.1     elric     if(krbtgt_out)
   2439  1.1     elric 	_kdc_free_ent(context, krbtgt_out);
   2440  1.1     elric     if(server)
   2441  1.1     elric 	_kdc_free_ent(context, server);
   2442  1.1     elric     if(client)
   2443  1.1     elric 	_kdc_free_ent(context, client);
   2444  1.1     elric     if(s4u2self_impersonated_client)
   2445  1.1     elric 	_kdc_free_ent(context, s4u2self_impersonated_client);
   2446  1.1     elric 
   2447  1.2  christos     if (tp && tp != cp)
   2448  1.2  christos 	krb5_free_principal(context, tp);
   2449  1.2  christos     krb5_free_principal(context, cp);
   2450  1.2  christos     krb5_free_principal(context, dp);
   2451  1.2  christos     krb5_free_principal(context, sp);
   2452  1.2  christos     krb5_free_principal(context, krbtgt_out_principal);
   2453  1.2  christos     free(ref_realm);
   2454  1.1     elric     free_METHOD_DATA(&enc_pa_data);
   2455  1.1     elric 
   2456  1.1     elric     free_EncTicketPart(&adtkt);
   2457  1.1     elric 
   2458  1.1     elric     return ret;
   2459  1.1     elric }
   2460  1.1     elric 
   2461  1.1     elric /*
   2462  1.1     elric  *
   2463  1.1     elric  */
   2464  1.1     elric 
   2465  1.1     elric krb5_error_code
   2466  1.1     elric _kdc_tgs_rep(krb5_context context,
   2467  1.1     elric 	     krb5_kdc_configuration *config,
   2468  1.1     elric 	     KDC_REQ *req,
   2469  1.1     elric 	     krb5_data *data,
   2470  1.1     elric 	     const char *from,
   2471  1.1     elric 	     struct sockaddr *from_addr,
   2472  1.1     elric 	     int datagram_reply)
   2473  1.1     elric {
   2474  1.1     elric     AuthorizationData *auth_data = NULL;
   2475  1.1     elric     krb5_error_code ret;
   2476  1.1     elric     int i = 0;
   2477  1.1     elric     const PA_DATA *tgs_req;
   2478  1.1     elric 
   2479  1.1     elric     hdb_entry_ex *krbtgt = NULL;
   2480  1.1     elric     krb5_ticket *ticket = NULL;
   2481  1.1     elric     const char *e_text = NULL;
   2482  1.1     elric     krb5_enctype krbtgt_etype = ETYPE_NULL;
   2483  1.1     elric 
   2484  1.1     elric     krb5_keyblock *replykey = NULL;
   2485  1.1     elric     int rk_is_subkey = 0;
   2486  1.1     elric     time_t *csec = NULL;
   2487  1.1     elric     int *cusec = NULL;
   2488  1.1     elric 
   2489  1.1     elric     if(req->padata == NULL){
   2490  1.1     elric 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
   2491  1.1     elric 	kdc_log(context, config, 0,
   2492  1.1     elric 		"TGS-REQ from %s without PA-DATA", from);
   2493  1.1     elric 	goto out;
   2494  1.1     elric     }
   2495  1.1     elric 
   2496  1.1     elric     tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
   2497  1.1     elric 
   2498  1.1     elric     if(tgs_req == NULL){
   2499  1.1     elric 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
   2500  1.2  christos 
   2501  1.1     elric 	kdc_log(context, config, 0,
   2502  1.1     elric 		"TGS-REQ from %s without PA-TGS-REQ", from);
   2503  1.1     elric 	goto out;
   2504  1.1     elric     }
   2505  1.1     elric     ret = tgs_parse_request(context, config,
   2506  1.1     elric 			    &req->req_body, tgs_req,
   2507  1.1     elric 			    &krbtgt,
   2508  1.1     elric 			    &krbtgt_etype,
   2509  1.1     elric 			    &ticket,
   2510  1.1     elric 			    &e_text,
   2511  1.1     elric 			    from, from_addr,
   2512  1.1     elric 			    &csec, &cusec,
   2513  1.1     elric 			    &auth_data,
   2514  1.1     elric 			    &replykey,
   2515  1.1     elric 			    &rk_is_subkey);
   2516  1.1     elric     if (ret == HDB_ERR_NOT_FOUND_HERE) {
   2517  1.1     elric 	/* kdc_log() is called in tgs_parse_request() */
   2518  1.1     elric 	goto out;
   2519  1.1     elric     }
   2520  1.1     elric     if (ret) {
   2521  1.1     elric 	kdc_log(context, config, 0,
   2522  1.1     elric 		"Failed parsing TGS-REQ from %s", from);
   2523  1.1     elric 	goto out;
   2524  1.1     elric     }
   2525  1.1     elric 
   2526  1.2  christos     {
   2527  1.2  christos 	const PA_DATA *pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
   2528  1.2  christos 	if (pa)
   2529  1.2  christos 	    kdc_log(context, config, 10, "Got TGS FAST request");
   2530  1.2  christos     }
   2531  1.2  christos 
   2532  1.2  christos 
   2533  1.1     elric     ret = tgs_build_reply(context,
   2534  1.1     elric 			  config,
   2535  1.1     elric 			  req,
   2536  1.1     elric 			  &req->req_body,
   2537  1.1     elric 			  krbtgt,
   2538  1.1     elric 			  krbtgt_etype,
   2539  1.1     elric 			  replykey,
   2540  1.1     elric 			  rk_is_subkey,
   2541  1.1     elric 			  ticket,
   2542  1.1     elric 			  data,
   2543  1.1     elric 			  from,
   2544  1.1     elric 			  &e_text,
   2545  1.1     elric 			  &auth_data,
   2546  1.1     elric 			  from_addr);
   2547  1.1     elric     if (ret) {
   2548  1.1     elric 	kdc_log(context, config, 0,
   2549  1.1     elric 		"Failed building TGS-REP to %s", from);
   2550  1.1     elric 	goto out;
   2551  1.1     elric     }
   2552  1.1     elric 
   2553  1.1     elric     /* */
   2554  1.1     elric     if (datagram_reply && data->length > config->max_datagram_reply_length) {
   2555  1.1     elric 	krb5_data_free(data);
   2556  1.1     elric 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
   2557  1.1     elric 	e_text = "Reply packet too large";
   2558  1.1     elric     }
   2559  1.1     elric 
   2560  1.1     elric out:
   2561  1.1     elric     if (replykey)
   2562  1.1     elric 	krb5_free_keyblock(context, replykey);
   2563  1.2  christos 
   2564  1.1     elric     if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
   2565  1.2  christos 	/* XXX add fast wrapping on the error */
   2566  1.2  christos 	METHOD_DATA error_method = { 0, NULL };
   2567  1.2  christos 
   2568  1.2  christos 
   2569  1.2  christos 	kdc_log(context, config, 10, "tgs-req: sending error: %d to client", ret);
   2570  1.2  christos 	ret = _kdc_fast_mk_error(context, NULL,
   2571  1.2  christos 				 &error_method,
   2572  1.2  christos 				 NULL,
   2573  1.2  christos 				 NULL,
   2574  1.2  christos 				 ret, NULL,
   2575  1.2  christos 				 NULL,
   2576  1.2  christos 				 NULL, NULL,
   2577  1.2  christos 				 csec, cusec,
   2578  1.2  christos 				 data);
   2579  1.2  christos 	free_METHOD_DATA(&error_method);
   2580  1.1     elric     }
   2581  1.1     elric     free(csec);
   2582  1.1     elric     free(cusec);
   2583  1.1     elric     if (ticket)
   2584  1.1     elric 	krb5_free_ticket(context, ticket);
   2585  1.1     elric     if(krbtgt)
   2586  1.1     elric 	_kdc_free_ent(context, krbtgt);
   2587  1.1     elric 
   2588  1.1     elric     if (auth_data) {
   2589  1.1     elric 	free_AuthorizationData(auth_data);
   2590  1.1     elric 	free(auth_data);
   2591  1.1     elric     }
   2592  1.1     elric 
   2593  1.1     elric     return ret;
   2594  1.1     elric }
   2595