init_creds.c revision 178825
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 36RCSID("$Id: init_creds.c 21711 2007-07-27 14:22:02Z lha $"); 37 38void KRB5_LIB_FUNCTION 39krb5_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 46krb5_error_code KRB5_LIB_FUNCTION 47krb5_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 70krb5_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 99void 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 109void 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 132void KRB5_LIB_FUNCTION 133krb5_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 149static int 150get_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 173static krb5_boolean 174get_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 198void KRB5_LIB_FUNCTION 199krb5_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 248void KRB5_LIB_FUNCTION 249krb5_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 256void KRB5_LIB_FUNCTION 257krb5_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 264void KRB5_LIB_FUNCTION 265krb5_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 272void KRB5_LIB_FUNCTION 273krb5_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 280void KRB5_LIB_FUNCTION 281krb5_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 290void KRB5_LIB_FUNCTION 291krb5_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 298void KRB5_LIB_FUNCTION 299krb5_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 308void KRB5_LIB_FUNCTION 309krb5_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 316void KRB5_LIB_FUNCTION 317krb5_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 324static krb5_error_code 325require_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 336krb5_error_code KRB5_LIB_FUNCTION 337krb5_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 351krb5_error_code KRB5_LIB_FUNCTION 352krb5_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 366krb5_error_code KRB5_LIB_FUNCTION 367krb5_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 395krb5_error_code KRB5_LIB_FUNCTION 396krb5_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 411krb5_error_code KRB5_LIB_FUNCTION 412krb5_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 427krb5_error_code KRB5_LIB_FUNCTION 428krb5_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