155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2004 Kungliga Tekniska H��gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 555682Smarkm * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7233294Sstas * 8178825Sdfr * Redistribution and use in source and binary forms, with or without 9178825Sdfr * modification, are permitted provided that the following conditions 10178825Sdfr * are met: 1155682Smarkm * 12178825Sdfr * 1. Redistributions of source code must retain the above copyright 13178825Sdfr * notice, this list of conditions and the following disclaimer. 1455682Smarkm * 15178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 16178825Sdfr * notice, this list of conditions and the following disclaimer in the 17178825Sdfr * documentation and/or other materials provided with the distribution. 1855682Smarkm * 19178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 20178825Sdfr * may be used to endorse or promote products derived from this software 21178825Sdfr * without specific prior written permission. 2255682Smarkm * 23178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33178825Sdfr * SUCH DAMAGE. 3455682Smarkm */ 3555682Smarkm 3655682Smarkm#include "krb5_locl.h" 3755682Smarkm 38233294Sstas#undef __attribute__ 39233294Sstas#define __attribute__(x) 4055682Smarkm 41233294Sstas/** 42233294Sstas * @page krb5_init_creds_intro The initial credential handing functions 43233294Sstas * @section section_krb5_init_creds Initial credential 44233294Sstas * 45233294Sstas * Functions to get initial credentials: @ref krb5_credential . 46233294Sstas */ 4755682Smarkm 48233294Sstas/** 49233294Sstas * Allocate a new krb5_get_init_creds_opt structure, free with 50233294Sstas * krb5_get_init_creds_opt_free(). 51233294Sstas * 52233294Sstas * @ingroup krb5_credential 53233294Sstas */ 54233294Sstas 55233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 56233294Sstaskrb5_get_init_creds_opt_alloc(krb5_context context, 57178825Sdfr krb5_get_init_creds_opt **opt) 58178825Sdfr{ 59178825Sdfr krb5_get_init_creds_opt *o; 60233294Sstas 61178825Sdfr *opt = NULL; 62178825Sdfr o = calloc(1, sizeof(*o)); 63178825Sdfr if (o == NULL) { 64233294Sstas krb5_set_error_message(context, ENOMEM, 65233294Sstas N_("malloc: out of memory", "")); 66178825Sdfr return ENOMEM; 67178825Sdfr } 68233294Sstas 69178825Sdfr o->opt_private = calloc(1, sizeof(*o->opt_private)); 70178825Sdfr if (o->opt_private == NULL) { 71233294Sstas krb5_set_error_message(context, ENOMEM, 72233294Sstas N_("malloc: out of memory", "")); 73178825Sdfr free(o); 74178825Sdfr return ENOMEM; 75178825Sdfr } 76178825Sdfr o->opt_private->refcount = 1; 77178825Sdfr *opt = o; 78178825Sdfr return 0; 79178825Sdfr} 80178825Sdfr 81233294Sstas/** 82233294Sstas * Free krb5_get_init_creds_opt structure. 83233294Sstas * 84233294Sstas * @ingroup krb5_credential 85233294Sstas */ 86178825Sdfr 87233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 88178825Sdfrkrb5_get_init_creds_opt_free(krb5_context context, 89178825Sdfr krb5_get_init_creds_opt *opt) 90178825Sdfr{ 91178825Sdfr if (opt == NULL || opt->opt_private == NULL) 92178825Sdfr return; 93178825Sdfr if (opt->opt_private->refcount < 1) /* abort ? */ 94178825Sdfr return; 95178825Sdfr if (--opt->opt_private->refcount == 0) { 96178825Sdfr _krb5_get_init_creds_opt_free_pkinit(opt); 97178825Sdfr free(opt->opt_private); 98178825Sdfr } 99178825Sdfr memset(opt, 0, sizeof(*opt)); 100178825Sdfr free(opt); 101178825Sdfr} 102178825Sdfr 10390926Snectarstatic int 10490926Snectarget_config_time (krb5_context context, 10590926Snectar const char *realm, 10690926Snectar const char *name, 10790926Snectar int def) 10890926Snectar{ 10990926Snectar int ret; 11090926Snectar 11190926Snectar ret = krb5_config_get_time (context, NULL, 11290926Snectar "realms", 11390926Snectar realm, 11490926Snectar name, 11590926Snectar NULL); 11690926Snectar if (ret >= 0) 11790926Snectar return ret; 11890926Snectar ret = krb5_config_get_time (context, NULL, 11990926Snectar "libdefaults", 12090926Snectar name, 12190926Snectar NULL); 12290926Snectar if (ret >= 0) 12390926Snectar return ret; 12490926Snectar return def; 12590926Snectar} 12690926Snectar 12790926Snectarstatic krb5_boolean 12890926Snectarget_config_bool (krb5_context context, 129233294Sstas krb5_boolean def_value, 13090926Snectar const char *realm, 13190926Snectar const char *name) 13290926Snectar{ 133233294Sstas krb5_boolean b; 134233294Sstas 135233294Sstas b = krb5_config_get_bool_default(context, NULL, def_value, 136233294Sstas "realms", realm, name, NULL); 137233294Sstas if (b != def_value) 138233294Sstas return b; 139233294Sstas b = krb5_config_get_bool_default (context, NULL, def_value, 140233294Sstas "libdefaults", name, NULL); 141233294Sstas if (b != def_value) 142233294Sstas return b; 143233294Sstas return def_value; 14490926Snectar} 14590926Snectar 14690926Snectar/* 14790926Snectar * set all the values in `opt' to the appropriate values for 14890926Snectar * application `appname' (default to getprogname() if NULL), and realm 14990926Snectar * `realm'. First looks in [appdefaults] but falls back to 15090926Snectar * [realms] or [libdefaults] for some of the values. 15190926Snectar */ 15290926Snectar 153233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 15472445Sassarkrb5_get_init_creds_opt_set_default_flags(krb5_context context, 155178825Sdfr const char *appname, 15690926Snectar krb5_const_realm realm, 15772445Sassar krb5_get_init_creds_opt *opt) 15872445Sassar{ 15972445Sassar krb5_boolean b; 16072445Sassar time_t t; 16172445Sassar 162233294Sstas b = get_config_bool (context, KRB5_FORWARDABLE_DEFAULT, 163233294Sstas realm, "forwardable"); 16490926Snectar krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b); 16572445Sassar krb5_get_init_creds_opt_set_forwardable(opt, b); 16672445Sassar 167233294Sstas b = get_config_bool (context, FALSE, realm, "proxiable"); 16890926Snectar krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b); 16972445Sassar krb5_get_init_creds_opt_set_proxiable (opt, b); 17072445Sassar 17190926Snectar krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t); 17290926Snectar if (t == 0) 17390926Snectar t = get_config_time (context, realm, "ticket_lifetime", 0); 17472445Sassar if(t != 0) 17572445Sassar krb5_get_init_creds_opt_set_tkt_life(opt, t); 176178825Sdfr 17790926Snectar krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t); 17890926Snectar if (t == 0) 17990926Snectar t = get_config_time (context, realm, "renew_lifetime", 0); 18072445Sassar if(t != 0) 18172445Sassar krb5_get_init_creds_opt_set_renew_life(opt, t); 18272445Sassar 183233294Sstas krb5_appdefault_boolean(context, appname, realm, "no-addresses", 184178825Sdfr KRB5_ADDRESSLESS_DEFAULT, &b); 185178825Sdfr krb5_get_init_creds_opt_set_addressless (context, opt, b); 18690926Snectar 18772445Sassar#if 0 18872445Sassar krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); 18972445Sassar krb5_get_init_creds_opt_set_anonymous (opt, b); 19072445Sassar 191178825Sdfr krb5_get_init_creds_opt_set_etype_list(opt, enctype, 19272445Sassar etype_str.num_strings); 19372445Sassar 19472445Sassar krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 19572445Sassar krb5_data *salt); 19672445Sassar 19772445Sassar krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 19872445Sassar krb5_preauthtype *preauth_list, 19972445Sassar int preauth_list_length); 20072445Sassar#endif 20172445Sassar} 20272445Sassar 20372445Sassar 204233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 20555682Smarkmkrb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, 20655682Smarkm krb5_deltat tkt_life) 20755682Smarkm{ 20855682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; 20955682Smarkm opt->tkt_life = tkt_life; 21055682Smarkm} 21155682Smarkm 212233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 21355682Smarkmkrb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, 21455682Smarkm krb5_deltat renew_life) 21555682Smarkm{ 21655682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; 21755682Smarkm opt->renew_life = renew_life; 21855682Smarkm} 21955682Smarkm 220233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 22155682Smarkmkrb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, 22255682Smarkm int forwardable) 22355682Smarkm{ 22455682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; 22555682Smarkm opt->forwardable = forwardable; 22655682Smarkm} 22755682Smarkm 228233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 22955682Smarkmkrb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, 23055682Smarkm int proxiable) 23155682Smarkm{ 23255682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; 23355682Smarkm opt->proxiable = proxiable; 23455682Smarkm} 23555682Smarkm 236233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 23755682Smarkmkrb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, 23855682Smarkm krb5_enctype *etype_list, 23955682Smarkm int etype_list_length) 24055682Smarkm{ 24155682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; 24255682Smarkm opt->etype_list = etype_list; 24355682Smarkm opt->etype_list_length = etype_list_length; 24455682Smarkm} 24555682Smarkm 246233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 24755682Smarkmkrb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, 24855682Smarkm krb5_addresses *addresses) 24955682Smarkm{ 25055682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; 25155682Smarkm opt->address_list = addresses; 25255682Smarkm} 25355682Smarkm 254233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 25555682Smarkmkrb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 25655682Smarkm krb5_preauthtype *preauth_list, 25755682Smarkm int preauth_list_length) 25855682Smarkm{ 25955682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; 26055682Smarkm opt->preauth_list_length = preauth_list_length; 26155682Smarkm opt->preauth_list = preauth_list; 26255682Smarkm} 26355682Smarkm 264233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 26555682Smarkmkrb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 26655682Smarkm krb5_data *salt) 26755682Smarkm{ 26855682Smarkm opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; 26955682Smarkm opt->salt = salt; 27055682Smarkm} 27172445Sassar 272233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 27372445Sassarkrb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, 27472445Sassar int anonymous) 27572445Sassar{ 27672445Sassar opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; 27772445Sassar opt->anonymous = anonymous; 27872445Sassar} 279178825Sdfr 280178825Sdfrstatic krb5_error_code 281178825Sdfrrequire_ext_opt(krb5_context context, 282178825Sdfr krb5_get_init_creds_opt *opt, 283178825Sdfr const char *type) 284178825Sdfr{ 285178825Sdfr if (opt->opt_private == NULL) { 286233294Sstas krb5_set_error_message(context, EINVAL, 287233294Sstas N_("%s on non extendable opt", ""), type); 288178825Sdfr return EINVAL; 289178825Sdfr } 290178825Sdfr return 0; 291178825Sdfr} 292178825Sdfr 293233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 294178825Sdfrkrb5_get_init_creds_opt_set_pa_password(krb5_context context, 295178825Sdfr krb5_get_init_creds_opt *opt, 296178825Sdfr const char *password, 297178825Sdfr krb5_s2k_proc key_proc) 298178825Sdfr{ 299178825Sdfr krb5_error_code ret; 300178825Sdfr ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); 301178825Sdfr if (ret) 302178825Sdfr return ret; 303178825Sdfr opt->opt_private->password = password; 304178825Sdfr opt->opt_private->key_proc = key_proc; 305178825Sdfr return 0; 306178825Sdfr} 307178825Sdfr 308233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 309178825Sdfrkrb5_get_init_creds_opt_set_pac_request(krb5_context context, 310178825Sdfr krb5_get_init_creds_opt *opt, 311178825Sdfr krb5_boolean req_pac) 312178825Sdfr{ 313178825Sdfr krb5_error_code ret; 314178825Sdfr ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 315178825Sdfr if (ret) 316178825Sdfr return ret; 317178825Sdfr opt->opt_private->req_pac = req_pac ? 318178825Sdfr KRB5_INIT_CREDS_TRISTATE_TRUE : 319178825Sdfr KRB5_INIT_CREDS_TRISTATE_FALSE; 320178825Sdfr return 0; 321178825Sdfr} 322178825Sdfr 323233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 324178825Sdfrkrb5_get_init_creds_opt_set_addressless(krb5_context context, 325178825Sdfr krb5_get_init_creds_opt *opt, 326178825Sdfr krb5_boolean addressless) 327178825Sdfr{ 328178825Sdfr krb5_error_code ret; 329178825Sdfr ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 330178825Sdfr if (ret) 331178825Sdfr return ret; 332178825Sdfr if (addressless) 333178825Sdfr opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; 334178825Sdfr else 335178825Sdfr opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; 336178825Sdfr return 0; 337178825Sdfr} 338178825Sdfr 339233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 340178825Sdfrkrb5_get_init_creds_opt_set_canonicalize(krb5_context context, 341178825Sdfr krb5_get_init_creds_opt *opt, 342178825Sdfr krb5_boolean req) 343178825Sdfr{ 344178825Sdfr krb5_error_code ret; 345178825Sdfr ret = require_ext_opt(context, opt, "init_creds_opt_set_canonicalize"); 346178825Sdfr if (ret) 347178825Sdfr return ret; 348178825Sdfr if (req) 349178825Sdfr opt->opt_private->flags |= KRB5_INIT_CREDS_CANONICALIZE; 350178825Sdfr else 351178825Sdfr opt->opt_private->flags &= ~KRB5_INIT_CREDS_CANONICALIZE; 352178825Sdfr return 0; 353178825Sdfr} 354178825Sdfr 355233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 356178825Sdfrkrb5_get_init_creds_opt_set_win2k(krb5_context context, 357178825Sdfr krb5_get_init_creds_opt *opt, 358178825Sdfr krb5_boolean req) 359178825Sdfr{ 360178825Sdfr krb5_error_code ret; 361178825Sdfr ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 362178825Sdfr if (ret) 363178825Sdfr return ret; 364233294Sstas if (req) { 365178825Sdfr opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_CANON_CHECK; 366233294Sstas opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 367233294Sstas } else { 368178825Sdfr opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_CANON_CHECK; 369233294Sstas opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 370233294Sstas } 371178825Sdfr return 0; 372178825Sdfr} 373178825Sdfr 374233294Sstas 375233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 376233294Sstaskrb5_get_init_creds_opt_set_process_last_req(krb5_context context, 377233294Sstas krb5_get_init_creds_opt *opt, 378233294Sstas krb5_gic_process_last_req func, 379233294Sstas void *ctx) 380233294Sstas{ 381233294Sstas krb5_error_code ret; 382233294Sstas ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 383233294Sstas if (ret) 384233294Sstas return ret; 385233294Sstas 386233294Sstas opt->opt_private->lr.func = func; 387233294Sstas opt->opt_private->lr.ctx = ctx; 388233294Sstas 389233294Sstas return 0; 390233294Sstas} 391233294Sstas 392233294Sstas 393233294Sstas#ifndef HEIMDAL_SMALLER 394233294Sstas 395233294Sstas/** 396233294Sstas * Deprecated: use krb5_get_init_creds_opt_alloc(). 397233294Sstas * 398233294Sstas * The reason krb5_get_init_creds_opt_init() is deprecated is that 399233294Sstas * krb5_get_init_creds_opt is a static structure and for ABI reason it 400233294Sstas * can't grow, ie can't add new functionality. 401233294Sstas * 402233294Sstas * @ingroup krb5_deprecated 403233294Sstas */ 404233294Sstas 405233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 406233294Sstaskrb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) 407233294Sstas KRB5_DEPRECATED_FUNCTION("Use X instead") 408233294Sstas{ 409233294Sstas memset (opt, 0, sizeof(*opt)); 410233294Sstas} 411233294Sstas 412233294Sstas/** 413233294Sstas * Deprecated: use the new krb5_init_creds_init() and 414233294Sstas * krb5_init_creds_get_error(). 415233294Sstas * 416233294Sstas * @ingroup krb5_deprecated 417233294Sstas */ 418233294Sstas 419233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 420233294Sstaskrb5_get_init_creds_opt_get_error(krb5_context context, 421233294Sstas krb5_get_init_creds_opt *opt, 422233294Sstas KRB_ERROR **error) 423233294Sstas KRB5_DEPRECATED_FUNCTION("Use X instead") 424233294Sstas{ 425233294Sstas *error = calloc(1, sizeof(**error)); 426233294Sstas if (*error == NULL) { 427233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 428233294Sstas return ENOMEM; 429233294Sstas } 430233294Sstas 431233294Sstas return 0; 432233294Sstas} 433233294Sstas 434233294Sstas#endif /* HEIMDAL_SMALLER */ 435