1/* 2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "krb5_locl.h" 37 38/** 39 * @page krb5_init_creds_intro The initial credential handing functions 40 * @section section_krb5_init_creds Initial credential 41 * 42 * Functions to get initial credentials: @ref krb5_credential . 43 */ 44 45/** 46 * Allocate a new krb5_get_init_creds_opt structure, free with 47 * krb5_get_init_creds_opt_free(). 48 * 49 * @ingroup krb5_credential 50 */ 51 52KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 53krb5_get_init_creds_opt_alloc(krb5_context context, 54 krb5_get_init_creds_opt **opt) 55{ 56 krb5_get_init_creds_opt *o; 57 58 *opt = NULL; 59 o = calloc(1, sizeof(*o)); 60 if (o == NULL) { 61 krb5_set_error_message(context, ENOMEM, 62 N_("malloc: out of memory", "")); 63 return ENOMEM; 64 } 65 66 o->opt_private = calloc(1, sizeof(*o->opt_private)); 67 if (o->opt_private == NULL) { 68 krb5_set_error_message(context, ENOMEM, 69 N_("malloc: out of memory", "")); 70 free(o); 71 return ENOMEM; 72 } 73 o->opt_private->refcount = 1; 74 *opt = o; 75 return 0; 76} 77 78/** 79 * Free krb5_get_init_creds_opt structure. 80 * 81 * @ingroup krb5_credential 82 */ 83 84KRB5_LIB_FUNCTION void KRB5_LIB_CALL 85krb5_get_init_creds_opt_free(krb5_context context, 86 krb5_get_init_creds_opt *opt) 87{ 88 if (opt == NULL || opt->opt_private == NULL) 89 return; 90 if (opt->opt_private->refcount < 1) /* abort ? */ 91 return; 92 if (--opt->opt_private->refcount == 0) { 93 _krb5_get_init_creds_opt_free_pkinit(opt); 94 free(opt->opt_private); 95 } 96 memset(opt, 0, sizeof(*opt)); 97 free(opt); 98} 99 100static krb5_deltat 101get_config_time (krb5_context context, 102 const char *realm, 103 const char *name, 104 int def) 105{ 106 krb5_deltat ret; 107 108 ret = krb5_config_get_time (context, NULL, 109 "realms", 110 realm, 111 name, 112 NULL); 113 if (ret >= 0) 114 return ret; 115 ret = krb5_config_get_time (context, NULL, 116 "libdefaults", 117 name, 118 NULL); 119 if (ret >= 0) 120 return ret; 121 return def; 122} 123 124static krb5_boolean 125get_config_bool (krb5_context context, 126 krb5_boolean def_value, 127 const char *realm, 128 const char *name) 129{ 130 krb5_boolean b; 131 132 b = krb5_config_get_bool_default(context, NULL, def_value, 133 "realms", realm, name, NULL); 134 if (b != def_value) 135 return b; 136 b = krb5_config_get_bool_default (context, NULL, def_value, 137 "libdefaults", name, NULL); 138 if (b != def_value) 139 return b; 140 return def_value; 141} 142 143/* 144 * set all the values in `opt' to the appropriate values for 145 * application `appname' (default to getprogname() if NULL), and realm 146 * `realm'. First looks in [appdefaults] but falls back to 147 * [realms] or [libdefaults] for some of the values. 148 */ 149 150KRB5_LIB_FUNCTION void KRB5_LIB_CALL 151krb5_get_init_creds_opt_set_default_flags(krb5_context context, 152 const char *appname, 153 krb5_const_realm realm, 154 krb5_get_init_creds_opt *opt) 155{ 156 krb5_boolean b; 157 time_t t; 158 159 b = get_config_bool (context, KRB5_FORWARDABLE_DEFAULT, 160 realm, "forwardable"); 161 krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b); 162 krb5_get_init_creds_opt_set_forwardable(opt, b); 163 164 b = get_config_bool (context, FALSE, realm, "proxiable"); 165 krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b); 166 krb5_get_init_creds_opt_set_proxiable (opt, b); 167 168 krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t); 169 if (t == 0) 170 t = get_config_time (context, realm, "ticket_lifetime", 0); 171 if(t != 0) 172 krb5_get_init_creds_opt_set_tkt_life(opt, t); 173 174 krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t); 175 if (t == 0) 176 t = get_config_time (context, realm, "renew_lifetime", 0); 177 if(t != 0) 178 krb5_get_init_creds_opt_set_renew_life(opt, t); 179 180 krb5_appdefault_boolean(context, appname, realm, "no-addresses", 181 KRB5_ADDRESSLESS_DEFAULT, &b); 182 krb5_get_init_creds_opt_set_addressless (context, opt, b); 183 184#if 0 185 krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); 186 krb5_get_init_creds_opt_set_anonymous (opt, b); 187 188 krb5_get_init_creds_opt_set_etype_list(opt, enctype, 189 etype_str.num_strings); 190 191 krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 192 krb5_data *salt); 193 194 krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 195 krb5_preauthtype *preauth_list, 196 int preauth_list_length); 197#endif 198} 199 200 201KRB5_LIB_FUNCTION void KRB5_LIB_CALL 202krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, 203 krb5_deltat tkt_life) 204{ 205 opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; 206 opt->tkt_life = tkt_life; 207} 208 209KRB5_LIB_FUNCTION void KRB5_LIB_CALL 210krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, 211 krb5_deltat renew_life) 212{ 213 opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; 214 opt->renew_life = renew_life; 215} 216 217KRB5_LIB_FUNCTION void KRB5_LIB_CALL 218krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, 219 int forwardable) 220{ 221 opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; 222 opt->forwardable = forwardable; 223} 224 225KRB5_LIB_FUNCTION void KRB5_LIB_CALL 226krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, 227 int proxiable) 228{ 229 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; 230 opt->proxiable = proxiable; 231} 232 233KRB5_LIB_FUNCTION void KRB5_LIB_CALL 234krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, 235 krb5_enctype *etype_list, 236 int etype_list_length) 237{ 238 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; 239 opt->etype_list = etype_list; 240 opt->etype_list_length = etype_list_length; 241} 242 243KRB5_LIB_FUNCTION void KRB5_LIB_CALL 244krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, 245 krb5_addresses *addresses) 246{ 247 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; 248 opt->address_list = addresses; 249} 250 251KRB5_LIB_FUNCTION void KRB5_LIB_CALL 252krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 253 krb5_preauthtype *preauth_list, 254 int preauth_list_length) 255{ 256 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; 257 opt->preauth_list_length = preauth_list_length; 258 opt->preauth_list = preauth_list; 259} 260 261KRB5_LIB_FUNCTION void KRB5_LIB_CALL 262krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 263 krb5_data *salt) 264{ 265 opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; 266 opt->salt = salt; 267} 268 269KRB5_LIB_FUNCTION void KRB5_LIB_CALL 270krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, 271 int anonymous) 272{ 273 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; 274 opt->anonymous = anonymous; 275} 276 277static krb5_error_code 278require_ext_opt(krb5_context context, 279 krb5_get_init_creds_opt *opt, 280 const char *type) 281{ 282 if (opt->opt_private == NULL) { 283 krb5_set_error_message(context, EINVAL, 284 N_("%s on non extendable opt", ""), type); 285 return EINVAL; 286 } 287 return 0; 288} 289 290KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 291krb5_get_init_creds_opt_set_pa_password(krb5_context context, 292 krb5_get_init_creds_opt *opt, 293 const char *password, 294 krb5_s2k_proc key_proc) 295{ 296 krb5_error_code ret; 297 ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); 298 if (ret) 299 return ret; 300 opt->opt_private->password = password; 301 opt->opt_private->key_proc = key_proc; 302 return 0; 303} 304 305KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 306krb5_get_init_creds_opt_set_pac_request(krb5_context context, 307 krb5_get_init_creds_opt *opt, 308 krb5_boolean req_pac) 309{ 310 krb5_error_code ret; 311 ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 312 if (ret) 313 return ret; 314 opt->opt_private->req_pac = req_pac ? 315 KRB5_INIT_CREDS_TRISTATE_TRUE : 316 KRB5_INIT_CREDS_TRISTATE_FALSE; 317 return 0; 318} 319 320KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 321krb5_get_init_creds_opt_set_addressless(krb5_context context, 322 krb5_get_init_creds_opt *opt, 323 krb5_boolean addressless) 324{ 325 krb5_error_code ret; 326 ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 327 if (ret) 328 return ret; 329 if (addressless) 330 opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; 331 else 332 opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; 333 return 0; 334} 335 336KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 337krb5_get_init_creds_opt_set_canonicalize(krb5_context context, 338 krb5_get_init_creds_opt *opt, 339 krb5_boolean req) 340{ 341 krb5_error_code ret; 342 ret = require_ext_opt(context, opt, "init_creds_opt_set_canonicalize"); 343 if (ret) 344 return ret; 345 if (req) 346 opt->opt_private->flags |= KRB5_INIT_CREDS_CANONICALIZE; 347 else 348 opt->opt_private->flags &= ~KRB5_INIT_CREDS_CANONICALIZE; 349 return 0; 350} 351 352KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 353krb5_get_init_creds_opt_set_win2k(krb5_context context, 354 krb5_get_init_creds_opt *opt, 355 krb5_boolean req) 356{ 357 krb5_error_code ret; 358 ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 359 if (ret) 360 return ret; 361 if (req) { 362 opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_CANON_CHECK; 363 opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 364 } else { 365 opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_CANON_CHECK; 366 opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 367 } 368 return 0; 369} 370 371 372KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 373krb5_get_init_creds_opt_set_process_last_req(krb5_context context, 374 krb5_get_init_creds_opt *opt, 375 krb5_gic_process_last_req func, 376 void *ctx) 377{ 378 krb5_error_code ret; 379 ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 380 if (ret) 381 return ret; 382 383 opt->opt_private->lr.func = func; 384 opt->opt_private->lr.ctx = ctx; 385 386 return 0; 387} 388 389#ifndef HEIMDAL_SMALLER 390 391/** 392 * Deprecated: use krb5_get_init_creds_opt_alloc(). 393 * 394 * The reason krb5_get_init_creds_opt_init() is deprecated is that 395 * krb5_get_init_creds_opt is a static structure and for ABI reason it 396 * can't grow, ie can't add new functionality. 397 * 398 * @ingroup krb5_deprecated 399 */ 400 401KRB5_LIB_FUNCTION void KRB5_LIB_CALL 402krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) 403 KRB5_DEPRECATED_FUNCTION("Use X instead") 404{ 405 memset (opt, 0, sizeof(*opt)); 406} 407 408/** 409 * Deprecated: use the new krb5_init_creds_init() and 410 * krb5_init_creds_get_error(). 411 * 412 * @ingroup krb5_deprecated 413 */ 414 415KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 416krb5_get_init_creds_opt_get_error(krb5_context context, 417 krb5_get_init_creds_opt *opt, 418 KRB_ERROR **error) 419 KRB5_DEPRECATED_FUNCTION("Use X instead") 420{ 421 *error = calloc(1, sizeof(**error)); 422 if (*error == NULL) { 423 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 424 return ENOMEM; 425 } 426 427 return 0; 428} 429 430#endif /* HEIMDAL_SMALLER */ 431