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 #undef __attribute__ 39 #define __attribute__(x) 40 41 /** 42 * @page krb5_init_creds_intro The initial credential handing functions 43 * @section section_krb5_init_creds Initial credential 44 * 45 * Functions to get initial credentials: @ref krb5_credential . 46 */ 47 48 /** 49 * Allocate a new krb5_get_init_creds_opt structure, free with 50 * krb5_get_init_creds_opt_free(). 51 * 52 * @ingroup krb5_credential 53 */ 54 55 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 56 krb5_get_init_creds_opt_alloc(krb5_context context, 57 krb5_get_init_creds_opt **opt) 58 { 59 krb5_get_init_creds_opt *o; 60 61 *opt = NULL; 62 o = calloc(1, sizeof(*o)); 63 if (o == NULL) { 64 krb5_set_error_message(context, ENOMEM, 65 N_("malloc: out of memory", "")); 66 return ENOMEM; 67 } 68 69 o->opt_private = calloc(1, sizeof(*o->opt_private)); 70 if (o->opt_private == NULL) { 71 krb5_set_error_message(context, ENOMEM, 72 N_("malloc: out of memory", "")); 73 free(o); 74 return ENOMEM; 75 } 76 o->opt_private->refcount = 1; 77 *opt = o; 78 return 0; 79 } 80 81 /** 82 * Free krb5_get_init_creds_opt structure. 83 * 84 * @ingroup krb5_credential 85 */ 86 87 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 88 krb5_get_init_creds_opt_free(krb5_context context, 89 krb5_get_init_creds_opt *opt) 90 { 91 if (opt == NULL || opt->opt_private == NULL) 92 return; 93 if (opt->opt_private->refcount < 1) /* abort ? */ 94 return; 95 if (--opt->opt_private->refcount == 0) { 96 _krb5_get_init_creds_opt_free_pkinit(opt); 97 free(opt->opt_private); 98 } 99 memset(opt, 0, sizeof(*opt)); 100 free(opt); 101 } 102 103 static int 104 get_config_time (krb5_context context, 105 const char *realm, 106 const char *name, 107 int def) 108 { 109 int ret; 110 111 ret = krb5_config_get_time (context, NULL, 112 "realms", 113 realm, 114 name, 115 NULL); 116 if (ret >= 0) 117 return ret; 118 ret = krb5_config_get_time (context, NULL, 119 "libdefaults", 120 name, 121 NULL); 122 if (ret >= 0) 123 return ret; 124 return def; 125 } 126 127 static krb5_boolean 128 get_config_bool (krb5_context context, 129 krb5_boolean def_value, 130 const char *realm, 131 const char *name) 132 { 133 krb5_boolean b; 134 135 b = krb5_config_get_bool_default(context, NULL, def_value, 136 "realms", realm, name, NULL); 137 if (b != def_value) 138 return b; 139 b = krb5_config_get_bool_default (context, NULL, def_value, 140 "libdefaults", name, NULL); 141 if (b != def_value) 142 return b; 143 return def_value; 144 } 145 146 /* 147 * set all the values in `opt' to the appropriate values for 148 * application `appname' (default to getprogname() if NULL), and realm 149 * `realm'. First looks in [appdefaults] but falls back to 150 * [realms] or [libdefaults] for some of the values. 151 */ 152 153 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 154 krb5_get_init_creds_opt_set_default_flags(krb5_context context, 155 const char *appname, 156 krb5_const_realm realm, 157 krb5_get_init_creds_opt *opt) 158 { 159 krb5_boolean b; 160 time_t t; 161 162 b = get_config_bool (context, KRB5_FORWARDABLE_DEFAULT, 163 realm, "forwardable"); 164 krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b); 165 krb5_get_init_creds_opt_set_forwardable(opt, b); 166 167 b = get_config_bool (context, FALSE, realm, "proxiable"); 168 krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b); 169 krb5_get_init_creds_opt_set_proxiable (opt, b); 170 171 krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t); 172 if (t == 0) 173 t = get_config_time (context, realm, "ticket_lifetime", 0); 174 if(t != 0) 175 krb5_get_init_creds_opt_set_tkt_life(opt, t); 176 177 krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t); 178 if (t == 0) 179 t = get_config_time (context, realm, "renew_lifetime", 0); 180 if(t != 0) 181 krb5_get_init_creds_opt_set_renew_life(opt, t); 182 183 krb5_appdefault_boolean(context, appname, realm, "no-addresses", 184 KRB5_ADDRESSLESS_DEFAULT, &b); 185 krb5_get_init_creds_opt_set_addressless (context, opt, b); 186 187 #if 0 188 krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); 189 krb5_get_init_creds_opt_set_anonymous (opt, b); 190 191 krb5_get_init_creds_opt_set_etype_list(opt, enctype, 192 etype_str.num_strings); 193 194 krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 195 krb5_data *salt); 196 197 krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 198 krb5_preauthtype *preauth_list, 199 int preauth_list_length); 200 #endif 201 } 202 203 204 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 205 krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, 206 krb5_deltat tkt_life) 207 { 208 opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; 209 opt->tkt_life = tkt_life; 210 } 211 212 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 213 krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, 214 krb5_deltat renew_life) 215 { 216 opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; 217 opt->renew_life = renew_life; 218 } 219 220 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 221 krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, 222 int forwardable) 223 { 224 opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; 225 opt->forwardable = forwardable; 226 } 227 228 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 229 krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, 230 int proxiable) 231 { 232 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; 233 opt->proxiable = proxiable; 234 } 235 236 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 237 krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, 238 krb5_enctype *etype_list, 239 int etype_list_length) 240 { 241 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; 242 opt->etype_list = etype_list; 243 opt->etype_list_length = etype_list_length; 244 } 245 246 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 247 krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, 248 krb5_addresses *addresses) 249 { 250 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; 251 opt->address_list = addresses; 252 } 253 254 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 255 krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 256 krb5_preauthtype *preauth_list, 257 int preauth_list_length) 258 { 259 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; 260 opt->preauth_list_length = preauth_list_length; 261 opt->preauth_list = preauth_list; 262 } 263 264 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 265 krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 266 krb5_data *salt) 267 { 268 opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; 269 opt->salt = salt; 270 } 271 272 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 273 krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, 274 int anonymous) 275 { 276 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; 277 opt->anonymous = anonymous; 278 } 279 280 static krb5_error_code 281 require_ext_opt(krb5_context context, 282 krb5_get_init_creds_opt *opt, 283 const char *type) 284 { 285 if (opt->opt_private == NULL) { 286 krb5_set_error_message(context, EINVAL, 287 N_("%s on non extendable opt", ""), type); 288 return EINVAL; 289 } 290 return 0; 291 } 292 293 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 294 krb5_get_init_creds_opt_set_pa_password(krb5_context context, 295 krb5_get_init_creds_opt *opt, 296 const char *password, 297 krb5_s2k_proc key_proc) 298 { 299 krb5_error_code ret; 300 ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); 301 if (ret) 302 return ret; 303 opt->opt_private->password = password; 304 opt->opt_private->key_proc = key_proc; 305 return 0; 306 } 307 308 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 309 krb5_get_init_creds_opt_set_pac_request(krb5_context context, 310 krb5_get_init_creds_opt *opt, 311 krb5_boolean req_pac) 312 { 313 krb5_error_code ret; 314 ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 315 if (ret) 316 return ret; 317 opt->opt_private->req_pac = req_pac ? 318 KRB5_INIT_CREDS_TRISTATE_TRUE : 319 KRB5_INIT_CREDS_TRISTATE_FALSE; 320 return 0; 321 } 322 323 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 324 krb5_get_init_creds_opt_set_addressless(krb5_context context, 325 krb5_get_init_creds_opt *opt, 326 krb5_boolean addressless) 327 { 328 krb5_error_code ret; 329 ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); 330 if (ret) 331 return ret; 332 if (addressless) 333 opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; 334 else 335 opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; 336 return 0; 337 } 338 339 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 340 krb5_get_init_creds_opt_set_canonicalize(krb5_context context, 341 krb5_get_init_creds_opt *opt, 342 krb5_boolean req) 343 { 344 krb5_error_code ret; 345 ret = require_ext_opt(context, opt, "init_creds_opt_set_canonicalize"); 346 if (ret) 347 return ret; 348 if (req) 349 opt->opt_private->flags |= KRB5_INIT_CREDS_CANONICALIZE; 350 else 351 opt->opt_private->flags &= ~KRB5_INIT_CREDS_CANONICALIZE; 352 return 0; 353 } 354 355 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 356 krb5_get_init_creds_opt_set_win2k(krb5_context context, 357 krb5_get_init_creds_opt *opt, 358 krb5_boolean req) 359 { 360 krb5_error_code ret; 361 ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 362 if (ret) 363 return ret; 364 if (req) { 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 } else { 368 opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_CANON_CHECK; 369 opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK; 370 } 371 return 0; 372 } 373 374 375 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 376 krb5_get_init_creds_opt_set_process_last_req(krb5_context context, 377 krb5_get_init_creds_opt *opt, 378 krb5_gic_process_last_req func, 379 void *ctx) 380 { 381 krb5_error_code ret; 382 ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); 383 if (ret) 384 return ret; 385 386 opt->opt_private->lr.func = func; 387 opt->opt_private->lr.ctx = ctx; 388 389 return 0; 390 } 391 392 393 #ifndef HEIMDAL_SMALLER 394 395 /** 396 * Deprecated: use krb5_get_init_creds_opt_alloc(). 397 * 398 * The reason krb5_get_init_creds_opt_init() is deprecated is that 399 * krb5_get_init_creds_opt is a static structure and for ABI reason it 400 * can't grow, ie can't add new functionality. 401 * 402 * @ingroup krb5_deprecated 403 */ 404 405 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 406 krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) 407 KRB5_DEPRECATED_FUNCTION("Use X instead") 408 { 409 memset (opt, 0, sizeof(*opt)); 410 } 411 412 /** 413 * Deprecated: use the new krb5_init_creds_init() and 414 * krb5_init_creds_get_error(). 415 * 416 * @ingroup krb5_deprecated 417 */ 418 419 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 420 krb5_get_init_creds_opt_get_error(krb5_context context, 421 krb5_get_init_creds_opt *opt, 422 KRB_ERROR **error) 423 KRB5_DEPRECATED_FUNCTION("Use X instead") 424 { 425 *error = calloc(1, sizeof(**error)); 426 if (*error == NULL) { 427 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 428 return ENOMEM; 429 } 430 431 return 0; 432 } 433 434 #endif /* HEIMDAL_SMALLER */ 435