155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kdc_locl.h" 3555682Smarkm 3655682Smarkm#define MAX_TIME ((time_t)((1U << 31) - 1)) 3755682Smarkm 38178825Sdfrvoid 39178825Sdfr_kdc_fix_time(time_t **t) 4055682Smarkm{ 4155682Smarkm if(*t == NULL){ 4255682Smarkm ALLOC(*t); 4355682Smarkm **t = MAX_TIME; 4455682Smarkm } 4555682Smarkm if(**t == 0) **t = MAX_TIME; /* fix for old clients */ 4655682Smarkm} 4755682Smarkm 48178825Sdfrstatic int 49178825Sdfrrealloc_method_data(METHOD_DATA *md) 50178825Sdfr{ 51178825Sdfr PA_DATA *pa; 52178825Sdfr pa = realloc(md->val, (md->len + 1) * sizeof(*md->val)); 53178825Sdfr if(pa == NULL) 54178825Sdfr return ENOMEM; 55178825Sdfr md->val = pa; 56178825Sdfr md->len++; 57178825Sdfr return 0; 58178825Sdfr} 59178825Sdfr 6055682Smarkmstatic void 61233294Sstasset_salt_padata(METHOD_DATA *md, Salt *salt) 6255682Smarkm{ 6355682Smarkm if (salt) { 64233294Sstas realloc_method_data(md); 65233294Sstas md->val[md->len - 1].padata_type = salt->type; 66233294Sstas der_copy_octet_string(&salt->salt, 67233294Sstas &md->val[md->len - 1].padata_value); 6855682Smarkm } 6955682Smarkm} 7055682Smarkm 71178825Sdfrconst PA_DATA* 72178825Sdfr_kdc_find_padata(const KDC_REQ *req, int *start, int type) 7355682Smarkm{ 74178825Sdfr if (req->padata == NULL) 75178825Sdfr return NULL; 76178825Sdfr 77233294Sstas while((size_t)*start < req->padata->len){ 7855682Smarkm (*start)++; 79233294Sstas if(req->padata->val[*start - 1].padata_type == (unsigned)type) 8055682Smarkm return &req->padata->val[*start - 1]; 8155682Smarkm } 8255682Smarkm return NULL; 8355682Smarkm} 8455682Smarkm 8572445Sassar/* 86233294Sstas * This is a hack to allow predefined weak services, like afs to 87233294Sstas * still use weak types 88233294Sstas */ 89233294Sstas 90233294Sstaskrb5_boolean 91233294Sstas_kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype) 92233294Sstas{ 93233294Sstas if (principal->name.name_string.len > 0 && 94233294Sstas strcmp(principal->name.name_string.val[0], "afs") == 0 && 95233294Sstas (etype == ETYPE_DES_CBC_CRC 96233294Sstas || etype == ETYPE_DES_CBC_MD4 97233294Sstas || etype == ETYPE_DES_CBC_MD5)) 98233294Sstas return TRUE; 99233294Sstas return FALSE; 100233294Sstas} 101233294Sstas 102233294Sstas 103233294Sstas/* 104178825Sdfr * Detect if `key' is the using the the precomputed `default_salt'. 105178825Sdfr */ 106178825Sdfr 107178825Sdfrstatic krb5_boolean 108178825Sdfris_default_salt_p(const krb5_salt *default_salt, const Key *key) 109178825Sdfr{ 110178825Sdfr if (key->salt == NULL) 111178825Sdfr return TRUE; 112178825Sdfr if (default_salt->salttype != key->salt->type) 113178825Sdfr return FALSE; 114178825Sdfr if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt)) 115178825Sdfr return FALSE; 116178825Sdfr return TRUE; 117178825Sdfr} 118178825Sdfr 119178825Sdfr/* 12072445Sassar * return the first appropriate key of `princ' in `ret_key'. Look for 12172445Sassar * all the etypes in (`etypes', `len'), stopping as soon as we find 12272445Sassar * one, but preferring one that has default salt 12372445Sassar */ 12455682Smarkm 125178825Sdfrkrb5_error_code 126233294Sstas_kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key, 127233294Sstas krb5_boolean is_preauth, hdb_entry_ex *princ, 128233294Sstas krb5_enctype *etypes, unsigned len, 129233294Sstas krb5_enctype *ret_enctype, Key **ret_key) 13055682Smarkm{ 131233294Sstas krb5_error_code ret; 132233294Sstas krb5_salt def_salt; 133233294Sstas krb5_enctype enctype = ETYPE_NULL; 134233294Sstas Key *key; 13555682Smarkm int i; 13655682Smarkm 137233294Sstas /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */ 138233294Sstas ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt); 139233294Sstas if (ret) 140233294Sstas return ret; 141178825Sdfr 142233294Sstas ret = KRB5KDC_ERR_ETYPE_NOSUPP; 14355682Smarkm 144233294Sstas if (use_strongest_session_key) { 145233294Sstas const krb5_enctype *p; 146233294Sstas krb5_enctype clientbest = ETYPE_NULL; 147233294Sstas int j; 148178825Sdfr 149233294Sstas /* 150233294Sstas * Pick the strongest key that the KDC, target service, and 151233294Sstas * client all support, using the local cryptosystem enctype 152233294Sstas * list in strongest-to-weakest order to drive the search. 153233294Sstas * 154233294Sstas * This is not what RFC4120 says to do, but it encourages 155233294Sstas * adoption of stronger enctypes. This doesn't play well with 156233294Sstas * clients that have multiple Kerberos client implementations 157233294Sstas * available with different supported enctype lists. 158233294Sstas */ 159233294Sstas 160233294Sstas /* drive the search with local supported enctypes list */ 161233294Sstas p = krb5_kerberos_enctypes(context); 162233294Sstas for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) { 163233294Sstas if (krb5_enctype_valid(context, p[i]) != 0) 16472445Sassar continue; 165233294Sstas 166233294Sstas /* check that the client supports it too */ 167233294Sstas for (j = 0; j < len && enctype == ETYPE_NULL; j++) { 168233294Sstas if (p[i] != etypes[j]) 169233294Sstas continue; 170233294Sstas /* save best of union of { client, crypto system } */ 171233294Sstas if (clientbest == ETYPE_NULL) 172233294Sstas clientbest = p[i]; 173233294Sstas /* check target princ support */ 174233294Sstas ret = hdb_enctype2key(context, &princ->entry, p[i], &key); 175233294Sstas if (ret) 176233294Sstas continue; 177233294Sstas if (is_preauth && !is_default_salt_p(&def_salt, key)) 178233294Sstas continue; 179233294Sstas enctype = p[i]; 18055682Smarkm } 181233294Sstas } 182233294Sstas if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL) 183233294Sstas enctype = clientbest; 184233294Sstas else if (enctype == ETYPE_NULL) 185233294Sstas ret = KRB5KDC_ERR_ETYPE_NOSUPP; 186233294Sstas if (ret == 0 && ret_enctype != NULL) 187233294Sstas *ret_enctype = enctype; 188233294Sstas if (ret == 0 && ret_key != NULL) 189233294Sstas *ret_key = key; 190233294Sstas } else { 191233294Sstas /* 192233294Sstas * Pick the first key from the client's enctype list that is 193233294Sstas * supported by the cryptosystem and by the given principal. 194233294Sstas * 195233294Sstas * RFC4120 says we SHOULD pick the first _strong_ key from the 196233294Sstas * client's list... not the first key... If the admin disallows 197233294Sstas * weak enctypes in krb5.conf and selects this key selection 198233294Sstas * algorithm, then we get exactly what RFC4120 says. 199233294Sstas */ 200233294Sstas for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) { 201233294Sstas 202233294Sstas if (krb5_enctype_valid(context, etypes[i]) != 0 && 203233294Sstas !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) 204233294Sstas continue; 205233294Sstas 206233294Sstas while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { 207233294Sstas if (key->key.keyvalue.length == 0) { 208233294Sstas ret = KRB5KDC_ERR_NULL_KEY; 209233294Sstas continue; 210233294Sstas } 211233294Sstas if (ret_key != NULL) 212233294Sstas *ret_key = key; 213233294Sstas if (ret_enctype != NULL) 214233294Sstas *ret_enctype = etypes[i]; 215233294Sstas ret = 0; 216233294Sstas if (is_preauth && is_default_salt_p(&def_salt, key)) 217233294Sstas goto out; 218178825Sdfr } 21955682Smarkm } 22055682Smarkm } 221233294Sstas 222233294Sstasout: 223178825Sdfr krb5_free_salt (context, def_salt); 22455682Smarkm return ret; 22555682Smarkm} 22655682Smarkm 227178825Sdfrkrb5_error_code 228178825Sdfr_kdc_make_anonymous_principalname (PrincipalName *pn) 22955682Smarkm{ 23072445Sassar pn->name_type = KRB5_NT_PRINCIPAL; 23172445Sassar pn->name_string.len = 1; 23272445Sassar pn->name_string.val = malloc(sizeof(*pn->name_string.val)); 23372445Sassar if (pn->name_string.val == NULL) 23472445Sassar return ENOMEM; 23572445Sassar pn->name_string.val[0] = strdup("anonymous"); 23672445Sassar if (pn->name_string.val[0] == NULL) { 23772445Sassar free(pn->name_string.val); 23872445Sassar pn->name_string.val = NULL; 23972445Sassar return ENOMEM; 24072445Sassar } 24172445Sassar return 0; 24272445Sassar} 24372445Sassar 244178825Sdfrvoid 245233294Sstas_kdc_log_timestamp(krb5_context context, 246178825Sdfr krb5_kdc_configuration *config, 247178825Sdfr const char *type, 248233294Sstas KerberosTime authtime, KerberosTime *starttime, 249178825Sdfr KerberosTime endtime, KerberosTime *renew_till) 25055682Smarkm{ 251233294Sstas char authtime_str[100], starttime_str[100], 252178825Sdfr endtime_str[100], renewtime_str[100]; 253233294Sstas 254233294Sstas krb5_format_time(context, authtime, 255233294Sstas authtime_str, sizeof(authtime_str), TRUE); 256178825Sdfr if (starttime) 257233294Sstas krb5_format_time(context, *starttime, 258233294Sstas starttime_str, sizeof(starttime_str), TRUE); 259178825Sdfr else 260178825Sdfr strlcpy(starttime_str, "unset", sizeof(starttime_str)); 261233294Sstas krb5_format_time(context, endtime, 262233294Sstas endtime_str, sizeof(endtime_str), TRUE); 263178825Sdfr if (renew_till) 264233294Sstas krb5_format_time(context, *renew_till, 265233294Sstas renewtime_str, sizeof(renewtime_str), TRUE); 266178825Sdfr else 267178825Sdfr strlcpy(renewtime_str, "unset", sizeof(renewtime_str)); 268233294Sstas 269178825Sdfr kdc_log(context, config, 5, 270178825Sdfr "%s authtime: %s starttime: %s endtime: %s renew till: %s", 271178825Sdfr type, authtime_str, starttime_str, endtime_str, renewtime_str); 272178825Sdfr} 273178825Sdfr 274178825Sdfrstatic void 275233294Sstaslog_patypes(krb5_context context, 276178825Sdfr krb5_kdc_configuration *config, 277178825Sdfr METHOD_DATA *padata) 278178825Sdfr{ 279178825Sdfr struct rk_strpool *p = NULL; 280178825Sdfr char *str; 281233294Sstas size_t i; 282233294Sstas 283178825Sdfr for (i = 0; i < padata->len; i++) { 284178825Sdfr switch(padata->val[i].padata_type) { 285178825Sdfr case KRB5_PADATA_PK_AS_REQ: 286178825Sdfr p = rk_strpoolprintf(p, "PK-INIT(ietf)"); 287178825Sdfr break; 288178825Sdfr case KRB5_PADATA_PK_AS_REQ_WIN: 289178825Sdfr p = rk_strpoolprintf(p, "PK-INIT(win2k)"); 290178825Sdfr break; 291178825Sdfr case KRB5_PADATA_PA_PK_OCSP_RESPONSE: 292178825Sdfr p = rk_strpoolprintf(p, "OCSP"); 293178825Sdfr break; 294178825Sdfr case KRB5_PADATA_ENC_TIMESTAMP: 295178825Sdfr p = rk_strpoolprintf(p, "encrypted-timestamp"); 296178825Sdfr break; 297178825Sdfr default: 298178825Sdfr p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type); 299178825Sdfr break; 300178825Sdfr } 301178825Sdfr if (p && i + 1 < padata->len) 302178825Sdfr p = rk_strpoolprintf(p, ", "); 303178825Sdfr if (p == NULL) { 304178825Sdfr kdc_log(context, config, 0, "out of memory"); 305178825Sdfr return; 306178825Sdfr } 307178825Sdfr } 308178825Sdfr if (p == NULL) 309178825Sdfr p = rk_strpoolprintf(p, "none"); 310233294Sstas 311178825Sdfr str = rk_strpoolcollect(p); 312178825Sdfr kdc_log(context, config, 0, "Client sent patypes: %s", str); 313178825Sdfr free(str); 314178825Sdfr} 315178825Sdfr 316178825Sdfr/* 317178825Sdfr * 318178825Sdfr */ 319178825Sdfr 320178825Sdfr 321178825Sdfrkrb5_error_code 322178825Sdfr_kdc_encode_reply(krb5_context context, 323178825Sdfr krb5_kdc_configuration *config, 324233294Sstas KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, 325233294Sstas krb5_enctype etype, 326178825Sdfr int skvno, const EncryptionKey *skey, 327233294Sstas int ckvno, const EncryptionKey *reply_key, 328233294Sstas int rk_is_subkey, 329178825Sdfr const char **e_text, 330178825Sdfr krb5_data *reply) 331178825Sdfr{ 332103423Snectar unsigned char *buf; 333103423Snectar size_t buf_size; 334233294Sstas size_t len = 0; 33555682Smarkm krb5_error_code ret; 33655682Smarkm krb5_crypto crypto; 33755682Smarkm 338103423Snectar ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); 33955682Smarkm if(ret) { 340233294Sstas const char *msg = krb5_get_error_message(context, ret); 341233294Sstas kdc_log(context, config, 0, "Failed to encode ticket: %s", msg); 342233294Sstas krb5_free_error_message(context, msg); 34355682Smarkm return ret; 34455682Smarkm } 345103423Snectar if(buf_size != len) { 346103423Snectar free(buf); 347178825Sdfr kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 348103423Snectar *e_text = "KDC internal error"; 349103423Snectar return KRB5KRB_ERR_GENERIC; 350103423Snectar } 35155682Smarkm 35272445Sassar ret = krb5_crypto_init(context, skey, etype, &crypto); 35372445Sassar if (ret) { 354233294Sstas const char *msg; 355103423Snectar free(buf); 356233294Sstas msg = krb5_get_error_message(context, ret); 357233294Sstas kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 358233294Sstas krb5_free_error_message(context, msg); 35972445Sassar return ret; 36072445Sassar } 36155682Smarkm 362233294Sstas ret = krb5_encrypt_EncryptedData(context, 363103423Snectar crypto, 364103423Snectar KRB5_KU_TICKET, 365103423Snectar buf, 366103423Snectar len, 367103423Snectar skvno, 368103423Snectar &rep->ticket.enc_part); 369103423Snectar free(buf); 37055682Smarkm krb5_crypto_destroy(context, crypto); 371103423Snectar if(ret) { 372233294Sstas const char *msg = krb5_get_error_message(context, ret); 373233294Sstas kdc_log(context, config, 0, "Failed to encrypt data: %s", msg); 374233294Sstas krb5_free_error_message(context, msg); 375103423Snectar return ret; 376103423Snectar } 377233294Sstas 378178825Sdfr if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep) 379103423Snectar ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret); 38055682Smarkm else 381103423Snectar ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret); 38255682Smarkm if(ret) { 383233294Sstas const char *msg = krb5_get_error_message(context, ret); 384233294Sstas kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 385233294Sstas krb5_free_error_message(context, msg); 38655682Smarkm return ret; 38755682Smarkm } 388103423Snectar if(buf_size != len) { 389103423Snectar free(buf); 390178825Sdfr kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 391103423Snectar *e_text = "KDC internal error"; 392103423Snectar return KRB5KRB_ERR_GENERIC; 393103423Snectar } 394233294Sstas ret = krb5_crypto_init(context, reply_key, 0, &crypto); 39572445Sassar if (ret) { 396233294Sstas const char *msg = krb5_get_error_message(context, ret); 397103423Snectar free(buf); 398233294Sstas kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 399233294Sstas krb5_free_error_message(context, msg); 40072445Sassar return ret; 40172445Sassar } 40255682Smarkm if(rep->msg_type == krb_as_rep) { 40355682Smarkm krb5_encrypt_EncryptedData(context, 40455682Smarkm crypto, 40555682Smarkm KRB5_KU_AS_REP_ENC_PART, 406103423Snectar buf, 40755682Smarkm len, 40855682Smarkm ckvno, 40955682Smarkm &rep->enc_part); 410103423Snectar free(buf); 411103423Snectar ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret); 41255682Smarkm } else { 41355682Smarkm krb5_encrypt_EncryptedData(context, 41455682Smarkm crypto, 415233294Sstas rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION, 416103423Snectar buf, 41755682Smarkm len, 41855682Smarkm ckvno, 41955682Smarkm &rep->enc_part); 420103423Snectar free(buf); 421103423Snectar ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret); 42255682Smarkm } 42355682Smarkm krb5_crypto_destroy(context, crypto); 42455682Smarkm if(ret) { 425233294Sstas const char *msg = krb5_get_error_message(context, ret); 426233294Sstas kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 427233294Sstas krb5_free_error_message(context, msg); 42855682Smarkm return ret; 42955682Smarkm } 430103423Snectar if(buf_size != len) { 431103423Snectar free(buf); 432178825Sdfr kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 433103423Snectar *e_text = "KDC internal error"; 434103423Snectar return KRB5KRB_ERR_GENERIC; 435103423Snectar } 436103423Snectar reply->data = buf; 437103423Snectar reply->length = buf_size; 43855682Smarkm return 0; 43955682Smarkm} 44055682Smarkm 441178825Sdfr/* 442178825Sdfr * Return 1 if the client have only older enctypes, this is for 443178825Sdfr * determining if the server should send ETYPE_INFO2 or not. 444178825Sdfr */ 445178825Sdfr 44655682Smarkmstatic int 447178825Sdfrolder_enctype(krb5_enctype enctype) 44855682Smarkm{ 449178825Sdfr switch (enctype) { 450178825Sdfr case ETYPE_DES_CBC_CRC: 451178825Sdfr case ETYPE_DES_CBC_MD4: 452178825Sdfr case ETYPE_DES_CBC_MD5: 453178825Sdfr case ETYPE_DES3_CBC_SHA1: 454178825Sdfr case ETYPE_ARCFOUR_HMAC_MD5: 455178825Sdfr case ETYPE_ARCFOUR_HMAC_MD5_56: 456233294Sstas /* 457178825Sdfr * The following three is "old" windows enctypes and is needed for 458178825Sdfr * windows 2000 hosts. 459178825Sdfr */ 460178825Sdfr case ETYPE_ARCFOUR_MD4: 461178825Sdfr case ETYPE_ARCFOUR_HMAC_OLD: 462178825Sdfr case ETYPE_ARCFOUR_HMAC_OLD_EXP: 463178825Sdfr return 1; 464178825Sdfr default: 465178825Sdfr return 0; 466178825Sdfr } 46755682Smarkm} 46855682Smarkm 469178825Sdfr/* 470178825Sdfr * 471178825Sdfr */ 472178825Sdfr 47355682Smarkmstatic krb5_error_code 474178825Sdfrmake_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key) 47555682Smarkm{ 476102644Snectar ent->etype = key->key.keytype; 477102644Snectar if(key->salt){ 478178825Sdfr#if 0 479102644Snectar ALLOC(ent->salttype); 480178825Sdfr 481102644Snectar if(key->salt->type == hdb_pw_salt) 482102644Snectar *ent->salttype = 0; /* or 1? or NULL? */ 483102644Snectar else if(key->salt->type == hdb_afs3_salt) 484102644Snectar *ent->salttype = 2; 485102644Snectar else { 486233294Sstas kdc_log(context, config, 0, "unknown salt-type: %d", 487102644Snectar key->salt->type); 488102644Snectar return KRB5KRB_ERR_GENERIC; 489102644Snectar } 490102644Snectar /* according to `the specs', we can't send a salt if 491102644Snectar we have AFS3 salted key, but that requires that you 492102644Snectar *know* what cell you are using (e.g by assuming 493102644Snectar that the cell is the same as the realm in lower 494102644Snectar case) */ 495178825Sdfr#elif 0 496178825Sdfr ALLOC(ent->salttype); 497178825Sdfr *ent->salttype = key->salt->type; 498102644Snectar#else 499233294Sstas /* 500178825Sdfr * We shouldn't sent salttype since it is incompatible with the 501178825Sdfr * specification and it breaks windows clients. The afs 502178825Sdfr * salting problem is solved by using KRB5-PADATA-AFS3-SALT 503178825Sdfr * implemented in Heimdal 0.7 and later. 504178825Sdfr */ 505178825Sdfr ent->salttype = NULL; 506102644Snectar#endif 507102644Snectar krb5_copy_data(context, &key->salt->salt, 508102644Snectar &ent->salt); 509102644Snectar } else { 510102644Snectar /* we return no salt type at all, as that should indicate 511102644Snectar * the default salt type and make everybody happy. some 512102644Snectar * systems (like w2k) dislike being told the salt type 513102644Snectar * here. */ 514102644Snectar 515102644Snectar ent->salttype = NULL; 516102644Snectar ent->salt = NULL; 517102644Snectar } 518102644Snectar return 0; 519102644Snectar} 520102644Snectar 521102644Snectarstatic krb5_error_code 522233294Sstasget_pa_etype_info(krb5_context context, 523178825Sdfr krb5_kdc_configuration *config, 524233294Sstas METHOD_DATA *md, Key *ckey) 525102644Snectar{ 52655682Smarkm krb5_error_code ret = 0; 52755682Smarkm ETYPE_INFO pa; 52855682Smarkm unsigned char *buf; 52955682Smarkm size_t len; 53055682Smarkm 531233294Sstas 532233294Sstas pa.len = 1; 533233294Sstas pa.val = calloc(1, sizeof(pa.val[0])); 53455682Smarkm if(pa.val == NULL) 53555682Smarkm return ENOMEM; 53672445Sassar 537233294Sstas ret = make_etype_info_entry(context, &pa.val[0], ckey); 538233294Sstas if (ret) { 539233294Sstas free_ETYPE_INFO(&pa); 540233294Sstas return ret; 54155682Smarkm } 542102644Snectar 543103423Snectar ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret); 54455682Smarkm free_ETYPE_INFO(&pa); 545103423Snectar if(ret) 54655682Smarkm return ret; 54755682Smarkm ret = realloc_method_data(md); 54855682Smarkm if(ret) { 54955682Smarkm free(buf); 55055682Smarkm return ret; 55155682Smarkm } 55272445Sassar md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; 55355682Smarkm md->val[md->len - 1].padata_value.length = len; 55455682Smarkm md->val[md->len - 1].padata_value.data = buf; 55555682Smarkm return 0; 55655682Smarkm} 55755682Smarkm 55872445Sassar/* 559178825Sdfr * 560178825Sdfr */ 561178825Sdfr 562178825Sdfrextern int _krb5_AES_string_to_default_iterator; 563178825Sdfr 564178825Sdfrstatic krb5_error_code 565178825Sdfrmake_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key) 566178825Sdfr{ 567178825Sdfr ent->etype = key->key.keytype; 568178825Sdfr if(key->salt) { 569178825Sdfr ALLOC(ent->salt); 570178825Sdfr if (ent->salt == NULL) 571178825Sdfr return ENOMEM; 572178825Sdfr *ent->salt = malloc(key->salt->salt.length + 1); 573178825Sdfr if (*ent->salt == NULL) { 574178825Sdfr free(ent->salt); 575178825Sdfr ent->salt = NULL; 576178825Sdfr return ENOMEM; 577178825Sdfr } 578178825Sdfr memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length); 579178825Sdfr (*ent->salt)[key->salt->salt.length] = '\0'; 580178825Sdfr } else 581178825Sdfr ent->salt = NULL; 582178825Sdfr 583178825Sdfr ent->s2kparams = NULL; 584178825Sdfr 585178825Sdfr switch (key->key.keytype) { 586178825Sdfr case ETYPE_AES128_CTS_HMAC_SHA1_96: 587178825Sdfr case ETYPE_AES256_CTS_HMAC_SHA1_96: 588178825Sdfr ALLOC(ent->s2kparams); 589178825Sdfr if (ent->s2kparams == NULL) 590178825Sdfr return ENOMEM; 591178825Sdfr ent->s2kparams->length = 4; 592178825Sdfr ent->s2kparams->data = malloc(ent->s2kparams->length); 593178825Sdfr if (ent->s2kparams->data == NULL) { 594178825Sdfr free(ent->s2kparams); 595178825Sdfr ent->s2kparams = NULL; 596178825Sdfr return ENOMEM; 597178825Sdfr } 598233294Sstas _krb5_put_int(ent->s2kparams->data, 599233294Sstas _krb5_AES_string_to_default_iterator, 600178825Sdfr ent->s2kparams->length); 601178825Sdfr break; 602178825Sdfr case ETYPE_DES_CBC_CRC: 603178825Sdfr case ETYPE_DES_CBC_MD4: 604178825Sdfr case ETYPE_DES_CBC_MD5: 605178825Sdfr /* Check if this was a AFS3 salted key */ 606178825Sdfr if(key->salt && key->salt->type == hdb_afs3_salt){ 607178825Sdfr ALLOC(ent->s2kparams); 608178825Sdfr if (ent->s2kparams == NULL) 609178825Sdfr return ENOMEM; 610178825Sdfr ent->s2kparams->length = 1; 611178825Sdfr ent->s2kparams->data = malloc(ent->s2kparams->length); 612178825Sdfr if (ent->s2kparams->data == NULL) { 613178825Sdfr free(ent->s2kparams); 614178825Sdfr ent->s2kparams = NULL; 615178825Sdfr return ENOMEM; 616178825Sdfr } 617233294Sstas _krb5_put_int(ent->s2kparams->data, 618178825Sdfr 1, 619178825Sdfr ent->s2kparams->length); 620178825Sdfr } 621178825Sdfr break; 622178825Sdfr default: 623178825Sdfr break; 624178825Sdfr } 625178825Sdfr return 0; 626178825Sdfr} 627178825Sdfr 628178825Sdfr/* 629178825Sdfr * Return an ETYPE-INFO2. Enctypes are storted the same way as in the 630178825Sdfr * database (client supported enctypes first, then the unsupported 631178825Sdfr * enctypes). 632178825Sdfr */ 633178825Sdfr 634178825Sdfrstatic krb5_error_code 635233294Sstasget_pa_etype_info2(krb5_context context, 636178825Sdfr krb5_kdc_configuration *config, 637233294Sstas METHOD_DATA *md, Key *ckey) 638178825Sdfr{ 639178825Sdfr krb5_error_code ret = 0; 640178825Sdfr ETYPE_INFO2 pa; 641178825Sdfr unsigned char *buf; 642178825Sdfr size_t len; 643178825Sdfr 644233294Sstas pa.len = 1; 645233294Sstas pa.val = calloc(1, sizeof(pa.val[0])); 646178825Sdfr if(pa.val == NULL) 647178825Sdfr return ENOMEM; 648178825Sdfr 649233294Sstas ret = make_etype_info2_entry(&pa.val[0], ckey); 650233294Sstas if (ret) { 651233294Sstas free_ETYPE_INFO2(&pa); 652233294Sstas return ret; 653178825Sdfr } 654178825Sdfr 655178825Sdfr ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret); 656178825Sdfr free_ETYPE_INFO2(&pa); 657178825Sdfr if(ret) 658178825Sdfr return ret; 659178825Sdfr ret = realloc_method_data(md); 660178825Sdfr if(ret) { 661178825Sdfr free(buf); 662178825Sdfr return ret; 663178825Sdfr } 664178825Sdfr md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2; 665178825Sdfr md->val[md->len - 1].padata_value.length = len; 666178825Sdfr md->val[md->len - 1].padata_value.data = buf; 667178825Sdfr return 0; 668178825Sdfr} 669178825Sdfr 670178825Sdfr/* 671178825Sdfr * 672178825Sdfr */ 673178825Sdfr 674178825Sdfrstatic void 675178825Sdfrlog_as_req(krb5_context context, 676178825Sdfr krb5_kdc_configuration *config, 677178825Sdfr krb5_enctype cetype, 678178825Sdfr krb5_enctype setype, 679178825Sdfr const KDC_REQ_BODY *b) 680178825Sdfr{ 681178825Sdfr krb5_error_code ret; 682233294Sstas struct rk_strpool *p; 683178825Sdfr char *str; 684233294Sstas size_t i; 685233294Sstas 686233294Sstas p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: "); 687233294Sstas 688178825Sdfr for (i = 0; i < b->etype.len; i++) { 689178825Sdfr ret = krb5_enctype_to_string(context, b->etype.val[i], &str); 690178825Sdfr if (ret == 0) { 691178825Sdfr p = rk_strpoolprintf(p, "%s", str); 692178825Sdfr free(str); 693178825Sdfr } else 694178825Sdfr p = rk_strpoolprintf(p, "%d", b->etype.val[i]); 695178825Sdfr if (p && i + 1 < b->etype.len) 696178825Sdfr p = rk_strpoolprintf(p, ", "); 697178825Sdfr if (p == NULL) { 698178825Sdfr kdc_log(context, config, 0, "out of memory"); 699178825Sdfr return; 700178825Sdfr } 701178825Sdfr } 702178825Sdfr if (p == NULL) 703178825Sdfr p = rk_strpoolprintf(p, "no encryption types"); 704178825Sdfr 705178825Sdfr { 706178825Sdfr char *cet; 707178825Sdfr char *set; 708178825Sdfr 709178825Sdfr ret = krb5_enctype_to_string(context, cetype, &cet); 710178825Sdfr if(ret == 0) { 711178825Sdfr ret = krb5_enctype_to_string(context, setype, &set); 712178825Sdfr if (ret == 0) { 713233294Sstas p = rk_strpoolprintf(p, ", using %s/%s", cet, set); 714178825Sdfr free(set); 715178825Sdfr } 716178825Sdfr free(cet); 717178825Sdfr } 718178825Sdfr if (ret != 0) 719233294Sstas p = rk_strpoolprintf(p, ", using enctypes %d/%d", 720233294Sstas cetype, setype); 721178825Sdfr } 722233294Sstas 723233294Sstas str = rk_strpoolcollect(p); 724233294Sstas kdc_log(context, config, 0, "%s", str); 725233294Sstas free(str); 726233294Sstas 727178825Sdfr { 728178825Sdfr char fixedstr[128]; 729233294Sstas unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(), 730178825Sdfr fixedstr, sizeof(fixedstr)); 731178825Sdfr if(*fixedstr) 732233294Sstas kdc_log(context, config, 0, "Requested flags: %s", fixedstr); 733178825Sdfr } 734178825Sdfr} 735178825Sdfr 736178825Sdfr/* 73772445Sassar * verify the flags on `client' and `server', returning 0 73872445Sassar * if they are OK and generating an error messages and returning 73972445Sassar * and error code otherwise. 74072445Sassar */ 74172445Sassar 74272445Sassarkrb5_error_code 743233294Sstaskdc_check_flags(krb5_context context, 744233294Sstas krb5_kdc_configuration *config, 745233294Sstas hdb_entry_ex *client_ex, const char *client_name, 746233294Sstas hdb_entry_ex *server_ex, const char *server_name, 747233294Sstas krb5_boolean is_as_req) 74855682Smarkm{ 749178825Sdfr if(client_ex != NULL) { 750178825Sdfr hdb_entry *client = &client_ex->entry; 751178825Sdfr 75255682Smarkm /* check client */ 753233294Sstas if (client->flags.locked_out) { 754233294Sstas kdc_log(context, config, 0, 755233294Sstas "Client (%s) is locked out", client_name); 756233294Sstas return KRB5KDC_ERR_POLICY; 757233294Sstas } 758233294Sstas 75955682Smarkm if (client->flags.invalid) { 760233294Sstas kdc_log(context, config, 0, 761178825Sdfr "Client (%s) has invalid bit set", client_name); 76255682Smarkm return KRB5KDC_ERR_POLICY; 76355682Smarkm } 764233294Sstas 76555682Smarkm if(!client->flags.client){ 766178825Sdfr kdc_log(context, config, 0, 767178825Sdfr "Principal may not act as client -- %s", client_name); 76855682Smarkm return KRB5KDC_ERR_POLICY; 76955682Smarkm } 770233294Sstas 77155682Smarkm if (client->valid_start && *client->valid_start > kdc_time) { 772178825Sdfr char starttime_str[100]; 773233294Sstas krb5_format_time(context, *client->valid_start, 774233294Sstas starttime_str, sizeof(starttime_str), TRUE); 775178825Sdfr kdc_log(context, config, 0, 776233294Sstas "Client not yet valid until %s -- %s", 777178825Sdfr starttime_str, client_name); 77855682Smarkm return KRB5KDC_ERR_CLIENT_NOTYET; 77955682Smarkm } 780233294Sstas 78155682Smarkm if (client->valid_end && *client->valid_end < kdc_time) { 782178825Sdfr char endtime_str[100]; 783233294Sstas krb5_format_time(context, *client->valid_end, 784233294Sstas endtime_str, sizeof(endtime_str), TRUE); 785178825Sdfr kdc_log(context, config, 0, 786178825Sdfr "Client expired at %s -- %s", 787178825Sdfr endtime_str, client_name); 78855682Smarkm return KRB5KDC_ERR_NAME_EXP; 78955682Smarkm } 790233294Sstas 791233294Sstas if (client->pw_end && *client->pw_end < kdc_time 792178825Sdfr && (server_ex == NULL || !server_ex->entry.flags.change_pw)) { 793178825Sdfr char pwend_str[100]; 794233294Sstas krb5_format_time(context, *client->pw_end, 795233294Sstas pwend_str, sizeof(pwend_str), TRUE); 796178825Sdfr kdc_log(context, config, 0, 797233294Sstas "Client's key has expired at %s -- %s", 798178825Sdfr pwend_str, client_name); 79955682Smarkm return KRB5KDC_ERR_KEY_EXPIRED; 80055682Smarkm } 80155682Smarkm } 80255682Smarkm 80355682Smarkm /* check server */ 804233294Sstas 805178825Sdfr if (server_ex != NULL) { 806178825Sdfr hdb_entry *server = &server_ex->entry; 807178825Sdfr 808233294Sstas if (server->flags.locked_out) { 809233294Sstas kdc_log(context, config, 0, 810233294Sstas "Client server locked out -- %s", server_name); 811233294Sstas return KRB5KDC_ERR_POLICY; 812233294Sstas } 81355682Smarkm if (server->flags.invalid) { 814178825Sdfr kdc_log(context, config, 0, 815178825Sdfr "Server has invalid flag set -- %s", server_name); 81655682Smarkm return KRB5KDC_ERR_POLICY; 81755682Smarkm } 81855682Smarkm 81955682Smarkm if(!server->flags.server){ 820178825Sdfr kdc_log(context, config, 0, 821178825Sdfr "Principal may not act as server -- %s", server_name); 82255682Smarkm return KRB5KDC_ERR_POLICY; 82355682Smarkm } 82455682Smarkm 82555682Smarkm if(!is_as_req && server->flags.initial) { 826178825Sdfr kdc_log(context, config, 0, 827178825Sdfr "AS-REQ is required for server -- %s", server_name); 82855682Smarkm return KRB5KDC_ERR_POLICY; 82955682Smarkm } 83055682Smarkm 83155682Smarkm if (server->valid_start && *server->valid_start > kdc_time) { 832178825Sdfr char starttime_str[100]; 833233294Sstas krb5_format_time(context, *server->valid_start, 834233294Sstas starttime_str, sizeof(starttime_str), TRUE); 835178825Sdfr kdc_log(context, config, 0, 836178825Sdfr "Server not yet valid until %s -- %s", 837178825Sdfr starttime_str, server_name); 83855682Smarkm return KRB5KDC_ERR_SERVICE_NOTYET; 83955682Smarkm } 84055682Smarkm 84155682Smarkm if (server->valid_end && *server->valid_end < kdc_time) { 842178825Sdfr char endtime_str[100]; 843233294Sstas krb5_format_time(context, *server->valid_end, 844233294Sstas endtime_str, sizeof(endtime_str), TRUE); 845178825Sdfr kdc_log(context, config, 0, 846233294Sstas "Server expired at %s -- %s", 847178825Sdfr endtime_str, server_name); 84855682Smarkm return KRB5KDC_ERR_SERVICE_EXP; 84955682Smarkm } 85055682Smarkm 85155682Smarkm if (server->pw_end && *server->pw_end < kdc_time) { 852178825Sdfr char pwend_str[100]; 853233294Sstas krb5_format_time(context, *server->pw_end, 854233294Sstas pwend_str, sizeof(pwend_str), TRUE); 855178825Sdfr kdc_log(context, config, 0, 856233294Sstas "Server's key has expired at -- %s", 857178825Sdfr pwend_str, server_name); 85855682Smarkm return KRB5KDC_ERR_KEY_EXPIRED; 85955682Smarkm } 86055682Smarkm } 86155682Smarkm return 0; 86255682Smarkm} 86355682Smarkm 86472445Sassar/* 86572445Sassar * Return TRUE if `from' is part of `addresses' taking into consideration 86672445Sassar * the configuration variables that tells us how strict we should be about 86772445Sassar * these checks 86872445Sassar */ 86972445Sassar 870178825Sdfrkrb5_boolean 871233294Sstas_kdc_check_addresses(krb5_context context, 872178825Sdfr krb5_kdc_configuration *config, 873178825Sdfr HostAddresses *addresses, const struct sockaddr *from) 87455682Smarkm{ 87555682Smarkm krb5_error_code ret; 87655682Smarkm krb5_address addr; 87772445Sassar krb5_boolean result; 878178825Sdfr krb5_boolean only_netbios = TRUE; 879233294Sstas size_t i; 880233294Sstas 881178825Sdfr if(config->check_ticket_addresses == 0) 88255682Smarkm return TRUE; 88355682Smarkm 88455682Smarkm if(addresses == NULL) 885178825Sdfr return config->allow_null_ticket_addresses; 886233294Sstas 887178825Sdfr for (i = 0; i < addresses->len; ++i) { 888178825Sdfr if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) { 889178825Sdfr only_netbios = FALSE; 890178825Sdfr } 891178825Sdfr } 892178825Sdfr 893178825Sdfr /* Windows sends it's netbios name, which I can only assume is 894178825Sdfr * used for the 'allowed workstations' check. This is painful, 895178825Sdfr * but we still want to check IP addresses if they happen to be 896178825Sdfr * present. 897178825Sdfr */ 898178825Sdfr 899178825Sdfr if(only_netbios) 900178825Sdfr return config->allow_null_ticket_addresses; 901178825Sdfr 90278527Sassar ret = krb5_sockaddr2address (context, from, &addr); 90355682Smarkm if(ret) 90455682Smarkm return FALSE; 90555682Smarkm 90672445Sassar result = krb5_address_search(context, &addr, addresses); 90772445Sassar krb5_free_address (context, &addr); 90872445Sassar return result; 90955682Smarkm} 91055682Smarkm 911178825Sdfr/* 912178825Sdfr * 913178825Sdfr */ 914178825Sdfr 915178825Sdfrstatic krb5_boolean 916178825Sdfrsend_pac_p(krb5_context context, KDC_REQ *req) 917178825Sdfr{ 918178825Sdfr krb5_error_code ret; 919178825Sdfr PA_PAC_REQUEST pacreq; 920178825Sdfr const PA_DATA *pa; 921178825Sdfr int i = 0; 922233294Sstas 923178825Sdfr pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST); 924178825Sdfr if (pa == NULL) 925178825Sdfr return TRUE; 926178825Sdfr 927178825Sdfr ret = decode_PA_PAC_REQUEST(pa->padata_value.data, 928178825Sdfr pa->padata_value.length, 929178825Sdfr &pacreq, 930178825Sdfr NULL); 931178825Sdfr if (ret) 932178825Sdfr return TRUE; 933178825Sdfr i = pacreq.include_pac; 934178825Sdfr free_PA_PAC_REQUEST(&pacreq); 935178825Sdfr if (i == 0) 936178825Sdfr return FALSE; 937178825Sdfr return TRUE; 938178825Sdfr} 939178825Sdfr 940233294Sstaskrb5_boolean 941233294Sstas_kdc_is_anonymous(krb5_context context, krb5_principal principal) 942233294Sstas{ 943233294Sstas if (principal->name.name_type != KRB5_NT_WELLKNOWN || 944233294Sstas principal->name.name_string.len != 2 || 945233294Sstas strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 || 946233294Sstas strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0) 947233294Sstas return 0; 948233294Sstas return 1; 949233294Sstas} 950233294Sstas 951178825Sdfr/* 952178825Sdfr * 953178825Sdfr */ 954178825Sdfr 95555682Smarkmkrb5_error_code 956233294Sstas_kdc_as_rep(krb5_context context, 957178825Sdfr krb5_kdc_configuration *config, 958233294Sstas KDC_REQ *req, 959233294Sstas const krb5_data *req_buffer, 960178825Sdfr krb5_data *reply, 961178825Sdfr const char *from, 962178825Sdfr struct sockaddr *from_addr, 963178825Sdfr int datagram_reply) 96455682Smarkm{ 96555682Smarkm KDC_REQ_BODY *b = &req->req_body; 96655682Smarkm AS_REP rep; 96755682Smarkm KDCOptions f = b->kdc_options; 968178825Sdfr hdb_entry_ex *client = NULL, *server = NULL; 969233294Sstas HDB *clientdb; 970233294Sstas krb5_enctype setype, sessionetype; 971178825Sdfr krb5_data e_data; 97255682Smarkm EncTicketPart et; 97355682Smarkm EncKDCRepPart ek; 974127808Snectar krb5_principal client_princ = NULL, server_princ = NULL; 975127808Snectar char *client_name = NULL, *server_name = NULL; 97655682Smarkm krb5_error_code ret = 0; 97755682Smarkm const char *e_text = NULL; 97855682Smarkm krb5_crypto crypto; 97955682Smarkm Key *ckey, *skey; 980233294Sstas EncryptionKey *reply_key = NULL, session_key; 981233294Sstas int flags = HDB_F_FOR_AS_REQ; 982178825Sdfr#ifdef PKINIT 983178825Sdfr pk_client_params *pkp = NULL; 984178825Sdfr#endif 98555682Smarkm 98672445Sassar memset(&rep, 0, sizeof(rep)); 987233294Sstas memset(&session_key, 0, sizeof(session_key)); 988178825Sdfr krb5_data_zero(&e_data); 98972445Sassar 990233294Sstas ALLOC(rep.padata); 991233294Sstas rep.padata->len = 0; 992233294Sstas rep.padata->val = NULL; 993233294Sstas 994178825Sdfr if (f.canonicalize) 995178825Sdfr flags |= HDB_F_CANON; 996178825Sdfr 99755682Smarkm if(b->sname == NULL){ 99855682Smarkm ret = KRB5KRB_ERR_GENERIC; 99955682Smarkm e_text = "No server in request"; 100055682Smarkm } else{ 1001178825Sdfr ret = _krb5_principalname2krb5_principal (context, 1002178825Sdfr &server_princ, 1003178825Sdfr *(b->sname), 1004178825Sdfr b->realm); 1005178825Sdfr if (ret == 0) 1006178825Sdfr ret = krb5_unparse_name(context, server_princ, &server_name); 100755682Smarkm } 1008127808Snectar if (ret) { 1009233294Sstas kdc_log(context, config, 0, 1010178825Sdfr "AS-REQ malformed server name from %s", from); 1011127808Snectar goto out; 1012127808Snectar } 101355682Smarkm if(b->cname == NULL){ 101455682Smarkm ret = KRB5KRB_ERR_GENERIC; 101555682Smarkm e_text = "No client in request"; 101655682Smarkm } else { 1017233294Sstas ret = _krb5_principalname2krb5_principal (context, 1018233294Sstas &client_princ, 1019233294Sstas *(b->cname), 1020233294Sstas b->realm); 1021233294Sstas if (ret) 1022233294Sstas goto out; 1023178825Sdfr 1024178825Sdfr ret = krb5_unparse_name(context, client_princ, &client_name); 102555682Smarkm } 1026127808Snectar if (ret) { 1027178825Sdfr kdc_log(context, config, 0, 1028178825Sdfr "AS-REQ malformed client name from %s", from); 102955682Smarkm goto out; 1030127808Snectar } 103155682Smarkm 1032233294Sstas kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 1033178825Sdfr client_name, from, server_name); 1034127808Snectar 1035233294Sstas /* 1036233294Sstas * 1037233294Sstas */ 1038233294Sstas 1039233294Sstas if (_kdc_is_anonymous(context, client_princ)) { 1040233294Sstas if (!b->kdc_options.request_anonymous) { 1041233294Sstas kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag"); 1042233294Sstas ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1043233294Sstas goto out; 1044233294Sstas } 1045233294Sstas } else if (b->kdc_options.request_anonymous) { 1046233294Sstas kdc_log(context, config, 0, 1047233294Sstas "Request for a anonymous ticket with non " 1048233294Sstas "anonymous client name: %s", client_name); 104955682Smarkm ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 105055682Smarkm goto out; 105155682Smarkm } 105255682Smarkm 1053233294Sstas /* 1054233294Sstas * 1055233294Sstas */ 1056233294Sstas 1057233294Sstas ret = _kdc_db_fetch(context, config, client_princ, 1058233294Sstas HDB_F_GET_CLIENT | flags, NULL, 1059233294Sstas &clientdb, &client); 1060233294Sstas if(ret == HDB_ERR_NOT_FOUND_HERE) { 1061233294Sstas kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name); 1062233294Sstas goto out; 1063233294Sstas } else if(ret){ 1064233294Sstas const char *msg = krb5_get_error_message(context, ret); 1065233294Sstas kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg); 1066233294Sstas krb5_free_error_message(context, msg); 1067233294Sstas ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1068233294Sstas goto out; 1069233294Sstas } 1070178825Sdfr ret = _kdc_db_fetch(context, config, server_princ, 1071233294Sstas HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags, 1072233294Sstas NULL, NULL, &server); 1073233294Sstas if(ret == HDB_ERR_NOT_FOUND_HERE) { 1074233294Sstas kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name); 1075233294Sstas goto out; 1076233294Sstas } else if(ret){ 1077233294Sstas const char *msg = krb5_get_error_message(context, ret); 1078233294Sstas kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg); 1079233294Sstas krb5_free_error_message(context, msg); 108055682Smarkm ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 108155682Smarkm goto out; 108255682Smarkm } 108355682Smarkm 1084233294Sstas memset(&et, 0, sizeof(et)); 1085233294Sstas memset(&ek, 0, sizeof(ek)); 108655682Smarkm 1087233294Sstas /* 1088233294Sstas * Select a session enctype from the list of the crypto system 1089233294Sstas * supported enctypes that is supported by the client and is one of 1090233294Sstas * the enctype of the enctype of the service (likely krbtgt). 1091233294Sstas * 1092233294Sstas * The latter is used as a hint of what enctypes all KDC support, 1093233294Sstas * to make sure a newer version of KDC won't generate a session 1094233294Sstas * enctype that an older version of a KDC in the same realm can't 1095233294Sstas * decrypt. 1096233294Sstas */ 1097234027Sstas ret = _kdc_find_etype(context, 1098234027Sstas krb5_principal_is_krbtgt(context, server_princ) ? 1099234027Sstas config->tgt_use_strongest_session_key : 1100234027Sstas config->svc_use_strongest_session_key, FALSE, 1101233294Sstas client, b->etype.val, b->etype.len, &sessionetype, 1102233294Sstas NULL); 1103233294Sstas if (ret) { 1104233294Sstas kdc_log(context, config, 0, 1105233294Sstas "Client (%s) from %s has no common enctypes with KDC " 1106233294Sstas "to use for the session key", 1107233294Sstas client_name, from); 1108178825Sdfr goto out; 1109233294Sstas } 1110233294Sstas /* 1111233294Sstas * But if the KDC admin is paranoid and doesn't want to have "not 1112233294Sstas * the best" enctypes on the krbtgt, lets save the best pick from 1113233294Sstas * the client list and hope that that will work for any other 1114233294Sstas * KDCs. 1115233294Sstas */ 1116178825Sdfr 1117233294Sstas /* 1118233294Sstas * Pre-auth processing 1119233294Sstas */ 112055682Smarkm 112155682Smarkm if(req->padata){ 1122178825Sdfr int i; 1123178825Sdfr const PA_DATA *pa; 112455682Smarkm int found_pa = 0; 1125178825Sdfr 1126178825Sdfr log_patypes(context, config, req->padata); 1127178825Sdfr 1128178825Sdfr#ifdef PKINIT 1129233294Sstas kdc_log(context, config, 5, 1130178825Sdfr "Looking for PKINIT pa-data -- %s", client_name); 1131178825Sdfr 1132178825Sdfr e_text = "No PKINIT PA found"; 1133178825Sdfr 1134178825Sdfr i = 0; 1135233294Sstas pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ); 1136178825Sdfr if (pa == NULL) { 1137178825Sdfr i = 0; 1138233294Sstas pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN); 1139178825Sdfr } 1140178825Sdfr if (pa) { 1141178825Sdfr char *client_cert = NULL; 1142178825Sdfr 1143233294Sstas ret = _kdc_pk_rd_padata(context, config, req, pa, client, &pkp); 1144178825Sdfr if (ret) { 1145178825Sdfr ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 1146233294Sstas kdc_log(context, config, 5, 1147233294Sstas "Failed to decode PKINIT PA-DATA -- %s", 1148178825Sdfr client_name); 1149178825Sdfr goto ts_enc; 1150178825Sdfr } 1151178825Sdfr if (ret == 0 && pkp == NULL) 1152178825Sdfr goto ts_enc; 1153178825Sdfr 1154178825Sdfr ret = _kdc_pk_check_client(context, 1155178825Sdfr config, 1156233294Sstas clientdb, 1157178825Sdfr client, 1158178825Sdfr pkp, 1159178825Sdfr &client_cert); 1160178825Sdfr if (ret) { 1161178825Sdfr e_text = "PKINIT certificate not allowed to " 1162178825Sdfr "impersonate principal"; 1163178825Sdfr _kdc_pk_free_client_param(context, pkp); 1164178825Sdfr 1165178825Sdfr kdc_log(context, config, 0, "%s", e_text); 1166178825Sdfr pkp = NULL; 1167178825Sdfr goto out; 1168178825Sdfr } 1169233294Sstas 1170178825Sdfr found_pa = 1; 1171178825Sdfr et.flags.pre_authent = 1; 1172178825Sdfr kdc_log(context, config, 0, 1173233294Sstas "PKINIT pre-authentication succeeded -- %s using %s", 1174178825Sdfr client_name, client_cert); 1175178825Sdfr free(client_cert); 1176178825Sdfr if (pkp) 1177178825Sdfr goto preauth_done; 1178178825Sdfr } 1179178825Sdfr ts_enc: 1180178825Sdfr#endif 1181233294Sstas kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s", 1182178825Sdfr client_name); 1183178825Sdfr 1184178825Sdfr i = 0; 1185178825Sdfr e_text = "No ENC-TS found"; 1186178825Sdfr while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){ 118755682Smarkm krb5_data ts_data; 118855682Smarkm PA_ENC_TS_ENC p; 118955682Smarkm size_t len; 119055682Smarkm EncryptedData enc_data; 119155682Smarkm Key *pa_key; 1192178825Sdfr char *str; 1193233294Sstas 119455682Smarkm found_pa = 1; 1195233294Sstas 1196233294Sstas if (b->kdc_options.request_anonymous) { 1197233294Sstas ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 1198233294Sstas kdc_log(context, config, 0, "ENC-TS doesn't support anon"); 1199233294Sstas goto out; 1200233294Sstas } 1201233294Sstas 120255682Smarkm ret = decode_EncryptedData(pa->padata_value.data, 120355682Smarkm pa->padata_value.length, 120455682Smarkm &enc_data, 120555682Smarkm &len); 120655682Smarkm if (ret) { 120755682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 1208233294Sstas kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s", 120955682Smarkm client_name); 121055682Smarkm goto out; 121155682Smarkm } 1212233294Sstas 1213233294Sstas ret = hdb_enctype2key(context, &client->entry, 1214178825Sdfr enc_data.etype, &pa_key); 121555682Smarkm if(ret){ 121655682Smarkm char *estr; 121755682Smarkm e_text = "No key matches pa-data"; 1218178825Sdfr ret = KRB5KDC_ERR_ETYPE_NOSUPP; 121955682Smarkm if(krb5_enctype_to_string(context, enc_data.etype, &estr)) 122055682Smarkm estr = NULL; 122155682Smarkm if(estr == NULL) 1222233294Sstas kdc_log(context, config, 5, 1223233294Sstas "No client key matching pa-data (%d) -- %s", 122455682Smarkm enc_data.etype, client_name); 122555682Smarkm else 1226178825Sdfr kdc_log(context, config, 5, 1227233294Sstas "No client key matching pa-data (%s) -- %s", 122855682Smarkm estr, client_name); 122955682Smarkm free(estr); 123055682Smarkm free_EncryptedData(&enc_data); 1231233294Sstas 123255682Smarkm continue; 123355682Smarkm } 1234102644Snectar 1235178825Sdfr try_next_key: 123672445Sassar ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto); 123772445Sassar if (ret) { 1238233294Sstas const char *msg = krb5_get_error_message(context, ret); 1239233294Sstas kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 1240233294Sstas krb5_free_error_message(context, msg); 124172445Sassar free_EncryptedData(&enc_data); 124272445Sassar continue; 124372445Sassar } 124472445Sassar 124555682Smarkm ret = krb5_decrypt_EncryptedData (context, 124655682Smarkm crypto, 124755682Smarkm KRB5_KU_PA_ENC_TIMESTAMP, 124855682Smarkm &enc_data, 124955682Smarkm &ts_data); 125055682Smarkm krb5_crypto_destroy(context, crypto); 1251233294Sstas /* 1252233294Sstas * Since the user might have several keys with the same 1253233294Sstas * enctype but with diffrent salting, we need to try all 1254233294Sstas * the keys with the same enctype. 1255233294Sstas */ 125655682Smarkm if(ret){ 1257178825Sdfr krb5_error_code ret2; 1258233294Sstas const char *msg = krb5_get_error_message(context, ret); 1259233294Sstas 1260233294Sstas ret2 = krb5_enctype_to_string(context, 1261178825Sdfr pa_key->key.keytype, &str); 1262178825Sdfr if (ret2) 1263178825Sdfr str = NULL; 1264233294Sstas kdc_log(context, config, 5, 1265178825Sdfr "Failed to decrypt PA-DATA -- %s " 1266178825Sdfr "(enctype %s) error %s", 1267233294Sstas client_name, str ? str : "unknown enctype", msg); 1268233294Sstas krb5_free_error_message(context, msg); 1269178825Sdfr free(str); 1270178825Sdfr 1271233294Sstas if(hdb_next_enctype2key(context, &client->entry, 1272102644Snectar enc_data.etype, &pa_key) == 0) 1273102644Snectar goto try_next_key; 1274178825Sdfr e_text = "Failed to decrypt PA-DATA"; 1275178825Sdfr 1276102644Snectar free_EncryptedData(&enc_data); 1277233294Sstas 1278233294Sstas if (clientdb->hdb_auth_status) 1279233294Sstas (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD); 1280233294Sstas 1281178825Sdfr ret = KRB5KDC_ERR_PREAUTH_FAILED; 128255682Smarkm continue; 128355682Smarkm } 1284102644Snectar free_EncryptedData(&enc_data); 128555682Smarkm ret = decode_PA_ENC_TS_ENC(ts_data.data, 128655682Smarkm ts_data.length, 128755682Smarkm &p, 128855682Smarkm &len); 128955682Smarkm krb5_data_free(&ts_data); 129055682Smarkm if(ret){ 129155682Smarkm e_text = "Failed to decode PA-ENC-TS-ENC"; 1292178825Sdfr ret = KRB5KDC_ERR_PREAUTH_FAILED; 1293233294Sstas kdc_log(context, config, 1294178825Sdfr 5, "Failed to decode PA-ENC-TS_ENC -- %s", 1295178825Sdfr client_name); 129655682Smarkm continue; 129755682Smarkm } 129855682Smarkm free_PA_ENC_TS_ENC(&p); 129955682Smarkm if (abs(kdc_time - p.patimestamp) > context->max_skew) { 1300178825Sdfr char client_time[100]; 1301178825Sdfr 1302233294Sstas krb5_format_time(context, p.patimestamp, 1303233294Sstas client_time, sizeof(client_time), TRUE); 1304233294Sstas 1305178825Sdfr ret = KRB5KRB_AP_ERR_SKEW; 1306178825Sdfr kdc_log(context, config, 0, 1307178825Sdfr "Too large time skew, " 1308233294Sstas "client time %s is out by %u > %u seconds -- %s", 1309233294Sstas client_time, 1310233294Sstas (unsigned)abs(kdc_time - p.patimestamp), 1311178825Sdfr context->max_skew, 1312178825Sdfr client_name); 1313233294Sstas 1314233294Sstas /* 1315233294Sstas * The following is needed to make windows clients to 1316233294Sstas * retry using the timestamp in the error message, if 1317233294Sstas * there is a e_text, they become unhappy. 1318178825Sdfr */ 1319178825Sdfr e_text = NULL; 132055682Smarkm goto out; 132155682Smarkm } 132255682Smarkm et.flags.pre_authent = 1; 1323178825Sdfr 1324233294Sstas set_salt_padata(rep.padata, pa_key->salt); 1325233294Sstas 1326233294Sstas reply_key = &pa_key->key; 1327233294Sstas 1328233294Sstas ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str); 1329178825Sdfr if (ret) 1330178825Sdfr str = NULL; 1331178825Sdfr 1332178825Sdfr kdc_log(context, config, 2, 1333233294Sstas "ENC-TS Pre-authentication succeeded -- %s using %s", 1334178825Sdfr client_name, str ? str : "unknown enctype"); 1335178825Sdfr free(str); 133655682Smarkm break; 133755682Smarkm } 1338178825Sdfr#ifdef PKINIT 1339178825Sdfr preauth_done: 1340178825Sdfr#endif 1341178825Sdfr if(found_pa == 0 && config->require_preauth) 134255682Smarkm goto use_pa; 134355682Smarkm /* We come here if we found a pa-enc-timestamp, but if there 134455682Smarkm was some problem with it, other than too large skew */ 134555682Smarkm if(found_pa && et.flags.pre_authent == 0){ 1346178825Sdfr kdc_log(context, config, 0, "%s -- %s", e_text, client_name); 134755682Smarkm e_text = NULL; 134855682Smarkm goto out; 134955682Smarkm } 1350178825Sdfr }else if (config->require_preauth 1351233294Sstas || b->kdc_options.request_anonymous /* hack to force anon */ 1352178825Sdfr || client->entry.flags.require_preauth 1353178825Sdfr || server->entry.flags.require_preauth) { 135455682Smarkm METHOD_DATA method_data; 135555682Smarkm PA_DATA *pa; 135655682Smarkm unsigned char *buf; 135755682Smarkm size_t len; 135855682Smarkm 1359233294Sstas use_pa: 136055682Smarkm method_data.len = 0; 136155682Smarkm method_data.val = NULL; 136255682Smarkm 136355682Smarkm ret = realloc_method_data(&method_data); 1364233294Sstas if (ret) { 1365233294Sstas free_METHOD_DATA(&method_data); 1366233294Sstas goto out; 1367233294Sstas } 136855682Smarkm pa = &method_data.val[method_data.len-1]; 136972445Sassar pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; 137055682Smarkm pa->padata_value.length = 0; 137155682Smarkm pa->padata_value.data = NULL; 137255682Smarkm 1373178825Sdfr#ifdef PKINIT 1374178825Sdfr ret = realloc_method_data(&method_data); 1375233294Sstas if (ret) { 1376233294Sstas free_METHOD_DATA(&method_data); 1377233294Sstas goto out; 1378233294Sstas } 1379178825Sdfr pa = &method_data.val[method_data.len-1]; 1380178825Sdfr pa->padata_type = KRB5_PADATA_PK_AS_REQ; 1381178825Sdfr pa->padata_value.length = 0; 1382178825Sdfr pa->padata_value.data = NULL; 1383178825Sdfr 1384178825Sdfr ret = realloc_method_data(&method_data); 1385233294Sstas if (ret) { 1386233294Sstas free_METHOD_DATA(&method_data); 1387233294Sstas goto out; 1388233294Sstas } 1389178825Sdfr pa = &method_data.val[method_data.len-1]; 1390178825Sdfr pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN; 1391178825Sdfr pa->padata_value.length = 0; 1392178825Sdfr pa->padata_value.data = NULL; 1393178825Sdfr#endif 1394178825Sdfr 1395233294Sstas /* 1396233294Sstas * If there is a client key, send ETYPE_INFO{,2} 1397178825Sdfr */ 1398233294Sstas ret = _kdc_find_etype(context, 1399233294Sstas config->preauth_use_strongest_session_key, TRUE, 1400233294Sstas client, b->etype.val, b->etype.len, NULL, &ckey); 1401233294Sstas if (ret == 0) { 1402178825Sdfr 1403233294Sstas /* 1404233294Sstas * RFC4120 requires: 1405233294Sstas * - If the client only knows about old enctypes, then send 1406233294Sstas * both info replies (we send 'info' first in the list). 1407233294Sstas * - If the client is 'modern', because it knows about 'new' 1408233294Sstas * enctype types, then only send the 'info2' reply. 1409233294Sstas * 1410233294Sstas * Before we send the full list of etype-info data, we pick 1411233294Sstas * the client key we would have used anyway below, just pick 1412233294Sstas * that instead. 1413233294Sstas */ 1414178825Sdfr 1415233294Sstas if (older_enctype(ckey->key.keytype)) { 1416233294Sstas ret = get_pa_etype_info(context, config, 1417233294Sstas &method_data, ckey); 1418233294Sstas if (ret) { 1419233294Sstas free_METHOD_DATA(&method_data); 1420233294Sstas goto out; 1421233294Sstas } 1422233294Sstas } 1423233294Sstas ret = get_pa_etype_info2(context, config, 1424233294Sstas &method_data, ckey); 1425233294Sstas if (ret) { 1426233294Sstas free_METHOD_DATA(&method_data); 1427233294Sstas goto out; 1428233294Sstas } 1429233294Sstas } 1430233294Sstas 1431103423Snectar ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret); 143255682Smarkm free_METHOD_DATA(&method_data); 1433178825Sdfr 1434178825Sdfr e_data.data = buf; 1435178825Sdfr e_data.length = len; 1436178825Sdfr e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ", 1437178825Sdfr 143855682Smarkm ret = KRB5KDC_ERR_PREAUTH_REQUIRED; 1439178825Sdfr 1440178825Sdfr kdc_log(context, config, 0, 1441178825Sdfr "No preauth found, returning PREAUTH-REQUIRED -- %s", 1442178825Sdfr client_name); 1443178825Sdfr goto out; 144455682Smarkm } 1445233294Sstas 1446233294Sstas if (clientdb->hdb_auth_status) 1447233294Sstas (clientdb->hdb_auth_status)(context, clientdb, client, 1448233294Sstas HDB_AUTH_SUCCESS); 1449233294Sstas 1450178825Sdfr /* 1451233294Sstas * Verify flags after the user been required to prove its identity 1452233294Sstas * with in a preauth mech. 1453178825Sdfr */ 1454178825Sdfr 1455233294Sstas ret = _kdc_check_access(context, config, client, client_name, 1456233294Sstas server, server_name, 1457233294Sstas req, &e_data); 1458233294Sstas if(ret) 145955682Smarkm goto out; 1460233294Sstas 1461233294Sstas /* 1462233294Sstas * Selelct the best encryption type for the KDC with out regard to 1463233294Sstas * the client since the client never needs to read that data. 1464233294Sstas */ 1465233294Sstas 1466178825Sdfr ret = _kdc_get_preferred_key(context, config, 1467178825Sdfr server, server_name, 1468178825Sdfr &setype, &skey); 1469178825Sdfr if(ret) 1470178825Sdfr goto out; 1471178825Sdfr 147272445Sassar if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey 1473178825Sdfr || (f.request_anonymous && !config->allow_anonymous)) { 147455682Smarkm ret = KRB5KDC_ERR_BADOPTION; 1475233294Sstas e_text = "Bad KDC options"; 1476178825Sdfr kdc_log(context, config, 0, "Bad KDC options -- %s", client_name); 147755682Smarkm goto out; 147855682Smarkm } 1479233294Sstas 148072445Sassar rep.pvno = 5; 148172445Sassar rep.msg_type = krb_as_rep; 1482233294Sstas 1483233294Sstas ret = copy_Realm(&client->entry.principal->realm, &rep.crealm); 1484233294Sstas if (ret) 1485233294Sstas goto out; 1486233294Sstas ret = _krb5_principal2principalname(&rep.cname, client->entry.principal); 1487233294Sstas if (ret) 1488233294Sstas goto out; 1489233294Sstas 149072445Sassar rep.ticket.tkt_vno = 5; 1491178825Sdfr copy_Realm(&server->entry.principal->realm, &rep.ticket.realm); 1492233294Sstas _krb5_principal2principalname(&rep.ticket.sname, 1493178825Sdfr server->entry.principal); 1494178825Sdfr /* java 1.6 expects the name to be the same type, lets allow that 1495178825Sdfr * uncomplicated name-types. */ 1496178825Sdfr#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t) 1497178825Sdfr if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST)) 1498178825Sdfr rep.ticket.sname.name_type = b->sname->name_type; 1499178825Sdfr#undef CNT 150072445Sassar 150155682Smarkm et.flags.initial = 1; 1502178825Sdfr if(client->entry.flags.forwardable && server->entry.flags.forwardable) 150355682Smarkm et.flags.forwardable = f.forwardable; 150455682Smarkm else if (f.forwardable) { 1505233294Sstas e_text = "Ticket may not be forwardable"; 150655682Smarkm ret = KRB5KDC_ERR_POLICY; 1507178825Sdfr kdc_log(context, config, 0, 1508178825Sdfr "Ticket may not be forwardable -- %s", client_name); 150955682Smarkm goto out; 151055682Smarkm } 1511178825Sdfr if(client->entry.flags.proxiable && server->entry.flags.proxiable) 151255682Smarkm et.flags.proxiable = f.proxiable; 151355682Smarkm else if (f.proxiable) { 1514233294Sstas e_text = "Ticket may not be proxiable"; 151555682Smarkm ret = KRB5KDC_ERR_POLICY; 1516233294Sstas kdc_log(context, config, 0, 1517178825Sdfr "Ticket may not be proxiable -- %s", client_name); 151855682Smarkm goto out; 151955682Smarkm } 1520178825Sdfr if(client->entry.flags.postdate && server->entry.flags.postdate) 152155682Smarkm et.flags.may_postdate = f.allow_postdate; 152255682Smarkm else if (f.allow_postdate){ 1523233294Sstas e_text = "Ticket may not be postdate"; 152455682Smarkm ret = KRB5KDC_ERR_POLICY; 1525178825Sdfr kdc_log(context, config, 0, 1526178825Sdfr "Ticket may not be postdatable -- %s", client_name); 152755682Smarkm goto out; 152855682Smarkm } 152955682Smarkm 153055682Smarkm /* check for valid set of addresses */ 1531178825Sdfr if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) { 1532233294Sstas e_text = "Bad address list in requested"; 153355682Smarkm ret = KRB5KRB_AP_ERR_BADADDR; 1534178825Sdfr kdc_log(context, config, 0, 1535178825Sdfr "Bad address list requested -- %s", client_name); 153655682Smarkm goto out; 153755682Smarkm } 153855682Smarkm 1539233294Sstas ret = copy_PrincipalName(&rep.cname, &et.cname); 1540178825Sdfr if (ret) 1541178825Sdfr goto out; 1542233294Sstas ret = copy_Realm(&rep.crealm, &et.crealm); 1543233294Sstas if (ret) 1544233294Sstas goto out; 1545233294Sstas 154655682Smarkm { 154755682Smarkm time_t start; 154855682Smarkm time_t t; 1549233294Sstas 155055682Smarkm start = et.authtime = kdc_time; 1551233294Sstas 155255682Smarkm if(f.postdated && req->req_body.from){ 155355682Smarkm ALLOC(et.starttime); 155455682Smarkm start = *et.starttime = *req->req_body.from; 155555682Smarkm et.flags.invalid = 1; 155655682Smarkm et.flags.postdated = 1; /* XXX ??? */ 155755682Smarkm } 1558178825Sdfr _kdc_fix_time(&b->till); 155955682Smarkm t = *b->till; 156072445Sassar 156172445Sassar /* be careful not overflowing */ 156272445Sassar 1563178825Sdfr if(client->entry.max_life) 1564178825Sdfr t = start + min(t - start, *client->entry.max_life); 1565178825Sdfr if(server->entry.max_life) 1566178825Sdfr t = start + min(t - start, *server->entry.max_life); 156755682Smarkm#if 0 156855682Smarkm t = min(t, start + realm->max_life); 156955682Smarkm#endif 157055682Smarkm et.endtime = t; 157155682Smarkm if(f.renewable_ok && et.endtime < *b->till){ 157255682Smarkm f.renewable = 1; 157355682Smarkm if(b->rtime == NULL){ 157455682Smarkm ALLOC(b->rtime); 157555682Smarkm *b->rtime = 0; 157655682Smarkm } 157755682Smarkm if(*b->rtime < *b->till) 157855682Smarkm *b->rtime = *b->till; 157955682Smarkm } 158055682Smarkm if(f.renewable && b->rtime){ 158155682Smarkm t = *b->rtime; 158255682Smarkm if(t == 0) 158355682Smarkm t = MAX_TIME; 1584178825Sdfr if(client->entry.max_renew) 1585178825Sdfr t = start + min(t - start, *client->entry.max_renew); 1586178825Sdfr if(server->entry.max_renew) 1587178825Sdfr t = start + min(t - start, *server->entry.max_renew); 158855682Smarkm#if 0 158955682Smarkm t = min(t, start + realm->max_renew); 159055682Smarkm#endif 159155682Smarkm ALLOC(et.renew_till); 159255682Smarkm *et.renew_till = t; 159355682Smarkm et.flags.renewable = 1; 159455682Smarkm } 159555682Smarkm } 159672445Sassar 159772445Sassar if (f.request_anonymous) 159872445Sassar et.flags.anonymous = 1; 1599233294Sstas 160055682Smarkm if(b->addresses){ 160155682Smarkm ALLOC(et.caddr); 160255682Smarkm copy_HostAddresses(b->addresses, et.caddr); 160355682Smarkm } 1604233294Sstas 1605127808Snectar et.transited.tr_type = DOMAIN_X500_COMPRESS; 1606233294Sstas krb5_data_zero(&et.transited.contents); 160755682Smarkm 160855682Smarkm /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded 160955682Smarkm * as 0 and as 0x80 (meaning indefinite length) apart, and is thus 161055682Smarkm * incapable of correctly decoding SEQUENCE OF's of zero length. 161155682Smarkm * 161255682Smarkm * To fix this, always send at least one no-op last_req 161355682Smarkm * 161455682Smarkm * If there's a pw_end or valid_end we will use that, 161555682Smarkm * otherwise just a dummy lr. 161655682Smarkm */ 161755682Smarkm ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val)); 1618178825Sdfr if (ek.last_req.val == NULL) { 1619178825Sdfr ret = ENOMEM; 1620178825Sdfr goto out; 1621178825Sdfr } 162255682Smarkm ek.last_req.len = 0; 1623178825Sdfr if (client->entry.pw_end 1624178825Sdfr && (config->kdc_warn_pwexpire == 0 1625178825Sdfr || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) { 162678527Sassar ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME; 1627178825Sdfr ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end; 162855682Smarkm ++ek.last_req.len; 162955682Smarkm } 1630178825Sdfr if (client->entry.valid_end) { 163178527Sassar ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME; 1632178825Sdfr ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end; 163355682Smarkm ++ek.last_req.len; 163455682Smarkm } 163555682Smarkm if (ek.last_req.len == 0) { 163678527Sassar ek.last_req.val[ek.last_req.len].lr_type = LR_NONE; 163755682Smarkm ek.last_req.val[ek.last_req.len].lr_value = 0; 163855682Smarkm ++ek.last_req.len; 163955682Smarkm } 164055682Smarkm ek.nonce = b->nonce; 1641178825Sdfr if (client->entry.valid_end || client->entry.pw_end) { 164255682Smarkm ALLOC(ek.key_expiration); 1643178825Sdfr if (client->entry.valid_end) { 1644178825Sdfr if (client->entry.pw_end) 1645233294Sstas *ek.key_expiration = min(*client->entry.valid_end, 1646178825Sdfr *client->entry.pw_end); 164755682Smarkm else 1648178825Sdfr *ek.key_expiration = *client->entry.valid_end; 164955682Smarkm } else 1650178825Sdfr *ek.key_expiration = *client->entry.pw_end; 165155682Smarkm } else 165255682Smarkm ek.key_expiration = NULL; 165355682Smarkm ek.flags = et.flags; 165455682Smarkm ek.authtime = et.authtime; 165555682Smarkm if (et.starttime) { 165655682Smarkm ALLOC(ek.starttime); 165755682Smarkm *ek.starttime = *et.starttime; 165855682Smarkm } 165955682Smarkm ek.endtime = et.endtime; 166055682Smarkm if (et.renew_till) { 166155682Smarkm ALLOC(ek.renew_till); 166255682Smarkm *ek.renew_till = *et.renew_till; 166355682Smarkm } 166455682Smarkm copy_Realm(&rep.ticket.realm, &ek.srealm); 166555682Smarkm copy_PrincipalName(&rep.ticket.sname, &ek.sname); 166655682Smarkm if(et.caddr){ 166755682Smarkm ALLOC(ek.caddr); 166855682Smarkm copy_HostAddresses(et.caddr, ek.caddr); 166955682Smarkm } 167055682Smarkm 1671178825Sdfr#if PKINIT 1672178825Sdfr if (pkp) { 1673233294Sstas e_text = "Failed to build PK-INIT reply"; 1674233294Sstas ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 1675233294Sstas sessionetype, req, req_buffer, 1676233294Sstas &reply_key, &et.key, rep.padata); 1677178825Sdfr if (ret) 1678178825Sdfr goto out; 1679178825Sdfr ret = _kdc_add_inital_verified_cas(context, 1680178825Sdfr config, 1681178825Sdfr pkp, 1682178825Sdfr &et); 1683178825Sdfr if (ret) 1684178825Sdfr goto out; 1685233294Sstas 1686233294Sstas } else 1687233294Sstas#endif 1688233294Sstas { 1689233294Sstas ret = krb5_generate_random_keyblock(context, sessionetype, &et.key); 1690233294Sstas if (ret) 1691233294Sstas goto out; 169255682Smarkm } 169355682Smarkm 1694233294Sstas if (reply_key == NULL) { 1695233294Sstas e_text = "Client have no reply key"; 1696233294Sstas ret = KRB5KDC_ERR_CLIENT_NOTYET; 1697233294Sstas goto out; 1698233294Sstas } 169955682Smarkm 1700233294Sstas ret = copy_EncryptionKey(&et.key, &ek.key); 1701233294Sstas if (ret) 1702233294Sstas goto out; 1703233294Sstas 1704178825Sdfr /* Add signing of alias referral */ 1705178825Sdfr if (f.canonicalize) { 1706178825Sdfr PA_ClientCanonicalized canon; 1707178825Sdfr krb5_data data; 1708178825Sdfr PA_DATA pa; 1709233294Sstas krb5_crypto cryptox; 1710233294Sstas size_t len = 0; 171155682Smarkm 1712178825Sdfr memset(&canon, 0, sizeof(canon)); 171355682Smarkm 1714178825Sdfr canon.names.requested_name = *b->cname; 1715233294Sstas canon.names.mapped_name = client->entry.principal->name; 171655682Smarkm 1717178825Sdfr ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, 1718178825Sdfr &canon.names, &len, ret); 1719233294Sstas if (ret) 1720178825Sdfr goto out; 1721178825Sdfr if (data.length != len) 1722178825Sdfr krb5_abortx(context, "internal asn.1 error"); 1723178825Sdfr 1724178825Sdfr /* sign using "returned session key" */ 1725233294Sstas ret = krb5_crypto_init(context, &et.key, 0, &cryptox); 1726178825Sdfr if (ret) { 1727178825Sdfr free(data.data); 1728178825Sdfr goto out; 172955682Smarkm } 173055682Smarkm 1731233294Sstas ret = krb5_create_checksum(context, cryptox, 1732178825Sdfr KRB5_KU_CANONICALIZED_NAMES, 0, 1733178825Sdfr data.data, data.length, 1734178825Sdfr &canon.canon_checksum); 1735178825Sdfr free(data.data); 1736233294Sstas krb5_crypto_destroy(context, cryptox); 1737178825Sdfr if (ret) 1738178825Sdfr goto out; 1739233294Sstas 1740178825Sdfr ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length, 1741178825Sdfr &canon, &len, ret); 1742178825Sdfr free_Checksum(&canon.canon_checksum); 1743233294Sstas if (ret) 1744178825Sdfr goto out; 1745178825Sdfr if (data.length != len) 1746178825Sdfr krb5_abortx(context, "internal asn.1 error"); 1747127808Snectar 1748178825Sdfr pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED; 1749178825Sdfr pa.padata_value = data; 1750178825Sdfr ret = add_METHOD_DATA(rep.padata, &pa); 1751178825Sdfr free(data.data); 1752178825Sdfr if (ret) 1753178825Sdfr goto out; 1754127808Snectar } 1755127808Snectar 1756178825Sdfr if (rep.padata->len == 0) { 1757178825Sdfr free(rep.padata); 1758178825Sdfr rep.padata = NULL; 1759127808Snectar } 1760178825Sdfr 1761178825Sdfr /* Add the PAC */ 1762178825Sdfr if (send_pac_p(context, req)) { 1763178825Sdfr krb5_pac p = NULL; 1764178825Sdfr krb5_data data; 1765178825Sdfr 1766178825Sdfr ret = _kdc_pac_generate(context, client, &p); 1767178825Sdfr if (ret) { 1768233294Sstas kdc_log(context, config, 0, "PAC generation failed for -- %s", 1769178825Sdfr client_name); 1770178825Sdfr goto out; 1771103423Snectar } 1772178825Sdfr if (p != NULL) { 1773178825Sdfr ret = _krb5_pac_sign(context, p, et.authtime, 1774178825Sdfr client->entry.principal, 1775233294Sstas &skey->key, /* Server key */ 1776178825Sdfr &skey->key, /* FIXME: should be krbtgt key */ 1777178825Sdfr &data); 1778178825Sdfr krb5_pac_free(context, p); 1779178825Sdfr if (ret) { 1780233294Sstas kdc_log(context, config, 0, "PAC signing failed for -- %s", 1781178825Sdfr client_name); 1782178825Sdfr goto out; 1783127808Snectar } 1784178825Sdfr 1785178825Sdfr ret = _kdc_tkt_add_if_relevant_ad(context, &et, 1786178825Sdfr KRB5_AUTHDATA_WIN2K_PAC, 1787178825Sdfr &data); 1788178825Sdfr krb5_data_free(&data); 1789178825Sdfr if (ret) 1790178825Sdfr goto out; 1791127808Snectar } 179255682Smarkm } 179355682Smarkm 1794233294Sstas _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 1795178825Sdfr et.endtime, et.renew_till); 179655682Smarkm 1797178825Sdfr /* do this as the last thing since this signs the EncTicketPart */ 1798178825Sdfr ret = _kdc_add_KRB5SignedPath(context, 1799178825Sdfr config, 1800178825Sdfr server, 1801178825Sdfr setype, 1802233294Sstas client->entry.principal, 1803178825Sdfr NULL, 1804178825Sdfr NULL, 1805178825Sdfr &et); 1806178825Sdfr if (ret) 1807120945Snectar goto out; 180855682Smarkm 1809233294Sstas log_as_req(context, config, reply_key->keytype, setype, b); 1810233294Sstas 1811233294Sstas ret = _kdc_encode_reply(context, config, 1812233294Sstas &rep, &et, &ek, setype, server->entry.kvno, 1813233294Sstas &skey->key, client->entry.kvno, 1814233294Sstas reply_key, 0, &e_text, reply); 1815178825Sdfr free_EncTicketPart(&et); 1816178825Sdfr free_EncKDCRepPart(&ek); 1817178825Sdfr if (ret) 1818120945Snectar goto out; 181955682Smarkm 1820178825Sdfr /* */ 1821178825Sdfr if (datagram_reply && reply->length > config->max_datagram_reply_length) { 1822178825Sdfr krb5_data_free(reply); 1823178825Sdfr ret = KRB5KRB_ERR_RESPONSE_TOO_BIG; 1824178825Sdfr e_text = "Reply packet too large"; 182555682Smarkm } 182655682Smarkm 1827178825Sdfrout: 1828178825Sdfr free_AS_REP(&rep); 1829233294Sstas if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){ 1830178825Sdfr krb5_mk_error(context, 1831178825Sdfr ret, 1832178825Sdfr e_text, 1833178825Sdfr (e_data.data ? &e_data : NULL), 1834178825Sdfr client_princ, 1835178825Sdfr server_princ, 1836178825Sdfr NULL, 1837178825Sdfr NULL, 1838178825Sdfr reply); 1839178825Sdfr ret = 0; 184055682Smarkm } 1841178825Sdfr#ifdef PKINIT 1842178825Sdfr if (pkp) 1843178825Sdfr _kdc_pk_free_client_param(context, pkp); 184455682Smarkm#endif 1845178825Sdfr if (e_data.data) 1846178825Sdfr free(e_data.data); 1847178825Sdfr if (client_princ) 1848178825Sdfr krb5_free_principal(context, client_princ); 1849178825Sdfr free(client_name); 1850178825Sdfr if (server_princ) 1851178825Sdfr krb5_free_principal(context, server_princ); 1852178825Sdfr free(server_name); 1853178825Sdfr if(client) 1854178825Sdfr _kdc_free_ent(context, client); 1855178825Sdfr if(server) 1856178825Sdfr _kdc_free_ent(context, server); 185755682Smarkm return ret; 185855682Smarkm} 185955682Smarkm 186078527Sassar/* 1861233294Sstas * Add the AuthorizationData `data�� of `type�� to the last element in 1862233294Sstas * the sequence of authorization_data in `tkt�� wrapped in an IF_RELEVANT 186378527Sassar */ 186478527Sassar 1865178825Sdfrkrb5_error_code 1866178825Sdfr_kdc_tkt_add_if_relevant_ad(krb5_context context, 1867178825Sdfr EncTicketPart *tkt, 1868178825Sdfr int type, 1869178825Sdfr const krb5_data *data) 187055682Smarkm{ 187155682Smarkm krb5_error_code ret; 1872233294Sstas size_t size = 0; 187355682Smarkm 1874178825Sdfr if (tkt->authorization_data == NULL) { 1875178825Sdfr tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); 1876178825Sdfr if (tkt->authorization_data == NULL) { 1877233294Sstas krb5_set_error_message(context, ENOMEM, "out of memory"); 1878178825Sdfr return ENOMEM; 1879178825Sdfr } 188055682Smarkm } 1881233294Sstas 1882178825Sdfr /* add the entry to the last element */ 188378527Sassar { 1884178825Sdfr AuthorizationData ad = { 0, NULL }; 1885178825Sdfr AuthorizationDataElement ade; 188678527Sassar 1887178825Sdfr ade.ad_type = type; 1888178825Sdfr ade.ad_data = *data; 188978527Sassar 1890178825Sdfr ret = add_AuthorizationData(&ad, &ade); 189172445Sassar if (ret) { 1892233294Sstas krb5_set_error_message(context, ret, "add AuthorizationData failed"); 1893178825Sdfr return ret; 189472445Sassar } 189555682Smarkm 1896178825Sdfr ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; 189755682Smarkm 1898233294Sstas ASN1_MALLOC_ENCODE(AuthorizationData, 1899233294Sstas ade.ad_data.data, ade.ad_data.length, 1900178825Sdfr &ad, &size, ret); 1901178825Sdfr free_AuthorizationData(&ad); 1902178825Sdfr if (ret) { 1903233294Sstas krb5_set_error_message(context, ret, "ASN.1 encode of " 1904233294Sstas "AuthorizationData failed"); 1905178825Sdfr return ret; 190655682Smarkm } 1907178825Sdfr if (ade.ad_data.length != size) 1908178825Sdfr krb5_abortx(context, "internal asn.1 encoder error"); 1909233294Sstas 1910178825Sdfr ret = add_AuthorizationData(tkt->authorization_data, &ade); 1911178825Sdfr der_free_octet_string(&ade.ad_data); 1912178825Sdfr if (ret) { 1913233294Sstas krb5_set_error_message(context, ret, "add AuthorizationData failed"); 1914178825Sdfr return ret; 191555682Smarkm } 191655682Smarkm } 191755682Smarkm 191855682Smarkm return 0; 191955682Smarkm} 1920