Home | History | Annotate | Line # | Download | only in kdc
krb5tgs.c revision 1.1
      1  1.1  elric /*	$NetBSD: krb5tgs.c,v 1.1 2011/04/13 18:14:37 elric 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.1  elric 
     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.1  elric 			krb5_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.1  elric     size_t size;
    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.1  elric 
    129  1.1  elric 	spd.client = 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.1  elric 
    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.1  elric 	ret = hdb_enctype2key(context, &krbtgt->entry, 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.1  elric 	size_t size;
    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.1  elric 	    ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
    232  1.1  elric 	    if (ret == 0)
    233  1.1  elric 		ret = krb5_crypto_init(context, &key->key, 0, &crypto);
    234  1.1  elric 	    if (ret) {
    235  1.1  elric 		free(data.data);
    236  1.1  elric 		free_KRB5SignedPath(&sp);
    237  1.1  elric 		return ret;
    238  1.1  elric 	    }
    239  1.1  elric 	}
    240  1.1  elric 	ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
    241  1.1  elric 				   data.data, data.length,
    242  1.1  elric 				   &sp.cksum);
    243  1.1  elric 	krb5_crypto_destroy(context, crypto);
    244  1.1  elric 	free(data.data);
    245  1.1  elric 	if (ret) {
    246  1.1  elric 	    free_KRB5SignedPath(&sp);
    247  1.1  elric 	    kdc_log(context, config, 5,
    248  1.1  elric 		    "KRB5SignedPath not signed correctly, not marking as signed");
    249  1.1  elric 	    return 0;
    250  1.1  elric 	}
    251  1.1  elric 
    252  1.1  elric 	if (delegated && sp.delegated) {
    253  1.1  elric 
    254  1.1  elric 	    *delegated = malloc(sizeof(*sp.delegated));
    255  1.1  elric 	    if (*delegated == NULL) {
    256  1.1  elric 		free_KRB5SignedPath(&sp);
    257  1.1  elric 		return ENOMEM;
    258  1.1  elric 	    }
    259  1.1  elric 
    260  1.1  elric 	    ret = copy_Principals(*delegated, sp.delegated);
    261  1.1  elric 	    if (ret) {
    262  1.1  elric 		free_KRB5SignedPath(&sp);
    263  1.1  elric 		free(*delegated);
    264  1.1  elric 		*delegated = NULL;
    265  1.1  elric 		return ret;
    266  1.1  elric 	    }
    267  1.1  elric 	}
    268  1.1  elric 	free_KRB5SignedPath(&sp);
    269  1.1  elric 
    270  1.1  elric 	*signedpath = 1;
    271  1.1  elric     }
    272  1.1  elric 
    273  1.1  elric     return 0;
    274  1.1  elric }
    275  1.1  elric 
    276  1.1  elric /*
    277  1.1  elric  *
    278  1.1  elric  */
    279  1.1  elric 
    280  1.1  elric static krb5_error_code
    281  1.1  elric check_PAC(krb5_context context,
    282  1.1  elric 	  krb5_kdc_configuration *config,
    283  1.1  elric 	  const krb5_principal client_principal,
    284  1.1  elric 	  hdb_entry_ex *client,
    285  1.1  elric 	  hdb_entry_ex *server,
    286  1.1  elric 	  hdb_entry_ex *krbtgt,
    287  1.1  elric 	  const EncryptionKey *server_key,
    288  1.1  elric 	  const EncryptionKey *krbtgt_check_key,
    289  1.1  elric 	  const EncryptionKey *krbtgt_sign_key,
    290  1.1  elric 	  EncTicketPart *tkt,
    291  1.1  elric 	  krb5_data *rspac,
    292  1.1  elric 	  int *signedpath)
    293  1.1  elric {
    294  1.1  elric     AuthorizationData *ad = tkt->authorization_data;
    295  1.1  elric     unsigned i, j;
    296  1.1  elric     krb5_error_code ret;
    297  1.1  elric 
    298  1.1  elric     if (ad == NULL || ad->len == 0)
    299  1.1  elric 	return 0;
    300  1.1  elric 
    301  1.1  elric     for (i = 0; i < ad->len; i++) {
    302  1.1  elric 	AuthorizationData child;
    303  1.1  elric 
    304  1.1  elric 	if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
    305  1.1  elric 	    continue;
    306  1.1  elric 
    307  1.1  elric 	ret = decode_AuthorizationData(ad->val[i].ad_data.data,
    308  1.1  elric 				       ad->val[i].ad_data.length,
    309  1.1  elric 				       &child,
    310  1.1  elric 				       NULL);
    311  1.1  elric 	if (ret) {
    312  1.1  elric 	    krb5_set_error_message(context, ret, "Failed to decode "
    313  1.1  elric 				   "IF_RELEVANT with %d", ret);
    314  1.1  elric 	    return ret;
    315  1.1  elric 	}
    316  1.1  elric 	for (j = 0; j < child.len; j++) {
    317  1.1  elric 
    318  1.1  elric 	    if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
    319  1.1  elric 		int signed_pac = 0;
    320  1.1  elric 		krb5_pac pac;
    321  1.1  elric 
    322  1.1  elric 		/* Found PAC */
    323  1.1  elric 		ret = krb5_pac_parse(context,
    324  1.1  elric 				     child.val[j].ad_data.data,
    325  1.1  elric 				     child.val[j].ad_data.length,
    326  1.1  elric 				     &pac);
    327  1.1  elric 		free_AuthorizationData(&child);
    328  1.1  elric 		if (ret)
    329  1.1  elric 		    return ret;
    330  1.1  elric 
    331  1.1  elric 		ret = krb5_pac_verify(context, pac, tkt->authtime,
    332  1.1  elric 				      client_principal,
    333  1.1  elric 				      krbtgt_check_key, NULL);
    334  1.1  elric 		if (ret) {
    335  1.1  elric 		    krb5_pac_free(context, pac);
    336  1.1  elric 		    return ret;
    337  1.1  elric 		}
    338  1.1  elric 
    339  1.1  elric 		ret = _kdc_pac_verify(context, client_principal,
    340  1.1  elric 				      client, server, krbtgt, &pac, &signed_pac);
    341  1.1  elric 		if (ret) {
    342  1.1  elric 		    krb5_pac_free(context, pac);
    343  1.1  elric 		    return ret;
    344  1.1  elric 		}
    345  1.1  elric 
    346  1.1  elric 		/*
    347  1.1  elric 		 * Only re-sign PAC if we could verify it with the PAC
    348  1.1  elric 		 * function. The no-verify case happens when we get in
    349  1.1  elric 		 * a PAC from cross realm from a Windows domain and
    350  1.1  elric 		 * that there is no PAC verification function.
    351  1.1  elric 		 */
    352  1.1  elric 		if (signed_pac) {
    353  1.1  elric 		    *signedpath = 1;
    354  1.1  elric 		    ret = _krb5_pac_sign(context, pac, tkt->authtime,
    355  1.1  elric 					 client_principal,
    356  1.1  elric 					 server_key, krbtgt_sign_key, rspac);
    357  1.1  elric 		}
    358  1.1  elric 		krb5_pac_free(context, pac);
    359  1.1  elric 
    360  1.1  elric 		return ret;
    361  1.1  elric 	    }
    362  1.1  elric 	}
    363  1.1  elric 	free_AuthorizationData(&child);
    364  1.1  elric     }
    365  1.1  elric     return 0;
    366  1.1  elric }
    367  1.1  elric 
    368  1.1  elric /*
    369  1.1  elric  *
    370  1.1  elric  */
    371  1.1  elric 
    372  1.1  elric static krb5_error_code
    373  1.1  elric check_tgs_flags(krb5_context context,
    374  1.1  elric 		krb5_kdc_configuration *config,
    375  1.1  elric 		KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
    376  1.1  elric {
    377  1.1  elric     KDCOptions f = b->kdc_options;
    378  1.1  elric 
    379  1.1  elric     if(f.validate){
    380  1.1  elric 	if(!tgt->flags.invalid || tgt->starttime == NULL){
    381  1.1  elric 	    kdc_log(context, config, 0,
    382  1.1  elric 		    "Bad request to validate ticket");
    383  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    384  1.1  elric 	}
    385  1.1  elric 	if(*tgt->starttime > kdc_time){
    386  1.1  elric 	    kdc_log(context, config, 0,
    387  1.1  elric 		    "Early request to validate ticket");
    388  1.1  elric 	    return KRB5KRB_AP_ERR_TKT_NYV;
    389  1.1  elric 	}
    390  1.1  elric 	/* XXX  tkt = tgt */
    391  1.1  elric 	et->flags.invalid = 0;
    392  1.1  elric     }else if(tgt->flags.invalid){
    393  1.1  elric 	kdc_log(context, config, 0,
    394  1.1  elric 		"Ticket-granting ticket has INVALID flag set");
    395  1.1  elric 	return KRB5KRB_AP_ERR_TKT_INVALID;
    396  1.1  elric     }
    397  1.1  elric 
    398  1.1  elric     if(f.forwardable){
    399  1.1  elric 	if(!tgt->flags.forwardable){
    400  1.1  elric 	    kdc_log(context, config, 0,
    401  1.1  elric 		    "Bad request for forwardable ticket");
    402  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    403  1.1  elric 	}
    404  1.1  elric 	et->flags.forwardable = 1;
    405  1.1  elric     }
    406  1.1  elric     if(f.forwarded){
    407  1.1  elric 	if(!tgt->flags.forwardable){
    408  1.1  elric 	    kdc_log(context, config, 0,
    409  1.1  elric 		    "Request to forward non-forwardable ticket");
    410  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    411  1.1  elric 	}
    412  1.1  elric 	et->flags.forwarded = 1;
    413  1.1  elric 	et->caddr = b->addresses;
    414  1.1  elric     }
    415  1.1  elric     if(tgt->flags.forwarded)
    416  1.1  elric 	et->flags.forwarded = 1;
    417  1.1  elric 
    418  1.1  elric     if(f.proxiable){
    419  1.1  elric 	if(!tgt->flags.proxiable){
    420  1.1  elric 	    kdc_log(context, config, 0,
    421  1.1  elric 		    "Bad request for proxiable ticket");
    422  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    423  1.1  elric 	}
    424  1.1  elric 	et->flags.proxiable = 1;
    425  1.1  elric     }
    426  1.1  elric     if(f.proxy){
    427  1.1  elric 	if(!tgt->flags.proxiable){
    428  1.1  elric 	    kdc_log(context, config, 0,
    429  1.1  elric 		    "Request to proxy non-proxiable ticket");
    430  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    431  1.1  elric 	}
    432  1.1  elric 	et->flags.proxy = 1;
    433  1.1  elric 	et->caddr = b->addresses;
    434  1.1  elric     }
    435  1.1  elric     if(tgt->flags.proxy)
    436  1.1  elric 	et->flags.proxy = 1;
    437  1.1  elric 
    438  1.1  elric     if(f.allow_postdate){
    439  1.1  elric 	if(!tgt->flags.may_postdate){
    440  1.1  elric 	    kdc_log(context, config, 0,
    441  1.1  elric 		    "Bad request for post-datable ticket");
    442  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    443  1.1  elric 	}
    444  1.1  elric 	et->flags.may_postdate = 1;
    445  1.1  elric     }
    446  1.1  elric     if(f.postdated){
    447  1.1  elric 	if(!tgt->flags.may_postdate){
    448  1.1  elric 	    kdc_log(context, config, 0,
    449  1.1  elric 		    "Bad request for postdated ticket");
    450  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    451  1.1  elric 	}
    452  1.1  elric 	if(b->from)
    453  1.1  elric 	    *et->starttime = *b->from;
    454  1.1  elric 	et->flags.postdated = 1;
    455  1.1  elric 	et->flags.invalid = 1;
    456  1.1  elric     }else if(b->from && *b->from > kdc_time + context->max_skew){
    457  1.1  elric 	kdc_log(context, config, 0, "Ticket cannot be postdated");
    458  1.1  elric 	return KRB5KDC_ERR_CANNOT_POSTDATE;
    459  1.1  elric     }
    460  1.1  elric 
    461  1.1  elric     if(f.renewable){
    462  1.1  elric 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
    463  1.1  elric 	    kdc_log(context, config, 0,
    464  1.1  elric 		    "Bad request for renewable ticket");
    465  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    466  1.1  elric 	}
    467  1.1  elric 	et->flags.renewable = 1;
    468  1.1  elric 	ALLOC(et->renew_till);
    469  1.1  elric 	_kdc_fix_time(&b->rtime);
    470  1.1  elric 	*et->renew_till = *b->rtime;
    471  1.1  elric     }
    472  1.1  elric     if(f.renew){
    473  1.1  elric 	time_t old_life;
    474  1.1  elric 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
    475  1.1  elric 	    kdc_log(context, config, 0,
    476  1.1  elric 		    "Request to renew non-renewable ticket");
    477  1.1  elric 	    return KRB5KDC_ERR_BADOPTION;
    478  1.1  elric 	}
    479  1.1  elric 	old_life = tgt->endtime;
    480  1.1  elric 	if(tgt->starttime)
    481  1.1  elric 	    old_life -= *tgt->starttime;
    482  1.1  elric 	else
    483  1.1  elric 	    old_life -= tgt->authtime;
    484  1.1  elric 	et->endtime = *et->starttime + old_life;
    485  1.1  elric 	if (et->renew_till != NULL)
    486  1.1  elric 	    et->endtime = min(*et->renew_till, et->endtime);
    487  1.1  elric     }
    488  1.1  elric 
    489  1.1  elric #if 0
    490  1.1  elric     /* checks for excess flags */
    491  1.1  elric     if(f.request_anonymous && !config->allow_anonymous){
    492  1.1  elric 	kdc_log(context, config, 0,
    493  1.1  elric 		"Request for anonymous ticket");
    494  1.1  elric 	return KRB5KDC_ERR_BADOPTION;
    495  1.1  elric     }
    496  1.1  elric #endif
    497  1.1  elric     return 0;
    498  1.1  elric }
    499  1.1  elric 
    500  1.1  elric /*
    501  1.1  elric  * Determine if constrained delegation is allowed from this client to this server
    502  1.1  elric  */
    503  1.1  elric 
    504  1.1  elric static krb5_error_code
    505  1.1  elric check_constrained_delegation(krb5_context context,
    506  1.1  elric 			     krb5_kdc_configuration *config,
    507  1.1  elric 			     HDB *clientdb,
    508  1.1  elric 			     hdb_entry_ex *client,
    509  1.1  elric 			     krb5_const_principal server)
    510  1.1  elric {
    511  1.1  elric     const HDB_Ext_Constrained_delegation_acl *acl;
    512  1.1  elric     krb5_error_code ret;
    513  1.1  elric     int i;
    514  1.1  elric 
    515  1.1  elric     /* if client delegates to itself, that ok */
    516  1.1  elric     if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
    517  1.1  elric 	return 0;
    518  1.1  elric 
    519  1.1  elric     if (clientdb->hdb_check_constrained_delegation) {
    520  1.1  elric 	ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, server);
    521  1.1  elric 	if (ret == 0)
    522  1.1  elric 	    return 0;
    523  1.1  elric     } else {
    524  1.1  elric 	ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
    525  1.1  elric 	if (ret) {
    526  1.1  elric 	    krb5_clear_error_message(context);
    527  1.1  elric 	    return ret;
    528  1.1  elric 	}
    529  1.1  elric 
    530  1.1  elric 	if (acl) {
    531  1.1  elric 	    for (i = 0; i < acl->len; i++) {
    532  1.1  elric 		if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
    533  1.1  elric 		    return 0;
    534  1.1  elric 	    }
    535  1.1  elric 	}
    536  1.1  elric 	ret = KRB5KDC_ERR_BADOPTION;
    537  1.1  elric     }
    538  1.1  elric     kdc_log(context, config, 0,
    539  1.1  elric 	    "Bad request for constrained delegation");
    540  1.1  elric     return ret;
    541  1.1  elric }
    542  1.1  elric 
    543  1.1  elric /*
    544  1.1  elric  * Determine if s4u2self is allowed from this client to this server
    545  1.1  elric  *
    546  1.1  elric  * For example, regardless of the principal being impersonated, if the
    547  1.1  elric  * 'client' and 'server' are the same, then it's safe.
    548  1.1  elric  */
    549  1.1  elric 
    550  1.1  elric static krb5_error_code
    551  1.1  elric check_s4u2self(krb5_context context,
    552  1.1  elric 	       krb5_kdc_configuration *config,
    553  1.1  elric 	       HDB *clientdb,
    554  1.1  elric 	       hdb_entry_ex *client,
    555  1.1  elric 	       krb5_const_principal server)
    556  1.1  elric {
    557  1.1  elric     krb5_error_code ret;
    558  1.1  elric 
    559  1.1  elric     /* if client does a s4u2self to itself, that ok */
    560  1.1  elric     if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
    561  1.1  elric 	return 0;
    562  1.1  elric 
    563  1.1  elric     if (clientdb->hdb_check_s4u2self) {
    564  1.1  elric 	ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server);
    565  1.1  elric 	if (ret == 0)
    566  1.1  elric 	    return 0;
    567  1.1  elric     } else {
    568  1.1  elric 	ret = KRB5KDC_ERR_BADOPTION;
    569  1.1  elric     }
    570  1.1  elric     return ret;
    571  1.1  elric }
    572  1.1  elric 
    573  1.1  elric /*
    574  1.1  elric  *
    575  1.1  elric  */
    576  1.1  elric 
    577  1.1  elric static krb5_error_code
    578  1.1  elric verify_flags (krb5_context context,
    579  1.1  elric 	      krb5_kdc_configuration *config,
    580  1.1  elric 	      const EncTicketPart *et,
    581  1.1  elric 	      const char *pstr)
    582  1.1  elric {
    583  1.1  elric     if(et->endtime < kdc_time){
    584  1.1  elric 	kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
    585  1.1  elric 	return KRB5KRB_AP_ERR_TKT_EXPIRED;
    586  1.1  elric     }
    587  1.1  elric     if(et->flags.invalid){
    588  1.1  elric 	kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
    589  1.1  elric 	return KRB5KRB_AP_ERR_TKT_NYV;
    590  1.1  elric     }
    591  1.1  elric     return 0;
    592  1.1  elric }
    593  1.1  elric 
    594  1.1  elric /*
    595  1.1  elric  *
    596  1.1  elric  */
    597  1.1  elric 
    598  1.1  elric static krb5_error_code
    599  1.1  elric fix_transited_encoding(krb5_context context,
    600  1.1  elric 		       krb5_kdc_configuration *config,
    601  1.1  elric 		       krb5_boolean check_policy,
    602  1.1  elric 		       const TransitedEncoding *tr,
    603  1.1  elric 		       EncTicketPart *et,
    604  1.1  elric 		       const char *client_realm,
    605  1.1  elric 		       const char *server_realm,
    606  1.1  elric 		       const char *tgt_realm)
    607  1.1  elric {
    608  1.1  elric     krb5_error_code ret = 0;
    609  1.1  elric     char **realms, **tmp;
    610  1.1  elric     unsigned int num_realms;
    611  1.1  elric     int i;
    612  1.1  elric 
    613  1.1  elric     switch (tr->tr_type) {
    614  1.1  elric     case DOMAIN_X500_COMPRESS:
    615  1.1  elric 	break;
    616  1.1  elric     case 0:
    617  1.1  elric 	/*
    618  1.1  elric 	 * Allow empty content of type 0 because that is was Microsoft
    619  1.1  elric 	 * generates in their TGT.
    620  1.1  elric 	 */
    621  1.1  elric 	if (tr->contents.length == 0)
    622  1.1  elric 	    break;
    623  1.1  elric 	kdc_log(context, config, 0,
    624  1.1  elric 		"Transited type 0 with non empty content");
    625  1.1  elric 	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    626  1.1  elric     default:
    627  1.1  elric 	kdc_log(context, config, 0,
    628  1.1  elric 		"Unknown transited type: %u", tr->tr_type);
    629  1.1  elric 	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    630  1.1  elric     }
    631  1.1  elric 
    632  1.1  elric     ret = krb5_domain_x500_decode(context,
    633  1.1  elric 				  tr->contents,
    634  1.1  elric 				  &realms,
    635  1.1  elric 				  &num_realms,
    636  1.1  elric 				  client_realm,
    637  1.1  elric 				  server_realm);
    638  1.1  elric     if(ret){
    639  1.1  elric 	krb5_warn(context, ret,
    640  1.1  elric 		  "Decoding transited encoding");
    641  1.1  elric 	return ret;
    642  1.1  elric     }
    643  1.1  elric     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
    644  1.1  elric 	/* not us, so add the previous realm to transited set */
    645  1.1  elric 	if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
    646  1.1  elric 	    ret = ERANGE;
    647  1.1  elric 	    goto free_realms;
    648  1.1  elric 	}
    649  1.1  elric 	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
    650  1.1  elric 	if(tmp == NULL){
    651  1.1  elric 	    ret = ENOMEM;
    652  1.1  elric 	    goto free_realms;
    653  1.1  elric 	}
    654  1.1  elric 	realms = tmp;
    655  1.1  elric 	realms[num_realms] = strdup(tgt_realm);
    656  1.1  elric 	if(realms[num_realms] == NULL){
    657  1.1  elric 	    ret = ENOMEM;
    658  1.1  elric 	    goto free_realms;
    659  1.1  elric 	}
    660  1.1  elric 	num_realms++;
    661  1.1  elric     }
    662  1.1  elric     if(num_realms == 0) {
    663  1.1  elric 	if(strcmp(client_realm, server_realm))
    664  1.1  elric 	    kdc_log(context, config, 0,
    665  1.1  elric 		    "cross-realm %s -> %s", client_realm, server_realm);
    666  1.1  elric     } else {
    667  1.1  elric 	size_t l = 0;
    668  1.1  elric 	char *rs;
    669  1.1  elric 	for(i = 0; i < num_realms; i++)
    670  1.1  elric 	    l += strlen(realms[i]) + 2;
    671  1.1  elric 	rs = malloc(l);
    672  1.1  elric 	if(rs != NULL) {
    673  1.1  elric 	    *rs = '\0';
    674  1.1  elric 	    for(i = 0; i < num_realms; i++) {
    675  1.1  elric 		if(i > 0)
    676  1.1  elric 		    strlcat(rs, ", ", l);
    677  1.1  elric 		strlcat(rs, realms[i], l);
    678  1.1  elric 	    }
    679  1.1  elric 	    kdc_log(context, config, 0,
    680  1.1  elric 		    "cross-realm %s -> %s via [%s]",
    681  1.1  elric 		    client_realm, server_realm, rs);
    682  1.1  elric 	    free(rs);
    683  1.1  elric 	}
    684  1.1  elric     }
    685  1.1  elric     if(check_policy) {
    686  1.1  elric 	ret = krb5_check_transited(context, client_realm,
    687  1.1  elric 				   server_realm,
    688  1.1  elric 				   realms, num_realms, NULL);
    689  1.1  elric 	if(ret) {
    690  1.1  elric 	    krb5_warn(context, ret, "cross-realm %s -> %s",
    691  1.1  elric 		      client_realm, server_realm);
    692  1.1  elric 	    goto free_realms;
    693  1.1  elric 	}
    694  1.1  elric 	et->flags.transited_policy_checked = 1;
    695  1.1  elric     }
    696  1.1  elric     et->transited.tr_type = DOMAIN_X500_COMPRESS;
    697  1.1  elric     ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
    698  1.1  elric     if(ret)
    699  1.1  elric 	krb5_warn(context, ret, "Encoding transited encoding");
    700  1.1  elric   free_realms:
    701  1.1  elric     for(i = 0; i < num_realms; i++)
    702  1.1  elric 	free(realms[i]);
    703  1.1  elric     free(realms);
    704  1.1  elric     return ret;
    705  1.1  elric }
    706  1.1  elric 
    707  1.1  elric 
    708  1.1  elric static krb5_error_code
    709  1.1  elric tgs_make_reply(krb5_context context,
    710  1.1  elric 	       krb5_kdc_configuration *config,
    711  1.1  elric 	       KDC_REQ_BODY *b,
    712  1.1  elric 	       krb5_const_principal tgt_name,
    713  1.1  elric 	       const EncTicketPart *tgt,
    714  1.1  elric 	       const krb5_keyblock *replykey,
    715  1.1  elric 	       int rk_is_subkey,
    716  1.1  elric 	       const EncryptionKey *serverkey,
    717  1.1  elric 	       const krb5_keyblock *sessionkey,
    718  1.1  elric 	       krb5_kvno kvno,
    719  1.1  elric 	       AuthorizationData *auth_data,
    720  1.1  elric 	       hdb_entry_ex *server,
    721  1.1  elric 	       krb5_principal server_principal,
    722  1.1  elric 	       const char *server_name,
    723  1.1  elric 	       hdb_entry_ex *client,
    724  1.1  elric 	       krb5_principal client_principal,
    725  1.1  elric 	       hdb_entry_ex *krbtgt,
    726  1.1  elric 	       krb5_enctype krbtgt_etype,
    727  1.1  elric 	       krb5_principals spp,
    728  1.1  elric 	       const krb5_data *rspac,
    729  1.1  elric 	       const METHOD_DATA *enc_pa_data,
    730  1.1  elric 	       const char **e_text,
    731  1.1  elric 	       krb5_data *reply)
    732  1.1  elric {
    733  1.1  elric     KDC_REP rep;
    734  1.1  elric     EncKDCRepPart ek;
    735  1.1  elric     EncTicketPart et;
    736  1.1  elric     KDCOptions f = b->kdc_options;
    737  1.1  elric     krb5_error_code ret;
    738  1.1  elric     int is_weak = 0;
    739  1.1  elric 
    740  1.1  elric     memset(&rep, 0, sizeof(rep));
    741  1.1  elric     memset(&et, 0, sizeof(et));
    742  1.1  elric     memset(&ek, 0, sizeof(ek));
    743  1.1  elric 
    744  1.1  elric     rep.pvno = 5;
    745  1.1  elric     rep.msg_type = krb_tgs_rep;
    746  1.1  elric 
    747  1.1  elric     et.authtime = tgt->authtime;
    748  1.1  elric     _kdc_fix_time(&b->till);
    749  1.1  elric     et.endtime = min(tgt->endtime, *b->till);
    750  1.1  elric     ALLOC(et.starttime);
    751  1.1  elric     *et.starttime = kdc_time;
    752  1.1  elric 
    753  1.1  elric     ret = check_tgs_flags(context, config, b, tgt, &et);
    754  1.1  elric     if(ret)
    755  1.1  elric 	goto out;
    756  1.1  elric 
    757  1.1  elric     /* We should check the transited encoding if:
    758  1.1  elric        1) the request doesn't ask not to be checked
    759  1.1  elric        2) globally enforcing a check
    760  1.1  elric        3) principal requires checking
    761  1.1  elric        4) we allow non-check per-principal, but principal isn't marked as allowing this
    762  1.1  elric        5) we don't globally allow this
    763  1.1  elric     */
    764  1.1  elric 
    765  1.1  elric #define GLOBAL_FORCE_TRANSITED_CHECK		\
    766  1.1  elric     (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
    767  1.1  elric #define GLOBAL_ALLOW_PER_PRINCIPAL			\
    768  1.1  elric     (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
    769  1.1  elric #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK			\
    770  1.1  elric     (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
    771  1.1  elric 
    772  1.1  elric /* these will consult the database in future release */
    773  1.1  elric #define PRINCIPAL_FORCE_TRANSITED_CHECK(P)		0
    774  1.1  elric #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)	0
    775  1.1  elric 
    776  1.1  elric     ret = fix_transited_encoding(context, config,
    777  1.1  elric 				 !f.disable_transited_check ||
    778  1.1  elric 				 GLOBAL_FORCE_TRANSITED_CHECK ||
    779  1.1  elric 				 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
    780  1.1  elric 				 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
    781  1.1  elric 				    PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
    782  1.1  elric 				   GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
    783  1.1  elric 				 &tgt->transited, &et,
    784  1.1  elric 				 krb5_principal_get_realm(context, client_principal),
    785  1.1  elric 				 krb5_principal_get_realm(context, server->entry.principal),
    786  1.1  elric 				 krb5_principal_get_realm(context, krbtgt->entry.principal));
    787  1.1  elric     if(ret)
    788  1.1  elric 	goto out;
    789  1.1  elric 
    790  1.1  elric     copy_Realm(&server_principal->realm, &rep.ticket.realm);
    791  1.1  elric     _krb5_principal2principalname(&rep.ticket.sname, server_principal);
    792  1.1  elric     copy_Realm(&tgt_name->realm, &rep.crealm);
    793  1.1  elric /*
    794  1.1  elric     if (f.request_anonymous)
    795  1.1  elric 	_kdc_make_anonymous_principalname (&rep.cname);
    796  1.1  elric     else */
    797  1.1  elric 
    798  1.1  elric     copy_PrincipalName(&tgt_name->name, &rep.cname);
    799  1.1  elric     rep.ticket.tkt_vno = 5;
    800  1.1  elric 
    801  1.1  elric     ek.caddr = et.caddr;
    802  1.1  elric     if(et.caddr == NULL)
    803  1.1  elric 	et.caddr = tgt->caddr;
    804  1.1  elric 
    805  1.1  elric     {
    806  1.1  elric 	time_t life;
    807  1.1  elric 	life = et.endtime - *et.starttime;
    808  1.1  elric 	if(client && client->entry.max_life)
    809  1.1  elric 	    life = min(life, *client->entry.max_life);
    810  1.1  elric 	if(server->entry.max_life)
    811  1.1  elric 	    life = min(life, *server->entry.max_life);
    812  1.1  elric 	et.endtime = *et.starttime + life;
    813  1.1  elric     }
    814  1.1  elric     if(f.renewable_ok && tgt->flags.renewable &&
    815  1.1  elric        et.renew_till == NULL && et.endtime < *b->till &&
    816  1.1  elric        tgt->renew_till != NULL)
    817  1.1  elric     {
    818  1.1  elric 	et.flags.renewable = 1;
    819  1.1  elric 	ALLOC(et.renew_till);
    820  1.1  elric 	*et.renew_till = *b->till;
    821  1.1  elric     }
    822  1.1  elric     if(et.renew_till){
    823  1.1  elric 	time_t renew;
    824  1.1  elric 	renew = *et.renew_till - et.authtime;
    825  1.1  elric 	if(client && client->entry.max_renew)
    826  1.1  elric 	    renew = min(renew, *client->entry.max_renew);
    827  1.1  elric 	if(server->entry.max_renew)
    828  1.1  elric 	    renew = min(renew, *server->entry.max_renew);
    829  1.1  elric 	*et.renew_till = et.authtime + renew;
    830  1.1  elric     }
    831  1.1  elric 
    832  1.1  elric     if(et.renew_till){
    833  1.1  elric 	*et.renew_till = min(*et.renew_till, *tgt->renew_till);
    834  1.1  elric 	*et.starttime = min(*et.starttime, *et.renew_till);
    835  1.1  elric 	et.endtime = min(et.endtime, *et.renew_till);
    836  1.1  elric     }
    837  1.1  elric 
    838  1.1  elric     *et.starttime = min(*et.starttime, et.endtime);
    839  1.1  elric 
    840  1.1  elric     if(*et.starttime == et.endtime){
    841  1.1  elric 	ret = KRB5KDC_ERR_NEVER_VALID;
    842  1.1  elric 	goto out;
    843  1.1  elric     }
    844  1.1  elric     if(et.renew_till && et.endtime == *et.renew_till){
    845  1.1  elric 	free(et.renew_till);
    846  1.1  elric 	et.renew_till = NULL;
    847  1.1  elric 	et.flags.renewable = 0;
    848  1.1  elric     }
    849  1.1  elric 
    850  1.1  elric     et.flags.pre_authent = tgt->flags.pre_authent;
    851  1.1  elric     et.flags.hw_authent  = tgt->flags.hw_authent;
    852  1.1  elric     et.flags.anonymous   = tgt->flags.anonymous;
    853  1.1  elric     et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
    854  1.1  elric 
    855  1.1  elric     if(rspac->length) {
    856  1.1  elric 	/*
    857  1.1  elric 	 * No not need to filter out the any PAC from the
    858  1.1  elric 	 * auth_data since it's signed by the KDC.
    859  1.1  elric 	 */
    860  1.1  elric 	ret = _kdc_tkt_add_if_relevant_ad(context, &et,
    861  1.1  elric 					  KRB5_AUTHDATA_WIN2K_PAC, rspac);
    862  1.1  elric 	if (ret)
    863  1.1  elric 	    goto out;
    864  1.1  elric     }
    865  1.1  elric 
    866  1.1  elric     if (auth_data) {
    867  1.1  elric 	unsigned int i = 0;
    868  1.1  elric 
    869  1.1  elric 	/* XXX check authdata */
    870  1.1  elric 
    871  1.1  elric 	if (et.authorization_data == NULL) {
    872  1.1  elric 	    et.authorization_data = calloc(1, sizeof(*et.authorization_data));
    873  1.1  elric 	    if (et.authorization_data == NULL) {
    874  1.1  elric 		ret = ENOMEM;
    875  1.1  elric 		krb5_set_error_message(context, ret, "malloc: out of memory");
    876  1.1  elric 		goto out;
    877  1.1  elric 	    }
    878  1.1  elric 	}
    879  1.1  elric 	for(i = 0; i < auth_data->len ; i++) {
    880  1.1  elric 	    ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
    881  1.1  elric 	    if (ret) {
    882  1.1  elric 		krb5_set_error_message(context, ret, "malloc: out of memory");
    883  1.1  elric 		goto out;
    884  1.1  elric 	    }
    885  1.1  elric 	}
    886  1.1  elric 
    887  1.1  elric 	/* Filter out type KRB5SignedPath */
    888  1.1  elric 	ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
    889  1.1  elric 	if (ret == 0) {
    890  1.1  elric 	    if (et.authorization_data->len == 1) {
    891  1.1  elric 		free_AuthorizationData(et.authorization_data);
    892  1.1  elric 		free(et.authorization_data);
    893  1.1  elric 		et.authorization_data = NULL;
    894  1.1  elric 	    } else {
    895  1.1  elric 		AuthorizationData *ad = et.authorization_data;
    896  1.1  elric 		free_AuthorizationDataElement(&ad->val[ad->len - 1]);
    897  1.1  elric 		ad->len--;
    898  1.1  elric 	    }
    899  1.1  elric 	}
    900  1.1  elric     }
    901  1.1  elric 
    902  1.1  elric     ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
    903  1.1  elric     if (ret)
    904  1.1  elric 	goto out;
    905  1.1  elric     et.crealm = tgt->crealm;
    906  1.1  elric     et.cname = tgt_name->name;
    907  1.1  elric 
    908  1.1  elric     ek.key = et.key;
    909  1.1  elric     /* MIT must have at least one last_req */
    910  1.1  elric     ek.last_req.len = 1;
    911  1.1  elric     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
    912  1.1  elric     if (ek.last_req.val == NULL) {
    913  1.1  elric 	ret = ENOMEM;
    914  1.1  elric 	goto out;
    915  1.1  elric     }
    916  1.1  elric     ek.nonce = b->nonce;
    917  1.1  elric     ek.flags = et.flags;
    918  1.1  elric     ek.authtime = et.authtime;
    919  1.1  elric     ek.starttime = et.starttime;
    920  1.1  elric     ek.endtime = et.endtime;
    921  1.1  elric     ek.renew_till = et.renew_till;
    922  1.1  elric     ek.srealm = rep.ticket.realm;
    923  1.1  elric     ek.sname = rep.ticket.sname;
    924  1.1  elric 
    925  1.1  elric     _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
    926  1.1  elric 		       et.endtime, et.renew_till);
    927  1.1  elric 
    928  1.1  elric     /* Don't sign cross realm tickets, they can't be checked anyway */
    929  1.1  elric     {
    930  1.1  elric 	char *r = get_krbtgt_realm(&ek.sname);
    931  1.1  elric 
    932  1.1  elric 	if (r == NULL || strcmp(r, ek.srealm) == 0) {
    933  1.1  elric 	    ret = _kdc_add_KRB5SignedPath(context,
    934  1.1  elric 					  config,
    935  1.1  elric 					  krbtgt,
    936  1.1  elric 					  krbtgt_etype,
    937  1.1  elric 					  client_principal,
    938  1.1  elric 					  NULL,
    939  1.1  elric 					  spp,
    940  1.1  elric 					  &et);
    941  1.1  elric 	    if (ret)
    942  1.1  elric 		goto out;
    943  1.1  elric 	}
    944  1.1  elric     }
    945  1.1  elric 
    946  1.1  elric     if (enc_pa_data->len) {
    947  1.1  elric 	rep.padata = calloc(1, sizeof(*rep.padata));
    948  1.1  elric 	if (rep.padata == NULL) {
    949  1.1  elric 	    ret = ENOMEM;
    950  1.1  elric 	    goto out;
    951  1.1  elric 	}
    952  1.1  elric 	ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
    953  1.1  elric 	if (ret)
    954  1.1  elric 	    goto out;
    955  1.1  elric     }
    956  1.1  elric 
    957  1.1  elric     if (krb5_enctype_valid(context, et.key.keytype) != 0
    958  1.1  elric 	&& _kdc_is_weak_exception(server->entry.principal, et.key.keytype))
    959  1.1  elric     {
    960  1.1  elric 	krb5_enctype_enable(context, et.key.keytype);
    961  1.1  elric 	is_weak = 1;
    962  1.1  elric     }
    963  1.1  elric 
    964  1.1  elric 
    965  1.1  elric     /* It is somewhat unclear where the etype in the following
    966  1.1  elric        encryption should come from. What we have is a session
    967  1.1  elric        key in the passed tgt, and a list of preferred etypes
    968  1.1  elric        *for the new ticket*. Should we pick the best possible
    969  1.1  elric        etype, given the keytype in the tgt, or should we look
    970  1.1  elric        at the etype list here as well?  What if the tgt
    971  1.1  elric        session key is DES3 and we want a ticket with a (say)
    972  1.1  elric        CAST session key. Should the DES3 etype be added to the
    973  1.1  elric        etype list, even if we don't want a session key with
    974  1.1  elric        DES3? */
    975  1.1  elric     ret = _kdc_encode_reply(context, config,
    976  1.1  elric 			    &rep, &et, &ek, et.key.keytype,
    977  1.1  elric 			    kvno,
    978  1.1  elric 			    serverkey, 0, replykey, rk_is_subkey,
    979  1.1  elric 			    e_text, reply);
    980  1.1  elric     if (is_weak)
    981  1.1  elric 	krb5_enctype_disable(context, et.key.keytype);
    982  1.1  elric 
    983  1.1  elric out:
    984  1.1  elric     free_TGS_REP(&rep);
    985  1.1  elric     free_TransitedEncoding(&et.transited);
    986  1.1  elric     if(et.starttime)
    987  1.1  elric 	free(et.starttime);
    988  1.1  elric     if(et.renew_till)
    989  1.1  elric 	free(et.renew_till);
    990  1.1  elric     if(et.authorization_data) {
    991  1.1  elric 	free_AuthorizationData(et.authorization_data);
    992  1.1  elric 	free(et.authorization_data);
    993  1.1  elric     }
    994  1.1  elric     free_LastReq(&ek.last_req);
    995  1.1  elric     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
    996  1.1  elric     free_EncryptionKey(&et.key);
    997  1.1  elric     return ret;
    998  1.1  elric }
    999  1.1  elric 
   1000  1.1  elric static krb5_error_code
   1001  1.1  elric tgs_check_authenticator(krb5_context context,
   1002  1.1  elric 			krb5_kdc_configuration *config,
   1003  1.1  elric 	                krb5_auth_context ac,
   1004  1.1  elric 			KDC_REQ_BODY *b,
   1005  1.1  elric 			const char **e_text,
   1006  1.1  elric 			krb5_keyblock *key)
   1007  1.1  elric {
   1008  1.1  elric     krb5_authenticator auth;
   1009  1.1  elric     size_t len;
   1010  1.1  elric     unsigned char *buf;
   1011  1.1  elric     size_t buf_size;
   1012  1.1  elric     krb5_error_code ret;
   1013  1.1  elric     krb5_crypto crypto;
   1014  1.1  elric 
   1015  1.1  elric     krb5_auth_con_getauthenticator(context, ac, &auth);
   1016  1.1  elric     if(auth->cksum == NULL){
   1017  1.1  elric 	kdc_log(context, config, 0, "No authenticator in request");
   1018  1.1  elric 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
   1019  1.1  elric 	goto out;
   1020  1.1  elric     }
   1021  1.1  elric     /*
   1022  1.1  elric      * according to RFC1510 it doesn't need to be keyed,
   1023  1.1  elric      * but according to the latest draft it needs to.
   1024  1.1  elric      */
   1025  1.1  elric     if (
   1026  1.1  elric #if 0
   1027  1.1  elric !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
   1028  1.1  elric 	||
   1029  1.1  elric #endif
   1030  1.1  elric  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
   1031  1.1  elric 	kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
   1032  1.1  elric 		auth->cksum->cksumtype);
   1033  1.1  elric 	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
   1034  1.1  elric 	goto out;
   1035  1.1  elric     }
   1036  1.1  elric 
   1037  1.1  elric     /* XXX should not re-encode this */
   1038  1.1  elric     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
   1039  1.1  elric     if(ret){
   1040  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1041  1.1  elric 	kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
   1042  1.1  elric 	krb5_free_error_message(context, msg);
   1043  1.1  elric 	goto out;
   1044  1.1  elric     }
   1045  1.1  elric     if(buf_size != len) {
   1046  1.1  elric 	free(buf);
   1047  1.1  elric 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
   1048  1.1  elric 	*e_text = "KDC internal error";
   1049  1.1  elric 	ret = KRB5KRB_ERR_GENERIC;
   1050  1.1  elric 	goto out;
   1051  1.1  elric     }
   1052  1.1  elric     ret = krb5_crypto_init(context, key, 0, &crypto);
   1053  1.1  elric     if (ret) {
   1054  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1055  1.1  elric 	free(buf);
   1056  1.1  elric 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   1057  1.1  elric 	krb5_free_error_message(context, msg);
   1058  1.1  elric 	goto out;
   1059  1.1  elric     }
   1060  1.1  elric     ret = krb5_verify_checksum(context,
   1061  1.1  elric 			       crypto,
   1062  1.1  elric 			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
   1063  1.1  elric 			       buf,
   1064  1.1  elric 			       len,
   1065  1.1  elric 			       auth->cksum);
   1066  1.1  elric     free(buf);
   1067  1.1  elric     krb5_crypto_destroy(context, crypto);
   1068  1.1  elric     if(ret){
   1069  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1070  1.1  elric 	kdc_log(context, config, 0,
   1071  1.1  elric 		"Failed to verify authenticator checksum: %s", msg);
   1072  1.1  elric 	krb5_free_error_message(context, msg);
   1073  1.1  elric     }
   1074  1.1  elric out:
   1075  1.1  elric     free_Authenticator(auth);
   1076  1.1  elric     free(auth);
   1077  1.1  elric     return ret;
   1078  1.1  elric }
   1079  1.1  elric 
   1080  1.1  elric /*
   1081  1.1  elric  *
   1082  1.1  elric  */
   1083  1.1  elric 
   1084  1.1  elric static const char *
   1085  1.1  elric find_rpath(krb5_context context, Realm crealm, Realm srealm)
   1086  1.1  elric {
   1087  1.1  elric     const char *new_realm = krb5_config_get_string(context,
   1088  1.1  elric 						   NULL,
   1089  1.1  elric 						   "capaths",
   1090  1.1  elric 						   crealm,
   1091  1.1  elric 						   srealm,
   1092  1.1  elric 						   NULL);
   1093  1.1  elric     return new_realm;
   1094  1.1  elric }
   1095  1.1  elric 
   1096  1.1  elric 
   1097  1.1  elric static krb5_boolean
   1098  1.1  elric need_referral(krb5_context context, krb5_kdc_configuration *config,
   1099  1.1  elric 	      const KDCOptions * const options, krb5_principal server,
   1100  1.1  elric 	      krb5_realm **realms)
   1101  1.1  elric {
   1102  1.1  elric     const char *name;
   1103  1.1  elric 
   1104  1.1  elric     if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
   1105  1.1  elric 	return FALSE;
   1106  1.1  elric 
   1107  1.1  elric     if (server->name.name_string.len == 1)
   1108  1.1  elric 	name = server->name.name_string.val[0];
   1109  1.1  elric     else if (server->name.name_string.len > 1)
   1110  1.1  elric 	name = server->name.name_string.val[1];
   1111  1.1  elric     else
   1112  1.1  elric 	return FALSE;
   1113  1.1  elric 
   1114  1.1  elric     kdc_log(context, config, 0, "Searching referral for %s", name);
   1115  1.1  elric 
   1116  1.1  elric     return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
   1117  1.1  elric }
   1118  1.1  elric 
   1119  1.1  elric static krb5_error_code
   1120  1.1  elric tgs_parse_request(krb5_context context,
   1121  1.1  elric 		  krb5_kdc_configuration *config,
   1122  1.1  elric 		  KDC_REQ_BODY *b,
   1123  1.1  elric 		  const PA_DATA *tgs_req,
   1124  1.1  elric 		  hdb_entry_ex **krbtgt,
   1125  1.1  elric 		  krb5_enctype *krbtgt_etype,
   1126  1.1  elric 		  krb5_ticket **ticket,
   1127  1.1  elric 		  const char **e_text,
   1128  1.1  elric 		  const char *from,
   1129  1.1  elric 		  const struct sockaddr *from_addr,
   1130  1.1  elric 		  time_t **csec,
   1131  1.1  elric 		  int **cusec,
   1132  1.1  elric 		  AuthorizationData **auth_data,
   1133  1.1  elric 		  krb5_keyblock **replykey,
   1134  1.1  elric 		  int *rk_is_subkey)
   1135  1.1  elric {
   1136  1.1  elric     krb5_ap_req ap_req;
   1137  1.1  elric     krb5_error_code ret;
   1138  1.1  elric     krb5_principal princ;
   1139  1.1  elric     krb5_auth_context ac = NULL;
   1140  1.1  elric     krb5_flags ap_req_options;
   1141  1.1  elric     krb5_flags verify_ap_req_flags;
   1142  1.1  elric     krb5_crypto crypto;
   1143  1.1  elric     Key *tkey;
   1144  1.1  elric     krb5_keyblock *subkey = NULL;
   1145  1.1  elric     unsigned usage;
   1146  1.1  elric 
   1147  1.1  elric     *auth_data = NULL;
   1148  1.1  elric     *csec  = NULL;
   1149  1.1  elric     *cusec = NULL;
   1150  1.1  elric     *replykey = NULL;
   1151  1.1  elric 
   1152  1.1  elric     memset(&ap_req, 0, sizeof(ap_req));
   1153  1.1  elric     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
   1154  1.1  elric     if(ret){
   1155  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1156  1.1  elric 	kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
   1157  1.1  elric 	krb5_free_error_message(context, msg);
   1158  1.1  elric 	goto out;
   1159  1.1  elric     }
   1160  1.1  elric 
   1161  1.1  elric     if(!get_krbtgt_realm(&ap_req.ticket.sname)){
   1162  1.1  elric 	/* XXX check for ticket.sname == req.sname */
   1163  1.1  elric 	kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
   1164  1.1  elric 	ret = KRB5KDC_ERR_POLICY; /* ? */
   1165  1.1  elric 	goto out;
   1166  1.1  elric     }
   1167  1.1  elric 
   1168  1.1  elric     _krb5_principalname2krb5_principal(context,
   1169  1.1  elric 				       &princ,
   1170  1.1  elric 				       ap_req.ticket.sname,
   1171  1.1  elric 				       ap_req.ticket.realm);
   1172  1.1  elric 
   1173  1.1  elric     ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, ap_req.ticket.enc_part.kvno, NULL, krbtgt);
   1174  1.1  elric 
   1175  1.1  elric     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1176  1.1  elric 	char *p;
   1177  1.1  elric 	ret = krb5_unparse_name(context, princ, &p);
   1178  1.1  elric 	if (ret != 0)
   1179  1.1  elric 	    p = "<unparse_name failed>";
   1180  1.1  elric 	krb5_free_principal(context, princ);
   1181  1.1  elric 	kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p);
   1182  1.1  elric 	if (ret == 0)
   1183  1.1  elric 	    free(p);
   1184  1.1  elric 	ret = HDB_ERR_NOT_FOUND_HERE;
   1185  1.1  elric 	goto out;
   1186  1.1  elric     } else if(ret){
   1187  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1188  1.1  elric 	char *p;
   1189  1.1  elric 	ret = krb5_unparse_name(context, princ, &p);
   1190  1.1  elric 	if (ret != 0)
   1191  1.1  elric 	    p = "<unparse_name failed>";
   1192  1.1  elric 	krb5_free_principal(context, princ);
   1193  1.1  elric 	kdc_log(context, config, 0,
   1194  1.1  elric 		"Ticket-granting ticket not found in database: %s", msg);
   1195  1.1  elric 	krb5_free_error_message(context, msg);
   1196  1.1  elric 	if (ret == 0)
   1197  1.1  elric 	    free(p);
   1198  1.1  elric 	ret = KRB5KRB_AP_ERR_NOT_US;
   1199  1.1  elric 	goto out;
   1200  1.1  elric     }
   1201  1.1  elric 
   1202  1.1  elric     if(ap_req.ticket.enc_part.kvno &&
   1203  1.1  elric        *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
   1204  1.1  elric 	char *p;
   1205  1.1  elric 
   1206  1.1  elric 	ret = krb5_unparse_name (context, princ, &p);
   1207  1.1  elric 	krb5_free_principal(context, princ);
   1208  1.1  elric 	if (ret != 0)
   1209  1.1  elric 	    p = "<unparse_name failed>";
   1210  1.1  elric 	kdc_log(context, config, 0,
   1211  1.1  elric 		"Ticket kvno = %d, DB kvno = %d (%s)",
   1212  1.1  elric 		*ap_req.ticket.enc_part.kvno,
   1213  1.1  elric 		(*krbtgt)->entry.kvno,
   1214  1.1  elric 		p);
   1215  1.1  elric 	if (ret == 0)
   1216  1.1  elric 	    free (p);
   1217  1.1  elric 	ret = KRB5KRB_AP_ERR_BADKEYVER;
   1218  1.1  elric 	goto out;
   1219  1.1  elric     }
   1220  1.1  elric 
   1221  1.1  elric     *krbtgt_etype = ap_req.ticket.enc_part.etype;
   1222  1.1  elric 
   1223  1.1  elric     ret = hdb_enctype2key(context, &(*krbtgt)->entry,
   1224  1.1  elric 			  ap_req.ticket.enc_part.etype, &tkey);
   1225  1.1  elric     if(ret){
   1226  1.1  elric 	char *str = NULL, *p = NULL;
   1227  1.1  elric 
   1228  1.1  elric 	krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
   1229  1.1  elric 	krb5_unparse_name(context, princ, &p);
   1230  1.1  elric  	kdc_log(context, config, 0,
   1231  1.1  elric 		"No server key with enctype %s found for %s",
   1232  1.1  elric 		str ? str : "<unknown enctype>",
   1233  1.1  elric 		p ? p : "<unparse_name failed>");
   1234  1.1  elric 	free(str);
   1235  1.1  elric 	free(p);
   1236  1.1  elric 	ret = KRB5KRB_AP_ERR_BADKEYVER;
   1237  1.1  elric 	goto out;
   1238  1.1  elric     }
   1239  1.1  elric 
   1240  1.1  elric     if (b->kdc_options.validate)
   1241  1.1  elric 	verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
   1242  1.1  elric     else
   1243  1.1  elric 	verify_ap_req_flags = 0;
   1244  1.1  elric 
   1245  1.1  elric     ret = krb5_verify_ap_req2(context,
   1246  1.1  elric 			      &ac,
   1247  1.1  elric 			      &ap_req,
   1248  1.1  elric 			      princ,
   1249  1.1  elric 			      &tkey->key,
   1250  1.1  elric 			      verify_ap_req_flags,
   1251  1.1  elric 			      &ap_req_options,
   1252  1.1  elric 			      ticket,
   1253  1.1  elric 			      KRB5_KU_TGS_REQ_AUTH);
   1254  1.1  elric 
   1255  1.1  elric     krb5_free_principal(context, princ);
   1256  1.1  elric     if(ret) {
   1257  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1258  1.1  elric 	kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
   1259  1.1  elric 	krb5_free_error_message(context, msg);
   1260  1.1  elric 	goto out;
   1261  1.1  elric     }
   1262  1.1  elric 
   1263  1.1  elric     {
   1264  1.1  elric 	krb5_authenticator auth;
   1265  1.1  elric 
   1266  1.1  elric 	ret = krb5_auth_con_getauthenticator(context, ac, &auth);
   1267  1.1  elric 	if (ret == 0) {
   1268  1.1  elric 	    *csec   = malloc(sizeof(**csec));
   1269  1.1  elric 	    if (*csec == NULL) {
   1270  1.1  elric 		krb5_free_authenticator(context, &auth);
   1271  1.1  elric 		kdc_log(context, config, 0, "malloc failed");
   1272  1.1  elric 		goto out;
   1273  1.1  elric 	    }
   1274  1.1  elric 	    **csec  = auth->ctime;
   1275  1.1  elric 	    *cusec  = malloc(sizeof(**cusec));
   1276  1.1  elric 	    if (*cusec == NULL) {
   1277  1.1  elric 		krb5_free_authenticator(context, &auth);
   1278  1.1  elric 		kdc_log(context, config, 0, "malloc failed");
   1279  1.1  elric 		goto out;
   1280  1.1  elric 	    }
   1281  1.1  elric 	    **cusec  = auth->cusec;
   1282  1.1  elric 	    krb5_free_authenticator(context, &auth);
   1283  1.1  elric 	}
   1284  1.1  elric     }
   1285  1.1  elric 
   1286  1.1  elric     ret = tgs_check_authenticator(context, config,
   1287  1.1  elric 				  ac, b, e_text, &(*ticket)->ticket.key);
   1288  1.1  elric     if (ret) {
   1289  1.1  elric 	krb5_auth_con_free(context, ac);
   1290  1.1  elric 	goto out;
   1291  1.1  elric     }
   1292  1.1  elric 
   1293  1.1  elric     usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
   1294  1.1  elric     *rk_is_subkey = 1;
   1295  1.1  elric 
   1296  1.1  elric     ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
   1297  1.1  elric     if(ret){
   1298  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1299  1.1  elric 	krb5_auth_con_free(context, ac);
   1300  1.1  elric 	kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
   1301  1.1  elric 	krb5_free_error_message(context, msg);
   1302  1.1  elric 	goto out;
   1303  1.1  elric     }
   1304  1.1  elric     if(subkey == NULL){
   1305  1.1  elric 	usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
   1306  1.1  elric 	*rk_is_subkey = 0;
   1307  1.1  elric 
   1308  1.1  elric 	ret = krb5_auth_con_getkey(context, ac, &subkey);
   1309  1.1  elric 	if(ret) {
   1310  1.1  elric 	    const char *msg = krb5_get_error_message(context, ret);
   1311  1.1  elric 	    krb5_auth_con_free(context, ac);
   1312  1.1  elric 	    kdc_log(context, config, 0, "Failed to get session key: %s", msg);
   1313  1.1  elric 	    krb5_free_error_message(context, msg);
   1314  1.1  elric 	    goto out;
   1315  1.1  elric 	}
   1316  1.1  elric     }
   1317  1.1  elric     if(subkey == NULL){
   1318  1.1  elric 	krb5_auth_con_free(context, ac);
   1319  1.1  elric 	kdc_log(context, config, 0,
   1320  1.1  elric 		"Failed to get key for enc-authorization-data");
   1321  1.1  elric 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1322  1.1  elric 	goto out;
   1323  1.1  elric     }
   1324  1.1  elric 
   1325  1.1  elric     *replykey = subkey;
   1326  1.1  elric 
   1327  1.1  elric     if (b->enc_authorization_data) {
   1328  1.1  elric 	krb5_data ad;
   1329  1.1  elric 
   1330  1.1  elric 	ret = krb5_crypto_init(context, subkey, 0, &crypto);
   1331  1.1  elric 	if (ret) {
   1332  1.1  elric 	    const char *msg = krb5_get_error_message(context, ret);
   1333  1.1  elric 	    krb5_auth_con_free(context, ac);
   1334  1.1  elric 	    kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   1335  1.1  elric 	    krb5_free_error_message(context, msg);
   1336  1.1  elric 	    goto out;
   1337  1.1  elric 	}
   1338  1.1  elric 	ret = krb5_decrypt_EncryptedData (context,
   1339  1.1  elric 					  crypto,
   1340  1.1  elric 					  usage,
   1341  1.1  elric 					  b->enc_authorization_data,
   1342  1.1  elric 					  &ad);
   1343  1.1  elric 	krb5_crypto_destroy(context, crypto);
   1344  1.1  elric 	if(ret){
   1345  1.1  elric 	    krb5_auth_con_free(context, ac);
   1346  1.1  elric 	    kdc_log(context, config, 0,
   1347  1.1  elric 		    "Failed to decrypt enc-authorization-data");
   1348  1.1  elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1349  1.1  elric 	    goto out;
   1350  1.1  elric 	}
   1351  1.1  elric 	ALLOC(*auth_data);
   1352  1.1  elric 	if (*auth_data == NULL) {
   1353  1.1  elric 	    krb5_auth_con_free(context, ac);
   1354  1.1  elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1355  1.1  elric 	    goto out;
   1356  1.1  elric 	}
   1357  1.1  elric 	ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
   1358  1.1  elric 	if(ret){
   1359  1.1  elric 	    krb5_auth_con_free(context, ac);
   1360  1.1  elric 	    free(*auth_data);
   1361  1.1  elric 	    *auth_data = NULL;
   1362  1.1  elric 	    kdc_log(context, config, 0, "Failed to decode authorization data");
   1363  1.1  elric 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
   1364  1.1  elric 	    goto out;
   1365  1.1  elric 	}
   1366  1.1  elric     }
   1367  1.1  elric 
   1368  1.1  elric     krb5_auth_con_free(context, ac);
   1369  1.1  elric 
   1370  1.1  elric out:
   1371  1.1  elric     free_AP_REQ(&ap_req);
   1372  1.1  elric 
   1373  1.1  elric     return ret;
   1374  1.1  elric }
   1375  1.1  elric 
   1376  1.1  elric static krb5_error_code
   1377  1.1  elric build_server_referral(krb5_context context,
   1378  1.1  elric 		      krb5_kdc_configuration *config,
   1379  1.1  elric 		      krb5_crypto session,
   1380  1.1  elric 		      krb5_const_realm referred_realm,
   1381  1.1  elric 		      const PrincipalName *true_principal_name,
   1382  1.1  elric 		      const PrincipalName *requested_principal,
   1383  1.1  elric 		      krb5_data *outdata)
   1384  1.1  elric {
   1385  1.1  elric     PA_ServerReferralData ref;
   1386  1.1  elric     krb5_error_code ret;
   1387  1.1  elric     EncryptedData ed;
   1388  1.1  elric     krb5_data data;
   1389  1.1  elric     size_t size;
   1390  1.1  elric 
   1391  1.1  elric     memset(&ref, 0, sizeof(ref));
   1392  1.1  elric 
   1393  1.1  elric     if (referred_realm) {
   1394  1.1  elric 	ALLOC(ref.referred_realm);
   1395  1.1  elric 	if (ref.referred_realm == NULL)
   1396  1.1  elric 	    goto eout;
   1397  1.1  elric 	*ref.referred_realm = strdup(referred_realm);
   1398  1.1  elric 	if (*ref.referred_realm == NULL)
   1399  1.1  elric 	    goto eout;
   1400  1.1  elric     }
   1401  1.1  elric     if (true_principal_name) {
   1402  1.1  elric 	ALLOC(ref.true_principal_name);
   1403  1.1  elric 	if (ref.true_principal_name == NULL)
   1404  1.1  elric 	    goto eout;
   1405  1.1  elric 	ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
   1406  1.1  elric 	if (ret)
   1407  1.1  elric 	    goto eout;
   1408  1.1  elric     }
   1409  1.1  elric     if (requested_principal) {
   1410  1.1  elric 	ALLOC(ref.requested_principal_name);
   1411  1.1  elric 	if (ref.requested_principal_name == NULL)
   1412  1.1  elric 	    goto eout;
   1413  1.1  elric 	ret = copy_PrincipalName(requested_principal,
   1414  1.1  elric 				 ref.requested_principal_name);
   1415  1.1  elric 	if (ret)
   1416  1.1  elric 	    goto eout;
   1417  1.1  elric     }
   1418  1.1  elric 
   1419  1.1  elric     ASN1_MALLOC_ENCODE(PA_ServerReferralData,
   1420  1.1  elric 		       data.data, data.length,
   1421  1.1  elric 		       &ref, &size, ret);
   1422  1.1  elric     free_PA_ServerReferralData(&ref);
   1423  1.1  elric     if (ret)
   1424  1.1  elric 	return ret;
   1425  1.1  elric     if (data.length != size)
   1426  1.1  elric 	krb5_abortx(context, "internal asn.1 encoder error");
   1427  1.1  elric 
   1428  1.1  elric     ret = krb5_encrypt_EncryptedData(context, session,
   1429  1.1  elric 				     KRB5_KU_PA_SERVER_REFERRAL,
   1430  1.1  elric 				     data.data, data.length,
   1431  1.1  elric 				     0 /* kvno */, &ed);
   1432  1.1  elric     free(data.data);
   1433  1.1  elric     if (ret)
   1434  1.1  elric 	return ret;
   1435  1.1  elric 
   1436  1.1  elric     ASN1_MALLOC_ENCODE(EncryptedData,
   1437  1.1  elric 		       outdata->data, outdata->length,
   1438  1.1  elric 		       &ed, &size, ret);
   1439  1.1  elric     free_EncryptedData(&ed);
   1440  1.1  elric     if (ret)
   1441  1.1  elric 	return ret;
   1442  1.1  elric     if (outdata->length != size)
   1443  1.1  elric 	krb5_abortx(context, "internal asn.1 encoder error");
   1444  1.1  elric 
   1445  1.1  elric     return 0;
   1446  1.1  elric eout:
   1447  1.1  elric     free_PA_ServerReferralData(&ref);
   1448  1.1  elric     krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
   1449  1.1  elric     return ENOMEM;
   1450  1.1  elric }
   1451  1.1  elric 
   1452  1.1  elric static krb5_error_code
   1453  1.1  elric tgs_build_reply(krb5_context context,
   1454  1.1  elric 		krb5_kdc_configuration *config,
   1455  1.1  elric 		KDC_REQ *req,
   1456  1.1  elric 		KDC_REQ_BODY *b,
   1457  1.1  elric 		hdb_entry_ex *krbtgt,
   1458  1.1  elric 		krb5_enctype krbtgt_etype,
   1459  1.1  elric 		const krb5_keyblock *replykey,
   1460  1.1  elric 		int rk_is_subkey,
   1461  1.1  elric 		krb5_ticket *ticket,
   1462  1.1  elric 		krb5_data *reply,
   1463  1.1  elric 		const char *from,
   1464  1.1  elric 		const char **e_text,
   1465  1.1  elric 		AuthorizationData **auth_data,
   1466  1.1  elric 		const struct sockaddr *from_addr)
   1467  1.1  elric {
   1468  1.1  elric     krb5_error_code ret;
   1469  1.1  elric     krb5_principal cp = NULL, sp = NULL;
   1470  1.1  elric     krb5_principal client_principal = NULL;
   1471  1.1  elric     krb5_principal krbtgt_principal = NULL;
   1472  1.1  elric     char *spn = NULL, *cpn = NULL;
   1473  1.1  elric     hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
   1474  1.1  elric     HDB *clientdb, *s4u2self_impersonated_clientdb;
   1475  1.1  elric     krb5_realm ref_realm = NULL;
   1476  1.1  elric     EncTicketPart *tgt = &ticket->ticket;
   1477  1.1  elric     krb5_principals spp = NULL;
   1478  1.1  elric     const EncryptionKey *ekey;
   1479  1.1  elric     krb5_keyblock sessionkey;
   1480  1.1  elric     krb5_kvno kvno;
   1481  1.1  elric     krb5_data rspac;
   1482  1.1  elric 
   1483  1.1  elric     hdb_entry_ex *krbtgt_out = NULL;
   1484  1.1  elric 
   1485  1.1  elric     METHOD_DATA enc_pa_data;
   1486  1.1  elric 
   1487  1.1  elric     PrincipalName *s;
   1488  1.1  elric     Realm r;
   1489  1.1  elric     int nloop = 0;
   1490  1.1  elric     EncTicketPart adtkt;
   1491  1.1  elric     char opt_str[128];
   1492  1.1  elric     int signedpath = 0;
   1493  1.1  elric 
   1494  1.1  elric     Key *tkey_check;
   1495  1.1  elric     Key *tkey_sign;
   1496  1.1  elric 
   1497  1.1  elric     memset(&sessionkey, 0, sizeof(sessionkey));
   1498  1.1  elric     memset(&adtkt, 0, sizeof(adtkt));
   1499  1.1  elric     krb5_data_zero(&rspac);
   1500  1.1  elric     memset(&enc_pa_data, 0, sizeof(enc_pa_data));
   1501  1.1  elric 
   1502  1.1  elric     s = b->sname;
   1503  1.1  elric     r = b->realm;
   1504  1.1  elric 
   1505  1.1  elric     if(b->kdc_options.enc_tkt_in_skey){
   1506  1.1  elric 	Ticket *t;
   1507  1.1  elric 	hdb_entry_ex *uu;
   1508  1.1  elric 	krb5_principal p;
   1509  1.1  elric 	Key *uukey;
   1510  1.1  elric 
   1511  1.1  elric 	if(b->additional_tickets == NULL ||
   1512  1.1  elric 	   b->additional_tickets->len == 0){
   1513  1.1  elric 	    ret = KRB5KDC_ERR_BADOPTION; /* ? */
   1514  1.1  elric 	    kdc_log(context, config, 0,
   1515  1.1  elric 		    "No second ticket present in request");
   1516  1.1  elric 	    goto out;
   1517  1.1  elric 	}
   1518  1.1  elric 	t = &b->additional_tickets->val[0];
   1519  1.1  elric 	if(!get_krbtgt_realm(&t->sname)){
   1520  1.1  elric 	    kdc_log(context, config, 0,
   1521  1.1  elric 		    "Additional ticket is not a ticket-granting ticket");
   1522  1.1  elric 	    ret = KRB5KDC_ERR_POLICY;
   1523  1.1  elric 	    goto out;
   1524  1.1  elric 	}
   1525  1.1  elric 	_krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
   1526  1.1  elric 	ret = _kdc_db_fetch(context, config, p,
   1527  1.1  elric 			    HDB_F_GET_KRBTGT, t->enc_part.kvno,
   1528  1.1  elric 			    NULL, &uu);
   1529  1.1  elric 	krb5_free_principal(context, p);
   1530  1.1  elric 	if(ret){
   1531  1.1  elric 	    if (ret == HDB_ERR_NOENTRY)
   1532  1.1  elric 		ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
   1533  1.1  elric 	    goto out;
   1534  1.1  elric 	}
   1535  1.1  elric 	ret = hdb_enctype2key(context, &uu->entry,
   1536  1.1  elric 			      t->enc_part.etype, &uukey);
   1537  1.1  elric 	if(ret){
   1538  1.1  elric 	    _kdc_free_ent(context, uu);
   1539  1.1  elric 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
   1540  1.1  elric 	    goto out;
   1541  1.1  elric 	}
   1542  1.1  elric 	ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
   1543  1.1  elric 	_kdc_free_ent(context, uu);
   1544  1.1  elric 	if(ret)
   1545  1.1  elric 	    goto out;
   1546  1.1  elric 
   1547  1.1  elric 	ret = verify_flags(context, config, &adtkt, spn);
   1548  1.1  elric 	if (ret)
   1549  1.1  elric 	    goto out;
   1550  1.1  elric 
   1551  1.1  elric 	s = &adtkt.cname;
   1552  1.1  elric 	r = adtkt.crealm;
   1553  1.1  elric     }
   1554  1.1  elric 
   1555  1.1  elric     _krb5_principalname2krb5_principal(context, &sp, *s, r);
   1556  1.1  elric     ret = krb5_unparse_name(context, sp, &spn);
   1557  1.1  elric     if (ret)
   1558  1.1  elric 	goto out;
   1559  1.1  elric     _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
   1560  1.1  elric     ret = krb5_unparse_name(context, cp, &cpn);
   1561  1.1  elric     if (ret)
   1562  1.1  elric 	goto out;
   1563  1.1  elric     unparse_flags (KDCOptions2int(b->kdc_options),
   1564  1.1  elric 		   asn1_KDCOptions_units(),
   1565  1.1  elric 		   opt_str, sizeof(opt_str));
   1566  1.1  elric     if(*opt_str)
   1567  1.1  elric 	kdc_log(context, config, 0,
   1568  1.1  elric 		"TGS-REQ %s from %s for %s [%s]",
   1569  1.1  elric 		cpn, from, spn, opt_str);
   1570  1.1  elric     else
   1571  1.1  elric 	kdc_log(context, config, 0,
   1572  1.1  elric 		"TGS-REQ %s from %s for %s", cpn, from, spn);
   1573  1.1  elric 
   1574  1.1  elric     /*
   1575  1.1  elric      * Fetch server
   1576  1.1  elric      */
   1577  1.1  elric 
   1578  1.1  elric server_lookup:
   1579  1.1  elric     ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
   1580  1.1  elric 			NULL, NULL, &server);
   1581  1.1  elric 
   1582  1.1  elric     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1583  1.1  elric 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
   1584  1.1  elric 	goto out;
   1585  1.1  elric     } else if(ret){
   1586  1.1  elric 	const char *new_rlm, *msg;
   1587  1.1  elric 	Realm req_rlm;
   1588  1.1  elric 	krb5_realm *realms;
   1589  1.1  elric 
   1590  1.1  elric 	if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
   1591  1.1  elric 	    if(nloop++ < 2) {
   1592  1.1  elric 		new_rlm = find_rpath(context, tgt->crealm, req_rlm);
   1593  1.1  elric 		if(new_rlm) {
   1594  1.1  elric 		    kdc_log(context, config, 5, "krbtgt for realm %s "
   1595  1.1  elric 			    "not found, trying %s",
   1596  1.1  elric 			    req_rlm, new_rlm);
   1597  1.1  elric 		    krb5_free_principal(context, sp);
   1598  1.1  elric 		    free(spn);
   1599  1.1  elric 		    krb5_make_principal(context, &sp, r,
   1600  1.1  elric 					KRB5_TGS_NAME, new_rlm, NULL);
   1601  1.1  elric 		    ret = krb5_unparse_name(context, sp, &spn);
   1602  1.1  elric 		    if (ret)
   1603  1.1  elric 			goto out;
   1604  1.1  elric 
   1605  1.1  elric 		    if (ref_realm)
   1606  1.1  elric 			free(ref_realm);
   1607  1.1  elric 		    ref_realm = strdup(new_rlm);
   1608  1.1  elric 		    goto server_lookup;
   1609  1.1  elric 		}
   1610  1.1  elric 	    }
   1611  1.1  elric 	} else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
   1612  1.1  elric 	    if (strcmp(realms[0], sp->realm) != 0) {
   1613  1.1  elric 		kdc_log(context, config, 5,
   1614  1.1  elric 			"Returning a referral to realm %s for "
   1615  1.1  elric 			"server %s that was not found",
   1616  1.1  elric 			realms[0], spn);
   1617  1.1  elric 		krb5_free_principal(context, sp);
   1618  1.1  elric 		free(spn);
   1619  1.1  elric 		krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
   1620  1.1  elric 				    realms[0], NULL);
   1621  1.1  elric 		ret = krb5_unparse_name(context, sp, &spn);
   1622  1.1  elric 		if (ret)
   1623  1.1  elric 		    goto out;
   1624  1.1  elric 
   1625  1.1  elric 		if (ref_realm)
   1626  1.1  elric 		    free(ref_realm);
   1627  1.1  elric 		ref_realm = strdup(realms[0]);
   1628  1.1  elric 
   1629  1.1  elric 		krb5_free_host_realm(context, realms);
   1630  1.1  elric 		goto server_lookup;
   1631  1.1  elric 	    }
   1632  1.1  elric 	    krb5_free_host_realm(context, realms);
   1633  1.1  elric 	}
   1634  1.1  elric 	msg = krb5_get_error_message(context, ret);
   1635  1.1  elric 	kdc_log(context, config, 0,
   1636  1.1  elric 		"Server not found in database: %s: %s", spn, msg);
   1637  1.1  elric 	krb5_free_error_message(context, msg);
   1638  1.1  elric 	if (ret == HDB_ERR_NOENTRY)
   1639  1.1  elric 	    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
   1640  1.1  elric 	goto out;
   1641  1.1  elric     }
   1642  1.1  elric 
   1643  1.1  elric     /*
   1644  1.1  elric      * Select enctype, return key and kvno.
   1645  1.1  elric      */
   1646  1.1  elric 
   1647  1.1  elric     {
   1648  1.1  elric 	krb5_enctype etype;
   1649  1.1  elric 
   1650  1.1  elric 	if(b->kdc_options.enc_tkt_in_skey) {
   1651  1.1  elric 	    int i;
   1652  1.1  elric 	    ekey = &adtkt.key;
   1653  1.1  elric 	    for(i = 0; i < b->etype.len; i++)
   1654  1.1  elric 		if (b->etype.val[i] == adtkt.key.keytype)
   1655  1.1  elric 		    break;
   1656  1.1  elric 	    if(i == b->etype.len) {
   1657  1.1  elric 		kdc_log(context, config, 0,
   1658  1.1  elric 			"Addition ticket have not matching etypes");
   1659  1.1  elric 		krb5_clear_error_message(context);
   1660  1.1  elric 		ret = KRB5KDC_ERR_ETYPE_NOSUPP;
   1661  1.1  elric 		goto out;
   1662  1.1  elric 	    }
   1663  1.1  elric 	    etype = b->etype.val[i];
   1664  1.1  elric 	    kvno = 0;
   1665  1.1  elric 	} else {
   1666  1.1  elric 	    Key *skey;
   1667  1.1  elric 
   1668  1.1  elric 	    ret = _kdc_find_etype(context, server,
   1669  1.1  elric 				  b->etype.val, b->etype.len, &skey);
   1670  1.1  elric 	    if(ret) {
   1671  1.1  elric 		kdc_log(context, config, 0,
   1672  1.1  elric 			"Server (%s) has no support for etypes", spn);
   1673  1.1  elric 		goto out;
   1674  1.1  elric 	    }
   1675  1.1  elric 	    ekey = &skey->key;
   1676  1.1  elric 	    etype = skey->key.keytype;
   1677  1.1  elric 	    kvno = server->entry.kvno;
   1678  1.1  elric 	}
   1679  1.1  elric 
   1680  1.1  elric 	ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
   1681  1.1  elric 	if (ret)
   1682  1.1  elric 	    goto out;
   1683  1.1  elric     }
   1684  1.1  elric 
   1685  1.1  elric     /*
   1686  1.1  elric      * Check that service is in the same realm as the krbtgt. If it's
   1687  1.1  elric      * not the same, it's someone that is using a uni-directional trust
   1688  1.1  elric      * backward.
   1689  1.1  elric      */
   1690  1.1  elric 
   1691  1.1  elric     /*
   1692  1.1  elric      * Validate authoriation data
   1693  1.1  elric      */
   1694  1.1  elric 
   1695  1.1  elric     ret = hdb_enctype2key(context, &krbtgt->entry,
   1696  1.1  elric 			  krbtgt_etype, &tkey_check);
   1697  1.1  elric     if(ret) {
   1698  1.1  elric 	kdc_log(context, config, 0,
   1699  1.1  elric 		    "Failed to find key for krbtgt PAC check");
   1700  1.1  elric 	goto out;
   1701  1.1  elric     }
   1702  1.1  elric 
   1703  1.1  elric     /* Now refetch the primary krbtgt, and get the current kvno (the
   1704  1.1  elric      * sign check may have been on an old kvno, and the server may
   1705  1.1  elric      * have been an incoming trust) */
   1706  1.1  elric     ret = krb5_make_principal(context, &krbtgt_principal,
   1707  1.1  elric 			      krb5_principal_get_comp_string(context,
   1708  1.1  elric 							     krbtgt->entry.principal,
   1709  1.1  elric 							     1),
   1710  1.1  elric 			      KRB5_TGS_NAME,
   1711  1.1  elric 			      krb5_principal_get_comp_string(context,
   1712  1.1  elric 							     krbtgt->entry.principal,
   1713  1.1  elric 							     1), NULL);
   1714  1.1  elric     if(ret) {
   1715  1.1  elric 	kdc_log(context, config, 0,
   1716  1.1  elric 		    "Failed to generate krbtgt principal");
   1717  1.1  elric 	goto out;
   1718  1.1  elric     }
   1719  1.1  elric 
   1720  1.1  elric     ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
   1721  1.1  elric     krb5_free_principal(context, krbtgt_principal);
   1722  1.1  elric     if (ret) {
   1723  1.1  elric 	krb5_error_code ret2;
   1724  1.1  elric 	char *tpn, *tpn2;
   1725  1.1  elric 	ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
   1726  1.1  elric 	ret2 = krb5_unparse_name(context, krbtgt->entry.principal, &tpn2);
   1727  1.1  elric 	kdc_log(context, config, 0,
   1728  1.1  elric 		"Request with wrong krbtgt: %s, %s not found in our database",
   1729  1.1  elric 		(ret == 0) ? tpn : "<unknown>", (ret2 == 0) ? tpn2 : "<unknown>");
   1730  1.1  elric 	if(ret == 0)
   1731  1.1  elric 	    free(tpn);
   1732  1.1  elric 	if(ret2 == 0)
   1733  1.1  elric 	    free(tpn2);
   1734  1.1  elric 	ret = KRB5KRB_AP_ERR_NOT_US;
   1735  1.1  elric 	goto out;
   1736  1.1  elric     }
   1737  1.1  elric 
   1738  1.1  elric     /* The first realm is the realm of the service, the second is
   1739  1.1  elric      * krbtgt/<this>/@REALM component of the krbtgt DN the request was
   1740  1.1  elric      * encrypted to.  The redirection via the krbtgt_out entry allows
   1741  1.1  elric      * the DB to possibly correct the case of the realm (Samba4 does
   1742  1.1  elric      * this) before the strcmp() */
   1743  1.1  elric     if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
   1744  1.1  elric 	       krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
   1745  1.1  elric 	char *tpn;
   1746  1.1  elric 	ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &tpn);
   1747  1.1  elric 	kdc_log(context, config, 0,
   1748  1.1  elric 		"Request with wrong krbtgt: %s",
   1749  1.1  elric 		(ret == 0) ? tpn : "<unknown>");
   1750  1.1  elric 	if(ret == 0)
   1751  1.1  elric 	    free(tpn);
   1752  1.1  elric 	ret = KRB5KRB_AP_ERR_NOT_US;
   1753  1.1  elric     }
   1754  1.1  elric 
   1755  1.1  elric     ret = hdb_enctype2key(context, &krbtgt_out->entry,
   1756  1.1  elric 			  krbtgt_etype, &tkey_sign);
   1757  1.1  elric     if(ret) {
   1758  1.1  elric 	kdc_log(context, config, 0,
   1759  1.1  elric 		    "Failed to find key for krbtgt PAC signature");
   1760  1.1  elric 	goto out;
   1761  1.1  elric     }
   1762  1.1  elric 
   1763  1.1  elric     ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
   1764  1.1  elric 			NULL, &clientdb, &client);
   1765  1.1  elric     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1766  1.1  elric 	/* This is OK, we are just trying to find out if they have
   1767  1.1  elric 	 * been disabled or deleted in the meantime, missing secrets
   1768  1.1  elric 	 * is OK */
   1769  1.1  elric     } else if(ret){
   1770  1.1  elric 	const char *krbtgt_realm, *msg;
   1771  1.1  elric 
   1772  1.1  elric 	/*
   1773  1.1  elric 	 * If the client belongs to the same realm as our krbtgt, it
   1774  1.1  elric 	 * should exist in the local database.
   1775  1.1  elric 	 *
   1776  1.1  elric 	 */
   1777  1.1  elric 
   1778  1.1  elric 	krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal);
   1779  1.1  elric 
   1780  1.1  elric 	if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
   1781  1.1  elric 	    if (ret == HDB_ERR_NOENTRY)
   1782  1.1  elric 		ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   1783  1.1  elric 	    kdc_log(context, config, 1, "Client no longer in database: %s",
   1784  1.1  elric 		    cpn);
   1785  1.1  elric 	    goto out;
   1786  1.1  elric 	}
   1787  1.1  elric 
   1788  1.1  elric 	msg = krb5_get_error_message(context, ret);
   1789  1.1  elric 	kdc_log(context, config, 1, "Client not found in database: %s", msg);
   1790  1.1  elric 	krb5_free_error_message(context, msg);
   1791  1.1  elric     }
   1792  1.1  elric 
   1793  1.1  elric     ret = check_PAC(context, config, cp,
   1794  1.1  elric 		    client, server, krbtgt, ekey, &tkey_check->key, &tkey_sign->key,
   1795  1.1  elric 		    tgt, &rspac, &signedpath);
   1796  1.1  elric     if (ret) {
   1797  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1798  1.1  elric 	kdc_log(context, config, 0,
   1799  1.1  elric 		"Verify PAC failed for %s (%s) from %s with %s",
   1800  1.1  elric 		spn, cpn, from, msg);
   1801  1.1  elric 	krb5_free_error_message(context, msg);
   1802  1.1  elric 	goto out;
   1803  1.1  elric     }
   1804  1.1  elric 
   1805  1.1  elric     /* also check the krbtgt for signature */
   1806  1.1  elric     ret = check_KRB5SignedPath(context,
   1807  1.1  elric 			       config,
   1808  1.1  elric 			       krbtgt,
   1809  1.1  elric 			       cp,
   1810  1.1  elric 			       tgt,
   1811  1.1  elric 			       &spp,
   1812  1.1  elric 			       &signedpath);
   1813  1.1  elric     if (ret) {
   1814  1.1  elric 	const char *msg = krb5_get_error_message(context, ret);
   1815  1.1  elric 	kdc_log(context, config, 0,
   1816  1.1  elric 		"KRB5SignedPath check failed for %s (%s) from %s with %s",
   1817  1.1  elric 		spn, cpn, from, msg);
   1818  1.1  elric 	krb5_free_error_message(context, msg);
   1819  1.1  elric 	goto out;
   1820  1.1  elric     }
   1821  1.1  elric 
   1822  1.1  elric     /*
   1823  1.1  elric      * Process request
   1824  1.1  elric      */
   1825  1.1  elric 
   1826  1.1  elric     client_principal = cp;
   1827  1.1  elric 
   1828  1.1  elric     if (client) {
   1829  1.1  elric 	const PA_DATA *sdata;
   1830  1.1  elric 	int i = 0;
   1831  1.1  elric 
   1832  1.1  elric 	sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
   1833  1.1  elric 	if (sdata) {
   1834  1.1  elric 	    krb5_crypto crypto;
   1835  1.1  elric 	    krb5_data datack;
   1836  1.1  elric 	    PA_S4U2Self self;
   1837  1.1  elric 	    char *selfcpn = NULL;
   1838  1.1  elric 	    const char *str;
   1839  1.1  elric 
   1840  1.1  elric 	    ret = decode_PA_S4U2Self(sdata->padata_value.data,
   1841  1.1  elric 				     sdata->padata_value.length,
   1842  1.1  elric 				     &self, NULL);
   1843  1.1  elric 	    if (ret) {
   1844  1.1  elric 		kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
   1845  1.1  elric 		goto out;
   1846  1.1  elric 	    }
   1847  1.1  elric 
   1848  1.1  elric 	    ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
   1849  1.1  elric 	    if (ret)
   1850  1.1  elric 		goto out;
   1851  1.1  elric 
   1852  1.1  elric 	    ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
   1853  1.1  elric 	    if (ret) {
   1854  1.1  elric 		const char *msg = krb5_get_error_message(context, ret);
   1855  1.1  elric 		free_PA_S4U2Self(&self);
   1856  1.1  elric 		krb5_data_free(&datack);
   1857  1.1  elric 		kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
   1858  1.1  elric 		krb5_free_error_message(context, msg);
   1859  1.1  elric 		goto out;
   1860  1.1  elric 	    }
   1861  1.1  elric 
   1862  1.1  elric 	    ret = krb5_verify_checksum(context,
   1863  1.1  elric 				       crypto,
   1864  1.1  elric 				       KRB5_KU_OTHER_CKSUM,
   1865  1.1  elric 				       datack.data,
   1866  1.1  elric 				       datack.length,
   1867  1.1  elric 				       &self.cksum);
   1868  1.1  elric 	    krb5_data_free(&datack);
   1869  1.1  elric 	    krb5_crypto_destroy(context, crypto);
   1870  1.1  elric 	    if (ret) {
   1871  1.1  elric 		const char *msg = krb5_get_error_message(context, ret);
   1872  1.1  elric 		free_PA_S4U2Self(&self);
   1873  1.1  elric 		kdc_log(context, config, 0,
   1874  1.1  elric 			"krb5_verify_checksum failed for S4U2Self: %s", msg);
   1875  1.1  elric 		krb5_free_error_message(context, msg);
   1876  1.1  elric 		goto out;
   1877  1.1  elric 	    }
   1878  1.1  elric 
   1879  1.1  elric 	    ret = _krb5_principalname2krb5_principal(context,
   1880  1.1  elric 						     &client_principal,
   1881  1.1  elric 						     self.name,
   1882  1.1  elric 						     self.realm);
   1883  1.1  elric 	    free_PA_S4U2Self(&self);
   1884  1.1  elric 	    if (ret)
   1885  1.1  elric 		goto out;
   1886  1.1  elric 
   1887  1.1  elric 	    ret = krb5_unparse_name(context, client_principal, &selfcpn);
   1888  1.1  elric 	    if (ret)
   1889  1.1  elric 		goto out;
   1890  1.1  elric 
   1891  1.1  elric 	    /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
   1892  1.1  elric 	    if(rspac.data) {
   1893  1.1  elric 		krb5_pac p = NULL;
   1894  1.1  elric 		krb5_data_free(&rspac);
   1895  1.1  elric 		ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON,
   1896  1.1  elric 				    NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
   1897  1.1  elric 		if (ret) {
   1898  1.1  elric 		    const char *msg;
   1899  1.1  elric 
   1900  1.1  elric 		    /*
   1901  1.1  elric 		     * If the client belongs to the same realm as our krbtgt, it
   1902  1.1  elric 		     * should exist in the local database.
   1903  1.1  elric 		     *
   1904  1.1  elric 		     */
   1905  1.1  elric 
   1906  1.1  elric 		    if (ret == HDB_ERR_NOENTRY)
   1907  1.1  elric 			ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   1908  1.1  elric 		    msg = krb5_get_error_message(context, ret);
   1909  1.1  elric 		    kdc_log(context, config, 1, "S2U4Self principal to impersonate %s not found in database: %s", cpn, msg);
   1910  1.1  elric 		    krb5_free_error_message(context, msg);
   1911  1.1  elric 		    goto out;
   1912  1.1  elric 		}
   1913  1.1  elric 		ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p);
   1914  1.1  elric 		if (ret) {
   1915  1.1  elric 		    kdc_log(context, config, 0, "PAC generation failed for -- %s",
   1916  1.1  elric 			    selfcpn);
   1917  1.1  elric 		    goto out;
   1918  1.1  elric 		}
   1919  1.1  elric 		if (p != NULL) {
   1920  1.1  elric 		    ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
   1921  1.1  elric 					 s4u2self_impersonated_client->entry.principal,
   1922  1.1  elric 					 ekey, &tkey_sign->key,
   1923  1.1  elric 					 &rspac);
   1924  1.1  elric 		    krb5_pac_free(context, p);
   1925  1.1  elric 		    if (ret) {
   1926  1.1  elric 			kdc_log(context, config, 0, "PAC signing failed for -- %s",
   1927  1.1  elric 				selfcpn);
   1928  1.1  elric 			goto out;
   1929  1.1  elric 		    }
   1930  1.1  elric 		}
   1931  1.1  elric 	    }
   1932  1.1  elric 
   1933  1.1  elric 	    /*
   1934  1.1  elric 	     * Check that service doing the impersonating is
   1935  1.1  elric 	     * requesting a ticket to it-self.
   1936  1.1  elric 	     */
   1937  1.1  elric 	    ret = check_s4u2self(context, config, clientdb, client, sp);
   1938  1.1  elric 	    if (ret) {
   1939  1.1  elric 		kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
   1940  1.1  elric 			"to impersonate to service "
   1941  1.1  elric 			"(tried for user %s to service %s)",
   1942  1.1  elric 			cpn, selfcpn, spn);
   1943  1.1  elric 		free(selfcpn);
   1944  1.1  elric 		goto out;
   1945  1.1  elric 	    }
   1946  1.1  elric 
   1947  1.1  elric 	    /*
   1948  1.1  elric 	     * If the service isn't trusted for authentication to
   1949  1.1  elric 	     * delegation, remove the forward flag.
   1950  1.1  elric 	     */
   1951  1.1  elric 
   1952  1.1  elric 	    if (client->entry.flags.trusted_for_delegation) {
   1953  1.1  elric 		str = "[forwardable]";
   1954  1.1  elric 	    } else {
   1955  1.1  elric 		b->kdc_options.forwardable = 0;
   1956  1.1  elric 		str = "";
   1957  1.1  elric 	    }
   1958  1.1  elric 	    kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
   1959  1.1  elric 		    "service %s %s", cpn, selfcpn, spn, str);
   1960  1.1  elric 	    free(selfcpn);
   1961  1.1  elric 	}
   1962  1.1  elric     }
   1963  1.1  elric 
   1964  1.1  elric     /*
   1965  1.1  elric      * Constrained delegation
   1966  1.1  elric      */
   1967  1.1  elric 
   1968  1.1  elric     if (client != NULL
   1969  1.1  elric 	&& b->additional_tickets != NULL
   1970  1.1  elric 	&& b->additional_tickets->len != 0
   1971  1.1  elric 	&& b->kdc_options.enc_tkt_in_skey == 0)
   1972  1.1  elric     {
   1973  1.1  elric 	int ad_signedpath = 0;
   1974  1.1  elric 	Key *clientkey;
   1975  1.1  elric 	Ticket *t;
   1976  1.1  elric 	char *str;
   1977  1.1  elric 
   1978  1.1  elric 	/*
   1979  1.1  elric 	 * Require that the KDC have issued the service's krbtgt (not
   1980  1.1  elric 	 * self-issued ticket with kimpersonate(1).
   1981  1.1  elric 	 */
   1982  1.1  elric 	if (!signedpath) {
   1983  1.1  elric 	    ret = KRB5KDC_ERR_BADOPTION;
   1984  1.1  elric 	    kdc_log(context, config, 0,
   1985  1.1  elric 		    "Constrained delegation done on service ticket %s/%s",
   1986  1.1  elric 		    cpn, spn);
   1987  1.1  elric 	    goto out;
   1988  1.1  elric 	}
   1989  1.1  elric 
   1990  1.1  elric 	t = &b->additional_tickets->val[0];
   1991  1.1  elric 
   1992  1.1  elric 	ret = hdb_enctype2key(context, &client->entry,
   1993  1.1  elric 			      t->enc_part.etype, &clientkey);
   1994  1.1  elric 	if(ret){
   1995  1.1  elric 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
   1996  1.1  elric 	    goto out;
   1997  1.1  elric 	}
   1998  1.1  elric 
   1999  1.1  elric 	ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
   2000  1.1  elric 	if (ret) {
   2001  1.1  elric 	    kdc_log(context, config, 0,
   2002  1.1  elric 		    "failed to decrypt ticket for "
   2003  1.1  elric 		    "constrained delegation from %s to %s ", cpn, spn);
   2004  1.1  elric 	    goto out;
   2005  1.1  elric 	}
   2006  1.1  elric 
   2007  1.1  elric 	/* check that ticket is valid */
   2008  1.1  elric 	if (adtkt.flags.forwardable == 0) {
   2009  1.1  elric 	    kdc_log(context, config, 0,
   2010  1.1  elric 		    "Missing forwardable flag on ticket for "
   2011  1.1  elric 		    "constrained delegation from %s to %s ", cpn, spn);
   2012  1.1  elric 	    ret = KRB5KDC_ERR_BADOPTION;
   2013  1.1  elric 	    goto out;
   2014  1.1  elric 	}
   2015  1.1  elric 
   2016  1.1  elric 	ret = check_constrained_delegation(context, config, clientdb,
   2017  1.1  elric 					   client, sp);
   2018  1.1  elric 	if (ret) {
   2019  1.1  elric 	    kdc_log(context, config, 0,
   2020  1.1  elric 		    "constrained delegation from %s to %s not allowed",
   2021  1.1  elric 		    cpn, spn);
   2022  1.1  elric 	    goto out;
   2023  1.1  elric 	}
   2024  1.1  elric 
   2025  1.1  elric 	ret = _krb5_principalname2krb5_principal(context,
   2026  1.1  elric 						 &client_principal,
   2027  1.1  elric 						 adtkt.cname,
   2028  1.1  elric 						 adtkt.crealm);
   2029  1.1  elric 	if (ret)
   2030  1.1  elric 	    goto out;
   2031  1.1  elric 
   2032  1.1  elric 	ret = krb5_unparse_name(context, client_principal, &str);
   2033  1.1  elric 	if (ret)
   2034  1.1  elric 	    goto out;
   2035  1.1  elric 
   2036  1.1  elric 	ret = verify_flags(context, config, &adtkt, str);
   2037  1.1  elric 	if (ret) {
   2038  1.1  elric 	    free(str);
   2039  1.1  elric 	    goto out;
   2040  1.1  elric 	}
   2041  1.1  elric 
   2042  1.1  elric 	/*
   2043  1.1  elric 	 * Check that the KDC issued the user's ticket.
   2044  1.1  elric 	 */
   2045  1.1  elric 	ret = check_KRB5SignedPath(context,
   2046  1.1  elric 				   config,
   2047  1.1  elric 				   krbtgt,
   2048  1.1  elric 				   cp,
   2049  1.1  elric 				   &adtkt,
   2050  1.1  elric 				   NULL,
   2051  1.1  elric 				   &ad_signedpath);
   2052  1.1  elric 	if (ret == 0 && !ad_signedpath)
   2053  1.1  elric 	    ret = KRB5KDC_ERR_BADOPTION;
   2054  1.1  elric 	if (ret) {
   2055  1.1  elric 	    const char *msg = krb5_get_error_message(context, ret);
   2056  1.1  elric 	    kdc_log(context, config, 0,
   2057  1.1  elric 		    "KRB5SignedPath check from service %s failed "
   2058  1.1  elric 		    "for delegation to %s for client %s "
   2059  1.1  elric 		    "from %s failed with %s",
   2060  1.1  elric 		    spn, str, cpn, from, msg);
   2061  1.1  elric 	    krb5_free_error_message(context, msg);
   2062  1.1  elric 	    free(str);
   2063  1.1  elric 	    goto out;
   2064  1.1  elric 	}
   2065  1.1  elric 
   2066  1.1  elric 	kdc_log(context, config, 0, "constrained delegation for %s "
   2067  1.1  elric 		"from %s to %s", str, cpn, spn);
   2068  1.1  elric 	free(str);
   2069  1.1  elric     }
   2070  1.1  elric 
   2071  1.1  elric     /*
   2072  1.1  elric      * Check flags
   2073  1.1  elric      */
   2074  1.1  elric 
   2075  1.1  elric     ret = kdc_check_flags(context, config,
   2076  1.1  elric 			  client, cpn,
   2077  1.1  elric 			  server, spn,
   2078  1.1  elric 			  FALSE);
   2079  1.1  elric     if(ret)
   2080  1.1  elric 	goto out;
   2081  1.1  elric 
   2082  1.1  elric     if((b->kdc_options.validate || b->kdc_options.renew) &&
   2083  1.1  elric        !krb5_principal_compare(context,
   2084  1.1  elric 			       krbtgt->entry.principal,
   2085  1.1  elric 			       server->entry.principal)){
   2086  1.1  elric 	kdc_log(context, config, 0, "Inconsistent request.");
   2087  1.1  elric 	ret = KRB5KDC_ERR_SERVER_NOMATCH;
   2088  1.1  elric 	goto out;
   2089  1.1  elric     }
   2090  1.1  elric 
   2091  1.1  elric     /* check for valid set of addresses */
   2092  1.1  elric     if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
   2093  1.1  elric 	ret = KRB5KRB_AP_ERR_BADADDR;
   2094  1.1  elric 	kdc_log(context, config, 0, "Request from wrong address");
   2095  1.1  elric 	goto out;
   2096  1.1  elric     }
   2097  1.1  elric 
   2098  1.1  elric     /*
   2099  1.1  elric      * If this is an referral, add server referral data to the
   2100  1.1  elric      * auth_data reply .
   2101  1.1  elric      */
   2102  1.1  elric     if (ref_realm) {
   2103  1.1  elric 	PA_DATA pa;
   2104  1.1  elric 	krb5_crypto crypto;
   2105  1.1  elric 
   2106  1.1  elric 	kdc_log(context, config, 0,
   2107  1.1  elric 		"Adding server referral to %s", ref_realm);
   2108  1.1  elric 
   2109  1.1  elric 	ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
   2110  1.1  elric 	if (ret)
   2111  1.1  elric 	    goto out;
   2112  1.1  elric 
   2113  1.1  elric 	ret = build_server_referral(context, config, crypto, ref_realm,
   2114  1.1  elric 				    NULL, s, &pa.padata_value);
   2115  1.1  elric 	krb5_crypto_destroy(context, crypto);
   2116  1.1  elric 	if (ret) {
   2117  1.1  elric 	    kdc_log(context, config, 0,
   2118  1.1  elric 		    "Failed building server referral");
   2119  1.1  elric 	    goto out;
   2120  1.1  elric 	}
   2121  1.1  elric 	pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
   2122  1.1  elric 
   2123  1.1  elric 	ret = add_METHOD_DATA(&enc_pa_data, &pa);
   2124  1.1  elric 	krb5_data_free(&pa.padata_value);
   2125  1.1  elric 	if (ret) {
   2126  1.1  elric 	    kdc_log(context, config, 0,
   2127  1.1  elric 		    "Add server referral METHOD-DATA failed");
   2128  1.1  elric 	    goto out;
   2129  1.1  elric 	}
   2130  1.1  elric     }
   2131  1.1  elric 
   2132  1.1  elric     /*
   2133  1.1  elric      *
   2134  1.1  elric      */
   2135  1.1  elric 
   2136  1.1  elric     ret = tgs_make_reply(context,
   2137  1.1  elric 			 config,
   2138  1.1  elric 			 b,
   2139  1.1  elric 			 client_principal,
   2140  1.1  elric 			 tgt,
   2141  1.1  elric 			 replykey,
   2142  1.1  elric 			 rk_is_subkey,
   2143  1.1  elric 			 ekey,
   2144  1.1  elric 			 &sessionkey,
   2145  1.1  elric 			 kvno,
   2146  1.1  elric 			 *auth_data,
   2147  1.1  elric 			 server,
   2148  1.1  elric 			 sp,
   2149  1.1  elric 			 spn,
   2150  1.1  elric 			 client,
   2151  1.1  elric 			 cp,
   2152  1.1  elric 			 krbtgt_out,
   2153  1.1  elric 			 krbtgt_etype,
   2154  1.1  elric 			 spp,
   2155  1.1  elric 			 &rspac,
   2156  1.1  elric 			 &enc_pa_data,
   2157  1.1  elric 			 e_text,
   2158  1.1  elric 			 reply);
   2159  1.1  elric 
   2160  1.1  elric out:
   2161  1.1  elric     free(spn);
   2162  1.1  elric     free(cpn);
   2163  1.1  elric 
   2164  1.1  elric     krb5_data_free(&rspac);
   2165  1.1  elric     krb5_free_keyblock_contents(context, &sessionkey);
   2166  1.1  elric     if(krbtgt_out)
   2167  1.1  elric 	_kdc_free_ent(context, krbtgt_out);
   2168  1.1  elric     if(server)
   2169  1.1  elric 	_kdc_free_ent(context, server);
   2170  1.1  elric     if(client)
   2171  1.1  elric 	_kdc_free_ent(context, client);
   2172  1.1  elric     if(s4u2self_impersonated_client)
   2173  1.1  elric 	_kdc_free_ent(context, s4u2self_impersonated_client);
   2174  1.1  elric 
   2175  1.1  elric     if (client_principal && client_principal != cp)
   2176  1.1  elric 	krb5_free_principal(context, client_principal);
   2177  1.1  elric     if (cp)
   2178  1.1  elric 	krb5_free_principal(context, cp);
   2179  1.1  elric     if (sp)
   2180  1.1  elric 	krb5_free_principal(context, sp);
   2181  1.1  elric     if (ref_realm)
   2182  1.1  elric 	free(ref_realm);
   2183  1.1  elric     free_METHOD_DATA(&enc_pa_data);
   2184  1.1  elric 
   2185  1.1  elric     free_EncTicketPart(&adtkt);
   2186  1.1  elric 
   2187  1.1  elric     return ret;
   2188  1.1  elric }
   2189  1.1  elric 
   2190  1.1  elric /*
   2191  1.1  elric  *
   2192  1.1  elric  */
   2193  1.1  elric 
   2194  1.1  elric krb5_error_code
   2195  1.1  elric _kdc_tgs_rep(krb5_context context,
   2196  1.1  elric 	     krb5_kdc_configuration *config,
   2197  1.1  elric 	     KDC_REQ *req,
   2198  1.1  elric 	     krb5_data *data,
   2199  1.1  elric 	     const char *from,
   2200  1.1  elric 	     struct sockaddr *from_addr,
   2201  1.1  elric 	     int datagram_reply)
   2202  1.1  elric {
   2203  1.1  elric     AuthorizationData *auth_data = NULL;
   2204  1.1  elric     krb5_error_code ret;
   2205  1.1  elric     int i = 0;
   2206  1.1  elric     const PA_DATA *tgs_req;
   2207  1.1  elric 
   2208  1.1  elric     hdb_entry_ex *krbtgt = NULL;
   2209  1.1  elric     krb5_ticket *ticket = NULL;
   2210  1.1  elric     const char *e_text = NULL;
   2211  1.1  elric     krb5_enctype krbtgt_etype = ETYPE_NULL;
   2212  1.1  elric 
   2213  1.1  elric     krb5_keyblock *replykey = NULL;
   2214  1.1  elric     int rk_is_subkey = 0;
   2215  1.1  elric     time_t *csec = NULL;
   2216  1.1  elric     int *cusec = NULL;
   2217  1.1  elric 
   2218  1.1  elric     if(req->padata == NULL){
   2219  1.1  elric 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
   2220  1.1  elric 	kdc_log(context, config, 0,
   2221  1.1  elric 		"TGS-REQ from %s without PA-DATA", from);
   2222  1.1  elric 	goto out;
   2223  1.1  elric     }
   2224  1.1  elric 
   2225  1.1  elric     tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
   2226  1.1  elric 
   2227  1.1  elric     if(tgs_req == NULL){
   2228  1.1  elric 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
   2229  1.1  elric 
   2230  1.1  elric 	kdc_log(context, config, 0,
   2231  1.1  elric 		"TGS-REQ from %s without PA-TGS-REQ", from);
   2232  1.1  elric 	goto out;
   2233  1.1  elric     }
   2234  1.1  elric     ret = tgs_parse_request(context, config,
   2235  1.1  elric 			    &req->req_body, tgs_req,
   2236  1.1  elric 			    &krbtgt,
   2237  1.1  elric 			    &krbtgt_etype,
   2238  1.1  elric 			    &ticket,
   2239  1.1  elric 			    &e_text,
   2240  1.1  elric 			    from, from_addr,
   2241  1.1  elric 			    &csec, &cusec,
   2242  1.1  elric 			    &auth_data,
   2243  1.1  elric 			    &replykey,
   2244  1.1  elric 			    &rk_is_subkey);
   2245  1.1  elric     if (ret == HDB_ERR_NOT_FOUND_HERE) {
   2246  1.1  elric 	/* kdc_log() is called in tgs_parse_request() */
   2247  1.1  elric 	goto out;
   2248  1.1  elric     }
   2249  1.1  elric     if (ret) {
   2250  1.1  elric 	kdc_log(context, config, 0,
   2251  1.1  elric 		"Failed parsing TGS-REQ from %s", from);
   2252  1.1  elric 	goto out;
   2253  1.1  elric     }
   2254  1.1  elric 
   2255  1.1  elric     ret = tgs_build_reply(context,
   2256  1.1  elric 			  config,
   2257  1.1  elric 			  req,
   2258  1.1  elric 			  &req->req_body,
   2259  1.1  elric 			  krbtgt,
   2260  1.1  elric 			  krbtgt_etype,
   2261  1.1  elric 			  replykey,
   2262  1.1  elric 			  rk_is_subkey,
   2263  1.1  elric 			  ticket,
   2264  1.1  elric 			  data,
   2265  1.1  elric 			  from,
   2266  1.1  elric 			  &e_text,
   2267  1.1  elric 			  &auth_data,
   2268  1.1  elric 			  from_addr);
   2269  1.1  elric     if (ret) {
   2270  1.1  elric 	kdc_log(context, config, 0,
   2271  1.1  elric 		"Failed building TGS-REP to %s", from);
   2272  1.1  elric 	goto out;
   2273  1.1  elric     }
   2274  1.1  elric 
   2275  1.1  elric     /* */
   2276  1.1  elric     if (datagram_reply && data->length > config->max_datagram_reply_length) {
   2277  1.1  elric 	krb5_data_free(data);
   2278  1.1  elric 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
   2279  1.1  elric 	e_text = "Reply packet too large";
   2280  1.1  elric     }
   2281  1.1  elric 
   2282  1.1  elric out:
   2283  1.1  elric     if (replykey)
   2284  1.1  elric 	krb5_free_keyblock(context, replykey);
   2285  1.1  elric     if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
   2286  1.1  elric 	krb5_mk_error(context,
   2287  1.1  elric 		      ret,
   2288  1.1  elric 		      NULL,
   2289  1.1  elric 		      NULL,
   2290  1.1  elric 		      NULL,
   2291  1.1  elric 		      NULL,
   2292  1.1  elric 		      csec,
   2293  1.1  elric 		      cusec,
   2294  1.1  elric 		      data);
   2295  1.1  elric 	ret = 0;
   2296  1.1  elric     }
   2297  1.1  elric     free(csec);
   2298  1.1  elric     free(cusec);
   2299  1.1  elric     if (ticket)
   2300  1.1  elric 	krb5_free_ticket(context, ticket);
   2301  1.1  elric     if(krbtgt)
   2302  1.1  elric 	_kdc_free_ent(context, krbtgt);
   2303  1.1  elric 
   2304  1.1  elric     if (auth_data) {
   2305  1.1  elric 	free_AuthorizationData(auth_data);
   2306  1.1  elric 	free(auth_data);
   2307  1.1  elric     }
   2308  1.1  elric 
   2309  1.1  elric     return ret;
   2310  1.1  elric }
   2311