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