1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6*ae771770SStanislav Sedov * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7*ae771770SStanislav Sedov * 8b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 9b528cefcSMark Murray * modification, are permitted provided that the following conditions 10b528cefcSMark Murray * are met: 11b528cefcSMark Murray * 12b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 13b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 14b528cefcSMark Murray * 15b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 16b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 17b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 18b528cefcSMark Murray * 19b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 20b528cefcSMark Murray * may be used to endorse or promote products derived from this software 21b528cefcSMark Murray * without specific prior written permission. 22b528cefcSMark Murray * 23b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33b528cefcSMark Murray * SUCH DAMAGE. 34b528cefcSMark Murray */ 35b528cefcSMark Murray 36b528cefcSMark Murray #include "krb5_locl.h" 37b528cefcSMark Murray 38*ae771770SStanislav Sedov /** 39*ae771770SStanislav Sedov * Free ticket and content 40*ae771770SStanislav Sedov * 41*ae771770SStanislav Sedov * @param context a Kerberos 5 context 42*ae771770SStanislav Sedov * @param ticket ticket to free 43*ae771770SStanislav Sedov * 44*ae771770SStanislav Sedov * @return Returns 0 to indicate success. Otherwise an kerberos et 45*ae771770SStanislav Sedov * error code is returned, see krb5_get_error_message(). 46*ae771770SStanislav Sedov * 47*ae771770SStanislav Sedov * @ingroup krb5 48*ae771770SStanislav Sedov */ 49b528cefcSMark Murray 50*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 51b528cefcSMark Murray krb5_free_ticket(krb5_context context, 52b528cefcSMark Murray krb5_ticket *ticket) 53b528cefcSMark Murray { 54b528cefcSMark Murray free_EncTicketPart(&ticket->ticket); 55b528cefcSMark Murray krb5_free_principal(context, ticket->client); 56b528cefcSMark Murray krb5_free_principal(context, ticket->server); 57c19800e8SDoug Rabson free(ticket); 58b528cefcSMark Murray return 0; 59b528cefcSMark Murray } 60b528cefcSMark Murray 61*ae771770SStanislav Sedov /** 62*ae771770SStanislav Sedov * Copy ticket and content 63*ae771770SStanislav Sedov * 64*ae771770SStanislav Sedov * @param context a Kerberos 5 context 65*ae771770SStanislav Sedov * @param from ticket to copy 66*ae771770SStanislav Sedov * @param to new copy of ticket, free with krb5_free_ticket() 67*ae771770SStanislav Sedov * 68*ae771770SStanislav Sedov * @return Returns 0 to indicate success. Otherwise an kerberos et 69*ae771770SStanislav Sedov * error code is returned, see krb5_get_error_message(). 70*ae771770SStanislav Sedov * 71*ae771770SStanislav Sedov * @ingroup krb5 72*ae771770SStanislav Sedov */ 73*ae771770SStanislav Sedov 74*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 75b528cefcSMark Murray krb5_copy_ticket(krb5_context context, 76b528cefcSMark Murray const krb5_ticket *from, 77b528cefcSMark Murray krb5_ticket **to) 78b528cefcSMark Murray { 79b528cefcSMark Murray krb5_error_code ret; 801c43270aSJacques Vidrine krb5_ticket *tmp; 811c43270aSJacques Vidrine 821c43270aSJacques Vidrine *to = NULL; 831c43270aSJacques Vidrine tmp = malloc(sizeof(*tmp)); 84adb0ddaeSAssar Westerlund if(tmp == NULL) { 85*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 86*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 87b528cefcSMark Murray return ENOMEM; 88adb0ddaeSAssar Westerlund } 89b528cefcSMark Murray if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ 90b528cefcSMark Murray free(tmp); 91b528cefcSMark Murray return ret; 92b528cefcSMark Murray } 93b528cefcSMark Murray ret = krb5_copy_principal(context, from->client, &tmp->client); 94b528cefcSMark Murray if(ret){ 95b528cefcSMark Murray free_EncTicketPart(&tmp->ticket); 961c43270aSJacques Vidrine free(tmp); 97b528cefcSMark Murray return ret; 98b528cefcSMark Murray } 991c43270aSJacques Vidrine ret = krb5_copy_principal(context, from->server, &tmp->server); 100b528cefcSMark Murray if(ret){ 101b528cefcSMark Murray krb5_free_principal(context, tmp->client); 102b528cefcSMark Murray free_EncTicketPart(&tmp->ticket); 1031c43270aSJacques Vidrine free(tmp); 104b528cefcSMark Murray return ret; 105b528cefcSMark Murray } 106b528cefcSMark Murray *to = tmp; 107b528cefcSMark Murray return 0; 108b528cefcSMark Murray } 109c19800e8SDoug Rabson 110*ae771770SStanislav Sedov /** 111*ae771770SStanislav Sedov * Return client principal in ticket 112*ae771770SStanislav Sedov * 113*ae771770SStanislav Sedov * @param context a Kerberos 5 context 114*ae771770SStanislav Sedov * @param ticket ticket to copy 115*ae771770SStanislav Sedov * @param client client principal, free with krb5_free_principal() 116*ae771770SStanislav Sedov * 117*ae771770SStanislav Sedov * @return Returns 0 to indicate success. Otherwise an kerberos et 118*ae771770SStanislav Sedov * error code is returned, see krb5_get_error_message(). 119*ae771770SStanislav Sedov * 120*ae771770SStanislav Sedov * @ingroup krb5 121*ae771770SStanislav Sedov */ 122*ae771770SStanislav Sedov 123*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 124c19800e8SDoug Rabson krb5_ticket_get_client(krb5_context context, 125c19800e8SDoug Rabson const krb5_ticket *ticket, 126c19800e8SDoug Rabson krb5_principal *client) 127c19800e8SDoug Rabson { 128c19800e8SDoug Rabson return krb5_copy_principal(context, ticket->client, client); 129c19800e8SDoug Rabson } 130c19800e8SDoug Rabson 131*ae771770SStanislav Sedov /** 132*ae771770SStanislav Sedov * Return server principal in ticket 133*ae771770SStanislav Sedov * 134*ae771770SStanislav Sedov * @param context a Kerberos 5 context 135*ae771770SStanislav Sedov * @param ticket ticket to copy 136*ae771770SStanislav Sedov * @param server server principal, free with krb5_free_principal() 137*ae771770SStanislav Sedov * 138*ae771770SStanislav Sedov * @return Returns 0 to indicate success. Otherwise an kerberos et 139*ae771770SStanislav Sedov * error code is returned, see krb5_get_error_message(). 140*ae771770SStanislav Sedov * 141*ae771770SStanislav Sedov * @ingroup krb5 142*ae771770SStanislav Sedov */ 143*ae771770SStanislav Sedov 144*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 145c19800e8SDoug Rabson krb5_ticket_get_server(krb5_context context, 146c19800e8SDoug Rabson const krb5_ticket *ticket, 147c19800e8SDoug Rabson krb5_principal *server) 148c19800e8SDoug Rabson { 149c19800e8SDoug Rabson return krb5_copy_principal(context, ticket->server, server); 150c19800e8SDoug Rabson } 151c19800e8SDoug Rabson 152*ae771770SStanislav Sedov /** 153*ae771770SStanislav Sedov * Return end time of ticket 154*ae771770SStanislav Sedov * 155*ae771770SStanislav Sedov * @param context a Kerberos 5 context 156*ae771770SStanislav Sedov * @param ticket ticket to copy 157*ae771770SStanislav Sedov * 158*ae771770SStanislav Sedov * @return end time of ticket 159*ae771770SStanislav Sedov * 160*ae771770SStanislav Sedov * @ingroup krb5 161*ae771770SStanislav Sedov */ 162*ae771770SStanislav Sedov 163*ae771770SStanislav Sedov KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL 164c19800e8SDoug Rabson krb5_ticket_get_endtime(krb5_context context, 165c19800e8SDoug Rabson const krb5_ticket *ticket) 166c19800e8SDoug Rabson { 167c19800e8SDoug Rabson return ticket->ticket.endtime; 168c19800e8SDoug Rabson } 169c19800e8SDoug Rabson 170*ae771770SStanislav Sedov /** 171*ae771770SStanislav Sedov * Get the flags from the Kerberos ticket 172*ae771770SStanislav Sedov * 173*ae771770SStanislav Sedov * @param context Kerberos context 174*ae771770SStanislav Sedov * @param ticket Kerberos ticket 175*ae771770SStanislav Sedov * 176*ae771770SStanislav Sedov * @return ticket flags 177*ae771770SStanislav Sedov * 178*ae771770SStanislav Sedov * @ingroup krb5_ticket 179*ae771770SStanislav Sedov */ 180*ae771770SStanislav Sedov KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL 181*ae771770SStanislav Sedov krb5_ticket_get_flags(krb5_context context, 182*ae771770SStanislav Sedov const krb5_ticket *ticket) 183*ae771770SStanislav Sedov { 184*ae771770SStanislav Sedov return TicketFlags2int(ticket->ticket.flags); 185*ae771770SStanislav Sedov } 186*ae771770SStanislav Sedov 187c19800e8SDoug Rabson static int 188c19800e8SDoug Rabson find_type_in_ad(krb5_context context, 189c19800e8SDoug Rabson int type, 190c19800e8SDoug Rabson krb5_data *data, 191c19800e8SDoug Rabson krb5_boolean *found, 192c19800e8SDoug Rabson krb5_boolean failp, 193c19800e8SDoug Rabson krb5_keyblock *sessionkey, 194c19800e8SDoug Rabson const AuthorizationData *ad, 195c19800e8SDoug Rabson int level) 196c19800e8SDoug Rabson { 197c19800e8SDoug Rabson krb5_error_code ret = 0; 198*ae771770SStanislav Sedov size_t i; 199c19800e8SDoug Rabson 200c19800e8SDoug Rabson if (level > 9) { 201c19800e8SDoug Rabson ret = ENOENT; /* XXX */ 202*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 203*ae771770SStanislav Sedov N_("Authorization data nested deeper " 204*ae771770SStanislav Sedov "then %d levels, stop searching", ""), 205*ae771770SStanislav Sedov level); 206c19800e8SDoug Rabson goto out; 207c19800e8SDoug Rabson } 208c19800e8SDoug Rabson 209c19800e8SDoug Rabson /* 210c19800e8SDoug Rabson * Only copy out the element the first time we get to it, we need 211c19800e8SDoug Rabson * to run over the whole authorization data fields to check if 212c19800e8SDoug Rabson * there are any container clases we need to care about. 213c19800e8SDoug Rabson */ 214c19800e8SDoug Rabson for (i = 0; i < ad->len; i++) { 215c19800e8SDoug Rabson if (!*found && ad->val[i].ad_type == type) { 216c19800e8SDoug Rabson ret = der_copy_octet_string(&ad->val[i].ad_data, data); 217c19800e8SDoug Rabson if (ret) { 218*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 219*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 220c19800e8SDoug Rabson goto out; 221c19800e8SDoug Rabson } 222c19800e8SDoug Rabson *found = TRUE; 223c19800e8SDoug Rabson continue; 224c19800e8SDoug Rabson } 225c19800e8SDoug Rabson switch (ad->val[i].ad_type) { 226c19800e8SDoug Rabson case KRB5_AUTHDATA_IF_RELEVANT: { 227c19800e8SDoug Rabson AuthorizationData child; 228c19800e8SDoug Rabson ret = decode_AuthorizationData(ad->val[i].ad_data.data, 229c19800e8SDoug Rabson ad->val[i].ad_data.length, 230c19800e8SDoug Rabson &child, 231c19800e8SDoug Rabson NULL); 232c19800e8SDoug Rabson if (ret) { 233*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 234*ae771770SStanislav Sedov N_("Failed to decode " 235*ae771770SStanislav Sedov "IF_RELEVANT with %d", ""), 236*ae771770SStanislav Sedov (int)ret); 237c19800e8SDoug Rabson goto out; 238c19800e8SDoug Rabson } 239c19800e8SDoug Rabson ret = find_type_in_ad(context, type, data, found, FALSE, 240c19800e8SDoug Rabson sessionkey, &child, level + 1); 241c19800e8SDoug Rabson free_AuthorizationData(&child); 242c19800e8SDoug Rabson if (ret) 243c19800e8SDoug Rabson goto out; 244c19800e8SDoug Rabson break; 245c19800e8SDoug Rabson } 246c19800e8SDoug Rabson #if 0 /* XXX test */ 247c19800e8SDoug Rabson case KRB5_AUTHDATA_KDC_ISSUED: { 248c19800e8SDoug Rabson AD_KDCIssued child; 249c19800e8SDoug Rabson 250c19800e8SDoug Rabson ret = decode_AD_KDCIssued(ad->val[i].ad_data.data, 251c19800e8SDoug Rabson ad->val[i].ad_data.length, 252c19800e8SDoug Rabson &child, 253c19800e8SDoug Rabson NULL); 254c19800e8SDoug Rabson if (ret) { 255*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 256*ae771770SStanislav Sedov N_("Failed to decode " 257*ae771770SStanislav Sedov "AD_KDCIssued with %d", ""), 258*ae771770SStanislav Sedov ret); 259c19800e8SDoug Rabson goto out; 260c19800e8SDoug Rabson } 261c19800e8SDoug Rabson if (failp) { 262c19800e8SDoug Rabson krb5_boolean valid; 263c19800e8SDoug Rabson krb5_data buf; 264c19800e8SDoug Rabson size_t len; 265c19800e8SDoug Rabson 266c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length, 267c19800e8SDoug Rabson &child.elements, &len, ret); 268c19800e8SDoug Rabson if (ret) { 269c19800e8SDoug Rabson free_AD_KDCIssued(&child); 270*ae771770SStanislav Sedov krb5_clear_error_message(context); 271c19800e8SDoug Rabson goto out; 272c19800e8SDoug Rabson } 273c19800e8SDoug Rabson if(buf.length != len) 274c19800e8SDoug Rabson krb5_abortx(context, "internal error in ASN.1 encoder"); 275c19800e8SDoug Rabson 276c19800e8SDoug Rabson ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf, 277c19800e8SDoug Rabson &child.ad_checksum, &valid); 278c19800e8SDoug Rabson krb5_data_free(&buf); 279c19800e8SDoug Rabson if (ret) { 280c19800e8SDoug Rabson free_AD_KDCIssued(&child); 281c19800e8SDoug Rabson goto out; 282c19800e8SDoug Rabson } 283c19800e8SDoug Rabson if (!valid) { 284*ae771770SStanislav Sedov krb5_clear_error_message(context); 285c19800e8SDoug Rabson ret = ENOENT; 286c19800e8SDoug Rabson free_AD_KDCIssued(&child); 287c19800e8SDoug Rabson goto out; 288c19800e8SDoug Rabson } 289c19800e8SDoug Rabson } 290c19800e8SDoug Rabson ret = find_type_in_ad(context, type, data, found, failp, sessionkey, 291c19800e8SDoug Rabson &child.elements, level + 1); 292c19800e8SDoug Rabson free_AD_KDCIssued(&child); 293c19800e8SDoug Rabson if (ret) 294c19800e8SDoug Rabson goto out; 295c19800e8SDoug Rabson break; 296c19800e8SDoug Rabson } 297c19800e8SDoug Rabson #endif 298c19800e8SDoug Rabson case KRB5_AUTHDATA_AND_OR: 299c19800e8SDoug Rabson if (!failp) 300c19800e8SDoug Rabson break; 301c19800e8SDoug Rabson ret = ENOENT; /* XXX */ 302*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 303*ae771770SStanislav Sedov N_("Authorization data contains " 304*ae771770SStanislav Sedov "AND-OR element that is unknown to the " 305*ae771770SStanislav Sedov "application", "")); 306c19800e8SDoug Rabson goto out; 307c19800e8SDoug Rabson default: 308c19800e8SDoug Rabson if (!failp) 309c19800e8SDoug Rabson break; 310c19800e8SDoug Rabson ret = ENOENT; /* XXX */ 311*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 312*ae771770SStanislav Sedov N_("Authorization data contains " 313*ae771770SStanislav Sedov "unknown type (%d) ", ""), 314*ae771770SStanislav Sedov ad->val[i].ad_type); 315c19800e8SDoug Rabson goto out; 316c19800e8SDoug Rabson } 317c19800e8SDoug Rabson } 318c19800e8SDoug Rabson out: 319c19800e8SDoug Rabson if (ret) { 320c19800e8SDoug Rabson if (*found) { 321c19800e8SDoug Rabson krb5_data_free(data); 322c19800e8SDoug Rabson *found = 0; 323c19800e8SDoug Rabson } 324c19800e8SDoug Rabson } 325c19800e8SDoug Rabson return ret; 326c19800e8SDoug Rabson } 327c19800e8SDoug Rabson 328*ae771770SStanislav Sedov /** 329*ae771770SStanislav Sedov * Extract the authorization data type of type from the ticket. Store 330*ae771770SStanislav Sedov * the field in data. This function is to use for kerberos 331*ae771770SStanislav Sedov * applications. 332*ae771770SStanislav Sedov * 333*ae771770SStanislav Sedov * @param context a Kerberos 5 context 334*ae771770SStanislav Sedov * @param ticket Kerberos ticket 335*ae771770SStanislav Sedov * @param type type to fetch 336*ae771770SStanislav Sedov * @param data returned data, free with krb5_data_free() 337*ae771770SStanislav Sedov * 338*ae771770SStanislav Sedov * @ingroup krb5 339c19800e8SDoug Rabson */ 340c19800e8SDoug Rabson 341*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 342c19800e8SDoug Rabson krb5_ticket_get_authorization_data_type(krb5_context context, 343c19800e8SDoug Rabson krb5_ticket *ticket, 344c19800e8SDoug Rabson int type, 345c19800e8SDoug Rabson krb5_data *data) 346c19800e8SDoug Rabson { 347c19800e8SDoug Rabson AuthorizationData *ad; 348c19800e8SDoug Rabson krb5_error_code ret; 349c19800e8SDoug Rabson krb5_boolean found = FALSE; 350c19800e8SDoug Rabson 351c19800e8SDoug Rabson krb5_data_zero(data); 352c19800e8SDoug Rabson 353c19800e8SDoug Rabson ad = ticket->ticket.authorization_data; 354c19800e8SDoug Rabson if (ticket->ticket.authorization_data == NULL) { 355*ae771770SStanislav Sedov krb5_set_error_message(context, ENOENT, 356*ae771770SStanislav Sedov N_("Ticket have not authorization data", "")); 357c19800e8SDoug Rabson return ENOENT; /* XXX */ 358c19800e8SDoug Rabson } 359c19800e8SDoug Rabson 360c19800e8SDoug Rabson ret = find_type_in_ad(context, type, data, &found, TRUE, 361c19800e8SDoug Rabson &ticket->ticket.key, ad, 0); 362c19800e8SDoug Rabson if (ret) 363c19800e8SDoug Rabson return ret; 364c19800e8SDoug Rabson if (!found) { 365*ae771770SStanislav Sedov krb5_set_error_message(context, ENOENT, 366*ae771770SStanislav Sedov N_("Ticket have not " 367*ae771770SStanislav Sedov "authorization data of type %d", ""), 368*ae771770SStanislav Sedov type); 369c19800e8SDoug Rabson return ENOENT; /* XXX */ 370c19800e8SDoug Rabson } 371c19800e8SDoug Rabson return 0; 372c19800e8SDoug Rabson } 373*ae771770SStanislav Sedov 374*ae771770SStanislav Sedov static krb5_error_code 375*ae771770SStanislav Sedov check_server_referral(krb5_context context, 376*ae771770SStanislav Sedov krb5_kdc_rep *rep, 377*ae771770SStanislav Sedov unsigned flags, 378*ae771770SStanislav Sedov krb5_const_principal requested, 379*ae771770SStanislav Sedov krb5_const_principal returned, 380*ae771770SStanislav Sedov krb5_keyblock * key) 381*ae771770SStanislav Sedov { 382*ae771770SStanislav Sedov krb5_error_code ret; 383*ae771770SStanislav Sedov PA_ServerReferralData ref; 384*ae771770SStanislav Sedov krb5_crypto session; 385*ae771770SStanislav Sedov EncryptedData ed; 386*ae771770SStanislav Sedov size_t len; 387*ae771770SStanislav Sedov krb5_data data; 388*ae771770SStanislav Sedov PA_DATA *pa; 389*ae771770SStanislav Sedov int i = 0, cmp; 390*ae771770SStanislav Sedov 391*ae771770SStanislav Sedov if (rep->kdc_rep.padata == NULL) 392*ae771770SStanislav Sedov goto noreferral; 393*ae771770SStanislav Sedov 394*ae771770SStanislav Sedov pa = krb5_find_padata(rep->kdc_rep.padata->val, 395*ae771770SStanislav Sedov rep->kdc_rep.padata->len, 396*ae771770SStanislav Sedov KRB5_PADATA_SERVER_REFERRAL, &i); 397*ae771770SStanislav Sedov if (pa == NULL) 398*ae771770SStanislav Sedov goto noreferral; 399*ae771770SStanislav Sedov 400*ae771770SStanislav Sedov memset(&ed, 0, sizeof(ed)); 401*ae771770SStanislav Sedov memset(&ref, 0, sizeof(ref)); 402*ae771770SStanislav Sedov 403*ae771770SStanislav Sedov ret = decode_EncryptedData(pa->padata_value.data, 404*ae771770SStanislav Sedov pa->padata_value.length, 405*ae771770SStanislav Sedov &ed, &len); 406*ae771770SStanislav Sedov if (ret) 407*ae771770SStanislav Sedov return ret; 408*ae771770SStanislav Sedov if (len != pa->padata_value.length) { 409*ae771770SStanislav Sedov free_EncryptedData(&ed); 410*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 411*ae771770SStanislav Sedov N_("Referral EncryptedData wrong for realm %s", 412*ae771770SStanislav Sedov "realm"), requested->realm); 413*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 414*ae771770SStanislav Sedov } 415*ae771770SStanislav Sedov 416*ae771770SStanislav Sedov ret = krb5_crypto_init(context, key, 0, &session); 417*ae771770SStanislav Sedov if (ret) { 418*ae771770SStanislav Sedov free_EncryptedData(&ed); 419*ae771770SStanislav Sedov return ret; 420*ae771770SStanislav Sedov } 421*ae771770SStanislav Sedov 422*ae771770SStanislav Sedov ret = krb5_decrypt_EncryptedData(context, session, 423*ae771770SStanislav Sedov KRB5_KU_PA_SERVER_REFERRAL, 424*ae771770SStanislav Sedov &ed, &data); 425*ae771770SStanislav Sedov free_EncryptedData(&ed); 426*ae771770SStanislav Sedov krb5_crypto_destroy(context, session); 427*ae771770SStanislav Sedov if (ret) 428*ae771770SStanislav Sedov return ret; 429*ae771770SStanislav Sedov 430*ae771770SStanislav Sedov ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len); 431*ae771770SStanislav Sedov if (ret) { 432*ae771770SStanislav Sedov krb5_data_free(&data); 433*ae771770SStanislav Sedov return ret; 434*ae771770SStanislav Sedov } 435*ae771770SStanislav Sedov krb5_data_free(&data); 436*ae771770SStanislav Sedov 437*ae771770SStanislav Sedov if (strcmp(requested->realm, returned->realm) != 0) { 438*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 439*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 440*ae771770SStanislav Sedov N_("server ref realm mismatch, " 441*ae771770SStanislav Sedov "requested realm %s got back %s", ""), 442*ae771770SStanislav Sedov requested->realm, returned->realm); 443*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 444*ae771770SStanislav Sedov } 445*ae771770SStanislav Sedov 446*ae771770SStanislav Sedov if (krb5_principal_is_krbtgt(context, returned)) { 447*ae771770SStanislav Sedov const char *realm = returned->name.name_string.val[1]; 448*ae771770SStanislav Sedov 449*ae771770SStanislav Sedov if (ref.referred_realm == NULL 450*ae771770SStanislav Sedov || strcmp(*ref.referred_realm, realm) != 0) 451*ae771770SStanislav Sedov { 452*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 453*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 454*ae771770SStanislav Sedov N_("tgt returned with wrong ref", "")); 455*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 456*ae771770SStanislav Sedov } 457*ae771770SStanislav Sedov } else if (krb5_principal_compare(context, returned, requested) == 0) { 458*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 459*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 460*ae771770SStanislav Sedov N_("req princ no same as returned", "")); 461*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 462*ae771770SStanislav Sedov } 463*ae771770SStanislav Sedov 464*ae771770SStanislav Sedov if (ref.requested_principal_name) { 465*ae771770SStanislav Sedov cmp = _krb5_principal_compare_PrincipalName(context, 466*ae771770SStanislav Sedov requested, 467*ae771770SStanislav Sedov ref.requested_principal_name); 468*ae771770SStanislav Sedov if (!cmp) { 469*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 470*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 471*ae771770SStanislav Sedov N_("referred principal not same " 472*ae771770SStanislav Sedov "as requested", "")); 473*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 474*ae771770SStanislav Sedov } 475*ae771770SStanislav Sedov } else if (flags & EXTRACT_TICKET_AS_REQ) { 476*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 477*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 478*ae771770SStanislav Sedov N_("Requested principal missing on AS-REQ", "")); 479*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 480*ae771770SStanislav Sedov } 481*ae771770SStanislav Sedov 482*ae771770SStanislav Sedov free_PA_ServerReferralData(&ref); 483*ae771770SStanislav Sedov 484*ae771770SStanislav Sedov return ret; 485*ae771770SStanislav Sedov noreferral: 486*ae771770SStanislav Sedov /* 487*ae771770SStanislav Sedov * Expect excact match or that we got a krbtgt 488*ae771770SStanislav Sedov */ 489*ae771770SStanislav Sedov if (krb5_principal_compare(context, requested, returned) != TRUE && 490*ae771770SStanislav Sedov (krb5_realm_compare(context, requested, returned) != TRUE && 491*ae771770SStanislav Sedov krb5_principal_is_krbtgt(context, returned) != TRUE)) 492*ae771770SStanislav Sedov { 493*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 494*ae771770SStanislav Sedov N_("Not same server principal returned " 495*ae771770SStanislav Sedov "as requested", "")); 496*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 497*ae771770SStanislav Sedov } 498*ae771770SStanislav Sedov return 0; 499*ae771770SStanislav Sedov } 500*ae771770SStanislav Sedov 501*ae771770SStanislav Sedov 502*ae771770SStanislav Sedov /* 503*ae771770SStanislav Sedov * Verify referral data 504*ae771770SStanislav Sedov */ 505*ae771770SStanislav Sedov 506*ae771770SStanislav Sedov 507*ae771770SStanislav Sedov static krb5_error_code 508*ae771770SStanislav Sedov check_client_referral(krb5_context context, 509*ae771770SStanislav Sedov krb5_kdc_rep *rep, 510*ae771770SStanislav Sedov krb5_const_principal requested, 511*ae771770SStanislav Sedov krb5_const_principal mapped, 512*ae771770SStanislav Sedov krb5_keyblock const * key) 513*ae771770SStanislav Sedov { 514*ae771770SStanislav Sedov krb5_error_code ret; 515*ae771770SStanislav Sedov PA_ClientCanonicalized canon; 516*ae771770SStanislav Sedov krb5_crypto crypto; 517*ae771770SStanislav Sedov krb5_data data; 518*ae771770SStanislav Sedov PA_DATA *pa; 519*ae771770SStanislav Sedov size_t len; 520*ae771770SStanislav Sedov int i = 0; 521*ae771770SStanislav Sedov 522*ae771770SStanislav Sedov if (rep->kdc_rep.padata == NULL) 523*ae771770SStanislav Sedov goto noreferral; 524*ae771770SStanislav Sedov 525*ae771770SStanislav Sedov pa = krb5_find_padata(rep->kdc_rep.padata->val, 526*ae771770SStanislav Sedov rep->kdc_rep.padata->len, 527*ae771770SStanislav Sedov KRB5_PADATA_CLIENT_CANONICALIZED, &i); 528*ae771770SStanislav Sedov if (pa == NULL) 529*ae771770SStanislav Sedov goto noreferral; 530*ae771770SStanislav Sedov 531*ae771770SStanislav Sedov ret = decode_PA_ClientCanonicalized(pa->padata_value.data, 532*ae771770SStanislav Sedov pa->padata_value.length, 533*ae771770SStanislav Sedov &canon, &len); 534*ae771770SStanislav Sedov if (ret) { 535*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 536*ae771770SStanislav Sedov N_("Failed to decode ClientCanonicalized " 537*ae771770SStanislav Sedov "from realm %s", ""), requested->realm); 538*ae771770SStanislav Sedov return ret; 539*ae771770SStanislav Sedov } 540*ae771770SStanislav Sedov 541*ae771770SStanislav Sedov ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, 542*ae771770SStanislav Sedov &canon.names, &len, ret); 543*ae771770SStanislav Sedov if (ret) { 544*ae771770SStanislav Sedov free_PA_ClientCanonicalized(&canon); 545*ae771770SStanislav Sedov return ret; 546*ae771770SStanislav Sedov } 547*ae771770SStanislav Sedov if (data.length != len) 548*ae771770SStanislav Sedov krb5_abortx(context, "internal asn.1 error"); 549*ae771770SStanislav Sedov 550*ae771770SStanislav Sedov ret = krb5_crypto_init(context, key, 0, &crypto); 551*ae771770SStanislav Sedov if (ret) { 552*ae771770SStanislav Sedov free(data.data); 553*ae771770SStanislav Sedov free_PA_ClientCanonicalized(&canon); 554*ae771770SStanislav Sedov return ret; 555*ae771770SStanislav Sedov } 556*ae771770SStanislav Sedov 557*ae771770SStanislav Sedov ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, 558*ae771770SStanislav Sedov data.data, data.length, 559*ae771770SStanislav Sedov &canon.canon_checksum); 560*ae771770SStanislav Sedov krb5_crypto_destroy(context, crypto); 561*ae771770SStanislav Sedov free(data.data); 562*ae771770SStanislav Sedov if (ret) { 563*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 564*ae771770SStanislav Sedov N_("Failed to verify client canonicalized " 565*ae771770SStanislav Sedov "data from realm %s", ""), 566*ae771770SStanislav Sedov requested->realm); 567*ae771770SStanislav Sedov free_PA_ClientCanonicalized(&canon); 568*ae771770SStanislav Sedov return ret; 569*ae771770SStanislav Sedov } 570*ae771770SStanislav Sedov 571*ae771770SStanislav Sedov if (!_krb5_principal_compare_PrincipalName(context, 572*ae771770SStanislav Sedov requested, 573*ae771770SStanislav Sedov &canon.names.requested_name)) 574*ae771770SStanislav Sedov { 575*ae771770SStanislav Sedov free_PA_ClientCanonicalized(&canon); 576*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 577*ae771770SStanislav Sedov N_("Requested name doesn't match" 578*ae771770SStanislav Sedov " in client referral", "")); 579*ae771770SStanislav Sedov return KRB5_PRINC_NOMATCH; 580*ae771770SStanislav Sedov } 581*ae771770SStanislav Sedov if (!_krb5_principal_compare_PrincipalName(context, 582*ae771770SStanislav Sedov mapped, 583*ae771770SStanislav Sedov &canon.names.mapped_name)) 584*ae771770SStanislav Sedov { 585*ae771770SStanislav Sedov free_PA_ClientCanonicalized(&canon); 586*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 587*ae771770SStanislav Sedov N_("Mapped name doesn't match" 588*ae771770SStanislav Sedov " in client referral", "")); 589*ae771770SStanislav Sedov return KRB5_PRINC_NOMATCH; 590*ae771770SStanislav Sedov } 591*ae771770SStanislav Sedov 592*ae771770SStanislav Sedov return 0; 593*ae771770SStanislav Sedov 594*ae771770SStanislav Sedov noreferral: 595*ae771770SStanislav Sedov if (krb5_principal_compare(context, requested, mapped) == FALSE) { 596*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 597*ae771770SStanislav Sedov N_("Not same client principal returned " 598*ae771770SStanislav Sedov "as requested", "")); 599*ae771770SStanislav Sedov return KRB5KRB_AP_ERR_MODIFIED; 600*ae771770SStanislav Sedov } 601*ae771770SStanislav Sedov return 0; 602*ae771770SStanislav Sedov } 603*ae771770SStanislav Sedov 604*ae771770SStanislav Sedov 605*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV 606*ae771770SStanislav Sedov decrypt_tkt (krb5_context context, 607*ae771770SStanislav Sedov krb5_keyblock *key, 608*ae771770SStanislav Sedov krb5_key_usage usage, 609*ae771770SStanislav Sedov krb5_const_pointer decrypt_arg, 610*ae771770SStanislav Sedov krb5_kdc_rep *dec_rep) 611*ae771770SStanislav Sedov { 612*ae771770SStanislav Sedov krb5_error_code ret; 613*ae771770SStanislav Sedov krb5_data data; 614*ae771770SStanislav Sedov size_t size; 615*ae771770SStanislav Sedov krb5_crypto crypto; 616*ae771770SStanislav Sedov 617*ae771770SStanislav Sedov ret = krb5_crypto_init(context, key, 0, &crypto); 618*ae771770SStanislav Sedov if (ret) 619*ae771770SStanislav Sedov return ret; 620*ae771770SStanislav Sedov 621*ae771770SStanislav Sedov ret = krb5_decrypt_EncryptedData (context, 622*ae771770SStanislav Sedov crypto, 623*ae771770SStanislav Sedov usage, 624*ae771770SStanislav Sedov &dec_rep->kdc_rep.enc_part, 625*ae771770SStanislav Sedov &data); 626*ae771770SStanislav Sedov krb5_crypto_destroy(context, crypto); 627*ae771770SStanislav Sedov 628*ae771770SStanislav Sedov if (ret) 629*ae771770SStanislav Sedov return ret; 630*ae771770SStanislav Sedov 631*ae771770SStanislav Sedov ret = decode_EncASRepPart(data.data, 632*ae771770SStanislav Sedov data.length, 633*ae771770SStanislav Sedov &dec_rep->enc_part, 634*ae771770SStanislav Sedov &size); 635*ae771770SStanislav Sedov if (ret) 636*ae771770SStanislav Sedov ret = decode_EncTGSRepPart(data.data, 637*ae771770SStanislav Sedov data.length, 638*ae771770SStanislav Sedov &dec_rep->enc_part, 639*ae771770SStanislav Sedov &size); 640*ae771770SStanislav Sedov krb5_data_free (&data); 641*ae771770SStanislav Sedov if (ret) { 642*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 643*ae771770SStanislav Sedov N_("Failed to decode encpart in ticket", "")); 644*ae771770SStanislav Sedov return ret; 645*ae771770SStanislav Sedov } 646*ae771770SStanislav Sedov return 0; 647*ae771770SStanislav Sedov } 648*ae771770SStanislav Sedov 649*ae771770SStanislav Sedov int 650*ae771770SStanislav Sedov _krb5_extract_ticket(krb5_context context, 651*ae771770SStanislav Sedov krb5_kdc_rep *rep, 652*ae771770SStanislav Sedov krb5_creds *creds, 653*ae771770SStanislav Sedov krb5_keyblock *key, 654*ae771770SStanislav Sedov krb5_const_pointer keyseed, 655*ae771770SStanislav Sedov krb5_key_usage key_usage, 656*ae771770SStanislav Sedov krb5_addresses *addrs, 657*ae771770SStanislav Sedov unsigned nonce, 658*ae771770SStanislav Sedov unsigned flags, 659*ae771770SStanislav Sedov krb5_decrypt_proc decrypt_proc, 660*ae771770SStanislav Sedov krb5_const_pointer decryptarg) 661*ae771770SStanislav Sedov { 662*ae771770SStanislav Sedov krb5_error_code ret; 663*ae771770SStanislav Sedov krb5_principal tmp_principal; 664*ae771770SStanislav Sedov size_t len = 0; 665*ae771770SStanislav Sedov time_t tmp_time; 666*ae771770SStanislav Sedov krb5_timestamp sec_now; 667*ae771770SStanislav Sedov 668*ae771770SStanislav Sedov /* decrypt */ 669*ae771770SStanislav Sedov 670*ae771770SStanislav Sedov if (decrypt_proc == NULL) 671*ae771770SStanislav Sedov decrypt_proc = decrypt_tkt; 672*ae771770SStanislav Sedov 673*ae771770SStanislav Sedov ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); 674*ae771770SStanislav Sedov if (ret) 675*ae771770SStanislav Sedov goto out; 676*ae771770SStanislav Sedov 677*ae771770SStanislav Sedov /* save session key */ 678*ae771770SStanislav Sedov 679*ae771770SStanislav Sedov creds->session.keyvalue.length = 0; 680*ae771770SStanislav Sedov creds->session.keyvalue.data = NULL; 681*ae771770SStanislav Sedov creds->session.keytype = rep->enc_part.key.keytype; 682*ae771770SStanislav Sedov ret = krb5_data_copy (&creds->session.keyvalue, 683*ae771770SStanislav Sedov rep->enc_part.key.keyvalue.data, 684*ae771770SStanislav Sedov rep->enc_part.key.keyvalue.length); 685*ae771770SStanislav Sedov if (ret) { 686*ae771770SStanislav Sedov krb5_clear_error_message(context); 687*ae771770SStanislav Sedov goto out; 688*ae771770SStanislav Sedov } 689*ae771770SStanislav Sedov 690*ae771770SStanislav Sedov /* compare client and save */ 691*ae771770SStanislav Sedov ret = _krb5_principalname2krb5_principal (context, 692*ae771770SStanislav Sedov &tmp_principal, 693*ae771770SStanislav Sedov rep->kdc_rep.cname, 694*ae771770SStanislav Sedov rep->kdc_rep.crealm); 695*ae771770SStanislav Sedov if (ret) 696*ae771770SStanislav Sedov goto out; 697*ae771770SStanislav Sedov 698*ae771770SStanislav Sedov /* check client referral and save principal */ 699*ae771770SStanislav Sedov /* anonymous here ? */ 700*ae771770SStanislav Sedov if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) { 701*ae771770SStanislav Sedov ret = check_client_referral(context, rep, 702*ae771770SStanislav Sedov creds->client, 703*ae771770SStanislav Sedov tmp_principal, 704*ae771770SStanislav Sedov &creds->session); 705*ae771770SStanislav Sedov if (ret) { 706*ae771770SStanislav Sedov krb5_free_principal (context, tmp_principal); 707*ae771770SStanislav Sedov goto out; 708*ae771770SStanislav Sedov } 709*ae771770SStanislav Sedov } 710*ae771770SStanislav Sedov krb5_free_principal (context, creds->client); 711*ae771770SStanislav Sedov creds->client = tmp_principal; 712*ae771770SStanislav Sedov 713*ae771770SStanislav Sedov /* check server referral and save principal */ 714*ae771770SStanislav Sedov ret = _krb5_principalname2krb5_principal (context, 715*ae771770SStanislav Sedov &tmp_principal, 716*ae771770SStanislav Sedov rep->kdc_rep.ticket.sname, 717*ae771770SStanislav Sedov rep->kdc_rep.ticket.realm); 718*ae771770SStanislav Sedov if (ret) 719*ae771770SStanislav Sedov goto out; 720*ae771770SStanislav Sedov if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){ 721*ae771770SStanislav Sedov ret = check_server_referral(context, 722*ae771770SStanislav Sedov rep, 723*ae771770SStanislav Sedov flags, 724*ae771770SStanislav Sedov creds->server, 725*ae771770SStanislav Sedov tmp_principal, 726*ae771770SStanislav Sedov &creds->session); 727*ae771770SStanislav Sedov if (ret) { 728*ae771770SStanislav Sedov krb5_free_principal (context, tmp_principal); 729*ae771770SStanislav Sedov goto out; 730*ae771770SStanislav Sedov } 731*ae771770SStanislav Sedov } 732*ae771770SStanislav Sedov krb5_free_principal(context, creds->server); 733*ae771770SStanislav Sedov creds->server = tmp_principal; 734*ae771770SStanislav Sedov 735*ae771770SStanislav Sedov /* verify names */ 736*ae771770SStanislav Sedov if(flags & EXTRACT_TICKET_MATCH_REALM){ 737*ae771770SStanislav Sedov const char *srealm = krb5_principal_get_realm(context, creds->server); 738*ae771770SStanislav Sedov const char *crealm = krb5_principal_get_realm(context, creds->client); 739*ae771770SStanislav Sedov 740*ae771770SStanislav Sedov if (strcmp(rep->enc_part.srealm, srealm) != 0 || 741*ae771770SStanislav Sedov strcmp(rep->enc_part.srealm, crealm) != 0) 742*ae771770SStanislav Sedov { 743*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_MODIFIED; 744*ae771770SStanislav Sedov krb5_clear_error_message(context); 745*ae771770SStanislav Sedov goto out; 746*ae771770SStanislav Sedov } 747*ae771770SStanislav Sedov } 748*ae771770SStanislav Sedov 749*ae771770SStanislav Sedov /* compare nonces */ 750*ae771770SStanislav Sedov 751*ae771770SStanislav Sedov if (nonce != (unsigned)rep->enc_part.nonce) { 752*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_MODIFIED; 753*ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 754*ae771770SStanislav Sedov goto out; 755*ae771770SStanislav Sedov } 756*ae771770SStanislav Sedov 757*ae771770SStanislav Sedov /* set kdc-offset */ 758*ae771770SStanislav Sedov 759*ae771770SStanislav Sedov krb5_timeofday (context, &sec_now); 760*ae771770SStanislav Sedov if (rep->enc_part.flags.initial 761*ae771770SStanislav Sedov && (flags & EXTRACT_TICKET_TIMESYNC) 762*ae771770SStanislav Sedov && context->kdc_sec_offset == 0 763*ae771770SStanislav Sedov && krb5_config_get_bool (context, NULL, 764*ae771770SStanislav Sedov "libdefaults", 765*ae771770SStanislav Sedov "kdc_timesync", 766*ae771770SStanislav Sedov NULL)) { 767*ae771770SStanislav Sedov context->kdc_sec_offset = rep->enc_part.authtime - sec_now; 768*ae771770SStanislav Sedov krb5_timeofday (context, &sec_now); 769*ae771770SStanislav Sedov } 770*ae771770SStanislav Sedov 771*ae771770SStanislav Sedov /* check all times */ 772*ae771770SStanislav Sedov 773*ae771770SStanislav Sedov if (rep->enc_part.starttime) { 774*ae771770SStanislav Sedov tmp_time = *rep->enc_part.starttime; 775*ae771770SStanislav Sedov } else 776*ae771770SStanislav Sedov tmp_time = rep->enc_part.authtime; 777*ae771770SStanislav Sedov 778*ae771770SStanislav Sedov if (creds->times.starttime == 0 779*ae771770SStanislav Sedov && abs(tmp_time - sec_now) > context->max_skew) { 780*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_SKEW; 781*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 782*ae771770SStanislav Sedov N_("time skew (%d) larger than max (%d)", ""), 783*ae771770SStanislav Sedov abs(tmp_time - sec_now), 784*ae771770SStanislav Sedov (int)context->max_skew); 785*ae771770SStanislav Sedov goto out; 786*ae771770SStanislav Sedov } 787*ae771770SStanislav Sedov 788*ae771770SStanislav Sedov if (creds->times.starttime != 0 789*ae771770SStanislav Sedov && tmp_time != creds->times.starttime) { 790*ae771770SStanislav Sedov krb5_clear_error_message (context); 791*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_MODIFIED; 792*ae771770SStanislav Sedov goto out; 793*ae771770SStanislav Sedov } 794*ae771770SStanislav Sedov 795*ae771770SStanislav Sedov creds->times.starttime = tmp_time; 796*ae771770SStanislav Sedov 797*ae771770SStanislav Sedov if (rep->enc_part.renew_till) { 798*ae771770SStanislav Sedov tmp_time = *rep->enc_part.renew_till; 799*ae771770SStanislav Sedov } else 800*ae771770SStanislav Sedov tmp_time = 0; 801*ae771770SStanislav Sedov 802*ae771770SStanislav Sedov if (creds->times.renew_till != 0 803*ae771770SStanislav Sedov && tmp_time > creds->times.renew_till) { 804*ae771770SStanislav Sedov krb5_clear_error_message (context); 805*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_MODIFIED; 806*ae771770SStanislav Sedov goto out; 807*ae771770SStanislav Sedov } 808*ae771770SStanislav Sedov 809*ae771770SStanislav Sedov creds->times.renew_till = tmp_time; 810*ae771770SStanislav Sedov 811*ae771770SStanislav Sedov creds->times.authtime = rep->enc_part.authtime; 812*ae771770SStanislav Sedov 813*ae771770SStanislav Sedov if (creds->times.endtime != 0 814*ae771770SStanislav Sedov && rep->enc_part.endtime > creds->times.endtime) { 815*ae771770SStanislav Sedov krb5_clear_error_message (context); 816*ae771770SStanislav Sedov ret = KRB5KRB_AP_ERR_MODIFIED; 817*ae771770SStanislav Sedov goto out; 818*ae771770SStanislav Sedov } 819*ae771770SStanislav Sedov 820*ae771770SStanislav Sedov creds->times.endtime = rep->enc_part.endtime; 821*ae771770SStanislav Sedov 822*ae771770SStanislav Sedov if(rep->enc_part.caddr) 823*ae771770SStanislav Sedov krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); 824*ae771770SStanislav Sedov else if(addrs) 825*ae771770SStanislav Sedov krb5_copy_addresses (context, addrs, &creds->addresses); 826*ae771770SStanislav Sedov else { 827*ae771770SStanislav Sedov creds->addresses.len = 0; 828*ae771770SStanislav Sedov creds->addresses.val = NULL; 829*ae771770SStanislav Sedov } 830*ae771770SStanislav Sedov creds->flags.b = rep->enc_part.flags; 831*ae771770SStanislav Sedov 832*ae771770SStanislav Sedov creds->authdata.len = 0; 833*ae771770SStanislav Sedov creds->authdata.val = NULL; 834*ae771770SStanislav Sedov 835*ae771770SStanislav Sedov /* extract ticket */ 836*ae771770SStanislav Sedov ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, 837*ae771770SStanislav Sedov &rep->kdc_rep.ticket, &len, ret); 838*ae771770SStanislav Sedov if(ret) 839*ae771770SStanislav Sedov goto out; 840*ae771770SStanislav Sedov if (creds->ticket.length != len) 841*ae771770SStanislav Sedov krb5_abortx(context, "internal error in ASN.1 encoder"); 842*ae771770SStanislav Sedov creds->second_ticket.length = 0; 843*ae771770SStanislav Sedov creds->second_ticket.data = NULL; 844*ae771770SStanislav Sedov 845*ae771770SStanislav Sedov 846*ae771770SStanislav Sedov out: 847*ae771770SStanislav Sedov memset (rep->enc_part.key.keyvalue.data, 0, 848*ae771770SStanislav Sedov rep->enc_part.key.keyvalue.length); 849*ae771770SStanislav Sedov return ret; 850*ae771770SStanislav Sedov } 851