1 /* 2 * Copyright (c) 1997 - 2002 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 #include <com_err.h> 36 37 RCSID("$Id: context.c,v 1.80 2002/08/28 15:27:24 joda Exp $"); 38 39 #define INIT_FIELD(C, T, E, D, F) \ 40 (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ 41 "libdefaults", F, NULL) 42 43 /* 44 * Set the list of etypes `ret_etypes' from the configuration variable 45 * `name' 46 */ 47 48 static krb5_error_code 49 set_etypes (krb5_context context, 50 const char *name, 51 krb5_enctype **ret_enctypes) 52 { 53 char **etypes_str; 54 krb5_enctype *etypes = NULL; 55 56 etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", 57 name, NULL); 58 if(etypes_str){ 59 int i, j, k; 60 for(i = 0; etypes_str[i]; i++); 61 etypes = malloc((i+1) * sizeof(*etypes)); 62 if (etypes == NULL) { 63 krb5_config_free_strings (etypes_str); 64 krb5_set_error_string (context, "malloc: out of memory"); 65 return ENOMEM; 66 } 67 for(j = 0, k = 0; j < i; j++) { 68 if(krb5_string_to_enctype(context, etypes_str[j], &etypes[k]) == 0) 69 k++; 70 } 71 etypes[k] = ETYPE_NULL; 72 krb5_config_free_strings(etypes_str); 73 } 74 *ret_enctypes = etypes; 75 return 0; 76 } 77 78 /* 79 * read variables from the configuration file and set in `context' 80 */ 81 82 static krb5_error_code 83 init_context_from_config_file(krb5_context context) 84 { 85 krb5_error_code ret; 86 const char * tmp; 87 krb5_enctype *tmptypes; 88 89 INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); 90 INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout"); 91 INIT_FIELD(context, int, max_retries, 3, "max_retries"); 92 93 INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); 94 95 ret = set_etypes (context, "default_etypes", &tmptypes); 96 if(ret) 97 return ret; 98 free(context->etypes); 99 context->etypes = tmptypes; 100 101 ret = set_etypes (context, "default_etypes_des", &tmptypes); 102 if(ret) 103 return ret; 104 free(context->etypes_des); 105 context->etypes_des = tmptypes; 106 107 /* default keytab name */ 108 tmp = NULL; 109 if(!issuid()) 110 tmp = getenv("KRB5_KTNAME"); 111 if(tmp != NULL) 112 context->default_keytab = tmp; 113 else 114 INIT_FIELD(context, string, default_keytab, 115 KEYTAB_DEFAULT, "default_keytab_name"); 116 117 INIT_FIELD(context, string, default_keytab_modify, 118 NULL, "default_keytab_modify_name"); 119 120 INIT_FIELD(context, string, time_fmt, 121 "%Y-%m-%dT%H:%M:%S", "time_format"); 122 123 INIT_FIELD(context, string, date_fmt, 124 "%Y-%m-%d", "date_format"); 125 126 INIT_FIELD(context, bool, log_utc, 127 FALSE, "log_utc"); 128 129 130 131 /* init dns-proxy slime */ 132 tmp = krb5_config_get_string(context, NULL, "libdefaults", 133 "dns_proxy", NULL); 134 if(tmp) 135 roken_gethostby_setup(context->http_proxy, tmp); 136 krb5_free_host_realm (context, context->default_realms); 137 context->default_realms = NULL; 138 139 { 140 krb5_addresses addresses; 141 char **adr, **a; 142 143 krb5_set_extra_addresses(context, NULL); 144 adr = krb5_config_get_strings(context, NULL, 145 "libdefaults", 146 "extra_addresses", 147 NULL); 148 memset(&addresses, 0, sizeof(addresses)); 149 for(a = adr; a && *a; a++) { 150 ret = krb5_parse_address(context, *a, &addresses); 151 if (ret == 0) { 152 krb5_add_extra_addresses(context, &addresses); 153 krb5_free_addresses(context, &addresses); 154 } 155 } 156 krb5_config_free_strings(adr); 157 158 krb5_set_ignore_addresses(context, NULL); 159 adr = krb5_config_get_strings(context, NULL, 160 "libdefaults", 161 "ignore_addresses", 162 NULL); 163 memset(&addresses, 0, sizeof(addresses)); 164 for(a = adr; a && *a; a++) { 165 ret = krb5_parse_address(context, *a, &addresses); 166 if (ret == 0) { 167 krb5_add_ignore_addresses(context, &addresses); 168 krb5_free_addresses(context, &addresses); 169 } 170 } 171 krb5_config_free_strings(adr); 172 } 173 174 INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); 175 INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); 176 INIT_FIELD(context, bool, srv_lookup, TRUE, "dns_lookup_kdc"); 177 /* srv_lookup backwards compatibility. */ 178 { 179 const char **p; 180 p = krb5_config_get_strings(context, NULL, "libdefaults", "srv_lookup", NULL); 181 if (p != NULL) 182 INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); 183 } 184 return 0; 185 } 186 187 krb5_error_code 188 krb5_init_context(krb5_context *context) 189 { 190 krb5_context p; 191 krb5_error_code ret; 192 char **files; 193 194 p = calloc(1, sizeof(*p)); 195 if(!p) 196 return ENOMEM; 197 198 ret = krb5_get_default_config_files(&files); 199 if(ret) 200 goto out; 201 ret = krb5_set_config_files(p, files); 202 krb5_free_config_files(files); 203 if(ret) 204 goto out; 205 206 /* init error tables */ 207 krb5_init_ets(p); 208 209 p->cc_ops = NULL; 210 p->num_cc_ops = 0; 211 krb5_cc_register(p, &krb5_fcc_ops, TRUE); 212 krb5_cc_register(p, &krb5_mcc_ops, TRUE); 213 214 p->num_kt_types = 0; 215 p->kt_types = NULL; 216 krb5_kt_register (p, &krb5_fkt_ops); 217 krb5_kt_register (p, &krb5_mkt_ops); 218 krb5_kt_register (p, &krb5_akf_ops); 219 krb5_kt_register (p, &krb4_fkt_ops); 220 krb5_kt_register (p, &krb5_srvtab_fkt_ops); 221 krb5_kt_register (p, &krb5_any_ops); 222 223 out: 224 if(ret) { 225 krb5_free_context(p); 226 p = NULL; 227 } 228 *context = p; 229 return ret; 230 } 231 232 void 233 krb5_free_context(krb5_context context) 234 { 235 free(context->etypes); 236 free(context->etypes_des); 237 krb5_free_host_realm (context, context->default_realms); 238 krb5_config_file_free (context, context->cf); 239 free_error_table (context->et_list); 240 free(context->cc_ops); 241 free(context->kt_types); 242 krb5_clear_error_string(context); 243 if(context->warn_dest != NULL) 244 krb5_closelog(context, context->warn_dest); 245 krb5_set_extra_addresses(context, NULL); 246 krb5_set_ignore_addresses(context, NULL); 247 free(context); 248 } 249 250 krb5_error_code 251 krb5_set_config_files(krb5_context context, char **filenames) 252 { 253 krb5_error_code ret; 254 krb5_config_binding *tmp = NULL; 255 while(filenames != NULL && *filenames != NULL && **filenames != '\0') { 256 ret = krb5_config_parse_file_multi(context, *filenames, &tmp); 257 if(ret != 0 && ret != ENOENT) { 258 krb5_config_file_free(context, tmp); 259 return ret; 260 } 261 filenames++; 262 } 263 #if 0 264 /* with this enabled and if there are no config files, Kerberos is 265 considererd disabled */ 266 if(tmp == NULL) 267 return ENOENT; 268 #endif 269 krb5_config_file_free(context, context->cf); 270 context->cf = tmp; 271 ret = init_context_from_config_file(context); 272 return ret; 273 } 274 275 krb5_error_code 276 krb5_get_default_config_files(char ***pfilenames) 277 { 278 const char *p, *q; 279 char **pp; 280 int n, i; 281 282 const char *files = NULL; 283 if (pfilenames == NULL) 284 return EINVAL; 285 if(!issuid()) 286 files = getenv("KRB5_CONFIG"); 287 if (files == NULL) 288 files = krb5_config_file; 289 290 for(n = 0, p = files; strsep_copy(&p, ":", NULL, 0) != -1; n++); 291 pp = malloc((n + 1) * sizeof(*pp)); 292 if(pp == NULL) 293 return ENOMEM; 294 295 n = 0; 296 p = files; 297 while(1) { 298 ssize_t l; 299 q = p; 300 l = strsep_copy(&q, ":", NULL, 0); 301 if(l == -1) 302 break; 303 pp[n] = malloc(l + 1); 304 if(pp[n] == NULL) { 305 krb5_free_config_files(pp); 306 return ENOMEM; 307 } 308 l = strsep_copy(&p, ":", pp[n], l + 1); 309 for(i = 0; i < n; i++) 310 if(strcmp(pp[i], pp[n]) == 0) { 311 free(pp[n]); 312 goto skip; 313 } 314 n++; 315 skip:; 316 } 317 pp[n] = NULL; 318 *pfilenames = pp; 319 return 0; 320 } 321 322 void 323 krb5_free_config_files(char **filenames) 324 { 325 char **p; 326 for(p = filenames; *p != NULL; p++) 327 free(*p); 328 free(filenames); 329 } 330 331 /* 332 * set `etype' to a malloced list of the default enctypes 333 */ 334 335 static krb5_error_code 336 default_etypes(krb5_context context, krb5_enctype **etype) 337 { 338 krb5_enctype p[] = { 339 ETYPE_DES3_CBC_SHA1, 340 ETYPE_DES3_CBC_MD5, 341 ETYPE_ARCFOUR_HMAC_MD5, 342 ETYPE_DES_CBC_MD5, 343 ETYPE_DES_CBC_MD4, 344 ETYPE_DES_CBC_CRC, 345 ETYPE_NULL 346 }; 347 348 *etype = malloc(sizeof(p)); 349 if(*etype == NULL) { 350 krb5_set_error_string (context, "malloc: out of memory"); 351 return ENOMEM; 352 } 353 memcpy(*etype, p, sizeof(p)); 354 return 0; 355 } 356 357 krb5_error_code 358 krb5_set_default_in_tkt_etypes(krb5_context context, 359 const krb5_enctype *etypes) 360 { 361 int i; 362 krb5_enctype *p = NULL; 363 364 if(etypes) { 365 for (i = 0; etypes[i]; ++i) 366 if(!krb5_enctype_valid(context, etypes[i])) { 367 krb5_set_error_string(context, "enctype %d not supported", 368 etypes[i]); 369 return KRB5_PROG_ETYPE_NOSUPP; 370 } 371 ++i; 372 ALLOC(p, i); 373 if(!p) { 374 krb5_set_error_string (context, "malloc: out of memory"); 375 return ENOMEM; 376 } 377 memmove(p, etypes, i * sizeof(krb5_enctype)); 378 } 379 if(context->etypes) 380 free(context->etypes); 381 context->etypes = p; 382 return 0; 383 } 384 385 386 krb5_error_code 387 krb5_get_default_in_tkt_etypes(krb5_context context, 388 krb5_enctype **etypes) 389 { 390 krb5_enctype *p; 391 int i; 392 krb5_error_code ret; 393 394 if(context->etypes) { 395 for(i = 0; context->etypes[i]; i++); 396 ++i; 397 ALLOC(p, i); 398 if(!p) { 399 krb5_set_error_string (context, "malloc: out of memory"); 400 return ENOMEM; 401 } 402 memmove(p, context->etypes, i * sizeof(krb5_enctype)); 403 } else { 404 ret = default_etypes(context, &p); 405 if (ret) 406 return ret; 407 } 408 *etypes = p; 409 return 0; 410 } 411 412 const char * 413 krb5_get_err_text(krb5_context context, krb5_error_code code) 414 { 415 const char *p = NULL; 416 if(context != NULL) 417 p = com_right(context->et_list, code); 418 if(p == NULL) 419 p = strerror(code); 420 return p; 421 } 422 423 void 424 krb5_init_ets(krb5_context context) 425 { 426 if(context->et_list == NULL){ 427 krb5_add_et_list(context, initialize_krb5_error_table_r); 428 krb5_add_et_list(context, initialize_asn1_error_table_r); 429 krb5_add_et_list(context, initialize_heim_error_table_r); 430 krb5_add_et_list(context, initialize_k524_error_table_r); 431 } 432 } 433 434 void 435 krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) 436 { 437 context->use_admin_kdc = flag; 438 } 439 440 krb5_boolean 441 krb5_get_use_admin_kdc (krb5_context context) 442 { 443 return context->use_admin_kdc; 444 } 445 446 krb5_error_code 447 krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) 448 { 449 450 if(context->extra_addresses) 451 return krb5_append_addresses(context, 452 context->extra_addresses, addresses); 453 else 454 return krb5_set_extra_addresses(context, addresses); 455 } 456 457 krb5_error_code 458 krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) 459 { 460 if(context->extra_addresses) 461 krb5_free_addresses(context, context->extra_addresses); 462 463 if(addresses == NULL) { 464 if(context->extra_addresses != NULL) { 465 free(context->extra_addresses); 466 context->extra_addresses = NULL; 467 } 468 return 0; 469 } 470 if(context->extra_addresses == NULL) { 471 context->extra_addresses = malloc(sizeof(*context->extra_addresses)); 472 if(context->extra_addresses == NULL) { 473 krb5_set_error_string (context, "malloc: out of memory"); 474 return ENOMEM; 475 } 476 } 477 return krb5_copy_addresses(context, addresses, context->extra_addresses); 478 } 479 480 krb5_error_code 481 krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) 482 { 483 if(context->extra_addresses == NULL) { 484 memset(addresses, 0, sizeof(*addresses)); 485 return 0; 486 } 487 return krb5_copy_addresses(context,context->extra_addresses, addresses); 488 } 489 490 krb5_error_code 491 krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) 492 { 493 494 if(context->ignore_addresses) 495 return krb5_append_addresses(context, 496 context->ignore_addresses, addresses); 497 else 498 return krb5_set_ignore_addresses(context, addresses); 499 } 500 501 krb5_error_code 502 krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) 503 { 504 if(context->ignore_addresses) 505 krb5_free_addresses(context, context->ignore_addresses); 506 if(addresses == NULL) { 507 if(context->ignore_addresses != NULL) { 508 free(context->ignore_addresses); 509 context->ignore_addresses = NULL; 510 } 511 return 0; 512 } 513 if(context->ignore_addresses == NULL) { 514 context->ignore_addresses = malloc(sizeof(*context->ignore_addresses)); 515 if(context->ignore_addresses == NULL) { 516 krb5_set_error_string (context, "malloc: out of memory"); 517 return ENOMEM; 518 } 519 } 520 return krb5_copy_addresses(context, addresses, context->ignore_addresses); 521 } 522 523 krb5_error_code 524 krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) 525 { 526 if(context->ignore_addresses == NULL) { 527 memset(addresses, 0, sizeof(*addresses)); 528 return 0; 529 } 530 return krb5_copy_addresses(context, context->ignore_addresses, addresses); 531 } 532 533 krb5_error_code 534 krb5_set_fcache_version(krb5_context context, int version) 535 { 536 context->fcache_vno = version; 537 return 0; 538 } 539 540 krb5_error_code 541 krb5_get_fcache_version(krb5_context context, int *version) 542 { 543 *version = context->fcache_vno; 544 return 0; 545 } 546