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