1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 7 /* 8 * kdc/main.c 9 * 10 * Copyright 1990,2001 by the Massachusetts Institute of Technology. 11 * 12 * Export of this software from the United States of America may 13 * require a specific license from the United States Government. 14 * It is the responsibility of any person or organization contemplating 15 * export to obtain such a license before exporting. 16 * 17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 18 * distribute this software and its documentation for any purpose and 19 * without fee is hereby granted, provided that the above copyright 20 * notice appear in all copies and that both that copyright notice and 21 * this permission notice appear in supporting documentation, and that 22 * the name of M.I.T. not be used in advertising or publicity pertaining 23 * to distribution of the software without specific, written prior 24 * permission. Furthermore if you modify this software you must label 25 * your software as modified software and not distribute it in such a 26 * fashion that it might be confused with the original M.I.T. software. 27 * M.I.T. makes no representations about the suitability of 28 * this software for any purpose. It is provided "as is" without express 29 * or implied warranty. 30 * 31 * 32 * Main procedure body for the KDC server process. 33 */ 34 35 #include <stdio.h> 36 #include <syslog.h> 37 #include <signal.h> 38 #include <errno.h> 39 #include <netdb.h> 40 41 #include "k5-int.h" 42 #include "com_err.h" 43 #include "adm.h" 44 #include "adm_proto.h" 45 #include "kdc_util.h" 46 #include "extern.h" 47 #include "kdc5_err.h" 48 #include <libintl.h> 49 #include <locale.h> 50 51 #ifdef HAVE_NETINET_IN_H 52 #include <netinet/in.h> 53 #endif 54 55 #ifdef KRB5_KRB4_COMPAT 56 #include <des.h> 57 #endif 58 59 #if defined(NEED_DAEMON_PROTO) 60 extern int daemon(int, int); 61 #endif 62 63 void usage (char *); 64 65 krb5_sigtype request_exit (int); 66 krb5_sigtype request_hup (int); 67 68 void setup_signal_handlers (void); 69 70 krb5_error_code setup_sam (void); 71 72 void initialize_realms (krb5_context, int, char **); 73 74 void finish_realms (char *); 75 76 static int nofork = 0; 77 static int rkey_init_done = 0; 78 79 /* Solaris Kerberos: global here that other functions access */ 80 int max_tcp_data_connections; 81 82 #ifdef POSIX_SIGNALS 83 static struct sigaction s_action; 84 #endif /* POSIX_SIGNALS */ 85 86 #define KRB5_KDC_MAX_REALMS 32 87 88 /* 89 * Find the realm entry for a given realm. 90 */ 91 kdc_realm_t * 92 find_realm_data(char *rname, krb5_ui_4 rsize) 93 { 94 int i; 95 for (i=0; i<kdc_numrealms; i++) { 96 if ((rsize == strlen(kdc_realmlist[i]->realm_name)) && 97 !strncmp(rname, kdc_realmlist[i]->realm_name, rsize)) 98 return(kdc_realmlist[i]); 99 } 100 return((kdc_realm_t *) NULL); 101 } 102 103 krb5_error_code 104 setup_server_realm(krb5_principal sprinc) 105 { 106 krb5_error_code kret; 107 kdc_realm_t *newrealm; 108 109 kret = 0; 110 if (kdc_numrealms > 1) { 111 if (!(newrealm = find_realm_data(sprinc->realm.data, 112 (krb5_ui_4) sprinc->realm.length))) 113 kret = ENOENT; 114 else 115 kdc_active_realm = newrealm; 116 } 117 else 118 kdc_active_realm = kdc_realmlist[0]; 119 return(kret); 120 } 121 122 static void 123 finish_realm(kdc_realm_t *rdp) 124 { 125 if (rdp->realm_dbname) 126 free(rdp->realm_dbname); 127 if (rdp->realm_mpname) 128 free(rdp->realm_mpname); 129 if (rdp->realm_stash) 130 free(rdp->realm_stash); 131 if (rdp->realm_ports) 132 free(rdp->realm_ports); 133 if (rdp->realm_tcp_ports) 134 free(rdp->realm_tcp_ports); 135 if (rdp->realm_keytab) 136 krb5_kt_close(rdp->realm_context, rdp->realm_keytab); 137 if (rdp->realm_context) { 138 if (rdp->realm_mprinc) 139 krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); 140 if (rdp->realm_mkey.length && rdp->realm_mkey.contents) { 141 memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length); 142 free(rdp->realm_mkey.contents); 143 } 144 krb5_db_fini(rdp->realm_context); 145 if (rdp->realm_tgsprinc) 146 krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); 147 krb5_free_context(rdp->realm_context); 148 } 149 memset((char *) rdp, 0, sizeof(*rdp)); 150 free(rdp); 151 } 152 153 /* 154 * Initialize a realm control structure from the alternate profile or from 155 * the specified defaults. 156 * 157 * After we're complete here, the essence of the realm is embodied in the 158 * realm data and we should be all set to begin operation for that realm. 159 */ 160 static krb5_error_code 161 init_realm(krb5_context kcontext, char *progname, kdc_realm_t *rdp, char *realm, 162 char *def_mpname, krb5_enctype def_enctype, char *def_udp_ports, 163 char *def_tcp_ports, krb5_boolean def_manual, char **db_args) 164 { 165 krb5_error_code kret; 166 krb5_boolean manual; 167 krb5_realm_params *rparams; 168 169 memset((char *) rdp, 0, sizeof(kdc_realm_t)); 170 if (!realm) { 171 kret = EINVAL; 172 goto whoops; 173 } 174 175 rdp->realm_name = realm; 176 kret = krb5int_init_context_kdc(&rdp->realm_context); 177 if (kret) { 178 com_err(progname, kret, gettext("while getting context for realm %s"), 179 realm); 180 goto whoops; 181 } 182 183 /* 184 * Solaris Kerberos: 185 * Set the current context to that of the realm being init'ed 186 */ 187 krb5_klog_set_context(rdp->realm_context); 188 189 kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name, 190 &rparams); 191 if (kret) { 192 com_err(progname, kret, gettext("while reading realm parameters")); 193 goto whoops; 194 } 195 196 /* Handle profile file name */ 197 if (rparams && rparams->realm_profile) 198 rdp->realm_profile = strdup(rparams->realm_profile); 199 200 /* Handle master key name */ 201 if (rparams && rparams->realm_mkey_name) 202 rdp->realm_mpname = strdup(rparams->realm_mkey_name); 203 else 204 rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : 205 strdup(KRB5_KDB_M_NAME); 206 207 /* Handle KDC ports */ 208 if (rparams && rparams->realm_kdc_ports) 209 rdp->realm_ports = strdup(rparams->realm_kdc_ports); 210 else 211 rdp->realm_ports = strdup(def_udp_ports); 212 if (rparams && rparams->realm_kdc_tcp_ports) 213 rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports); 214 else 215 rdp->realm_tcp_ports = strdup(def_tcp_ports); 216 217 /* Handle stash file */ 218 if (rparams && rparams->realm_stash_file) { 219 rdp->realm_stash = strdup(rparams->realm_stash_file); 220 manual = FALSE; 221 } else 222 manual = def_manual; 223 224 /* Handle master key type */ 225 if (rparams && rparams->realm_enctype_valid) 226 rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype; 227 else 228 rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; 229 230 /* Handle reject-bad-transit flag */ 231 if (rparams && rparams->realm_reject_bad_transit_valid) 232 rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit; 233 else 234 rdp->realm_reject_bad_transit = 1; 235 236 /* Handle ticket maximum life */ 237 rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ? 238 rparams->realm_max_life : KRB5_KDB_MAX_LIFE; 239 240 /* Handle ticket renewable maximum life */ 241 rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ? 242 rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; 243 244 if (rparams) 245 krb5_free_realm_params(rdp->realm_context, rparams); 246 247 /* 248 * We've got our parameters, now go and setup our realm context. 249 */ 250 251 /* Set the default realm of this context */ 252 if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) { 253 com_err(progname, kret, gettext("while setting default realm to %s"), 254 realm); 255 goto whoops; 256 } 257 258 /* first open the database before doing anything */ 259 #ifdef KRBCONF_KDC_MODIFIES_KDB 260 if ((kret = krb5_db_open(rdp->realm_context, db_args, 261 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC))) { 262 #else 263 if ((kret = krb5_db_open(rdp->realm_context, db_args, 264 KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC))) { 265 #endif 266 /* 267 * Solaris Kerberos: 268 * Make sure that error messages are printed using gettext 269 */ 270 com_err(progname, kret, 271 gettext("while initializing database for realm %s"), realm); 272 goto whoops; 273 } 274 275 /* Assemble and parse the master key name */ 276 if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname, 277 rdp->realm_name, (char **) NULL, 278 &rdp->realm_mprinc))) { 279 com_err(progname, kret, 280 gettext("while setting up master key name %s for realm %s"), 281 rdp->realm_mpname, realm); 282 goto whoops; 283 } 284 285 /* 286 * Get the master key. 287 */ 288 if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, 289 rdp->realm_mkey.enctype, manual, 290 FALSE, rdp->realm_stash, 291 0, &rdp->realm_mkey))) { 292 com_err(progname, kret, 293 gettext("while fetching master key %s for realm %s"), 294 rdp->realm_mpname, realm); 295 goto whoops; 296 } 297 298 /* Verify the master key */ 299 if ((kret = krb5_db_verify_master_key(rdp->realm_context, 300 rdp->realm_mprinc, 301 &rdp->realm_mkey))) { 302 com_err(progname, kret, 303 gettext("while verifying master key for realm %s"), 304 realm); 305 goto whoops; 306 } 307 308 if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { 309 com_err(progname, kret, 310 gettext("while processing master key for realm %s"), 311 realm); 312 goto whoops; 313 } 314 315 /* Set up the keytab */ 316 if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, 317 &rdp->realm_keytab))) { 318 com_err(progname, kret, 319 gettext("while resolving kdb keytab for realm %s"), 320 realm); 321 goto whoops; 322 } 323 324 /* Preformat the TGS name */ 325 if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc, 326 strlen(realm), realm, KRB5_TGS_NAME, 327 realm, (char *) NULL))) { 328 com_err(progname, kret, 329 gettext("while building TGS name for realm %s"), 330 realm); 331 goto whoops; 332 } 333 334 if (!rkey_init_done) { 335 #ifdef KRB5_KRB4_COMPAT 336 krb5_keyblock temp_key; 337 #endif 338 /* 339 * If all that worked, then initialize the random key 340 * generators. 341 */ 342 #ifdef KRB5_KRB4_COMPAT 343 if ((kret = krb5_c_make_random_key(rdp->realm_context, 344 ENCTYPE_DES_CBC_CRC, &temp_key))) { 345 com_err(progname, kret, 346 "while initializing V4 random key generator"); 347 goto whoops; 348 } 349 350 (void) des_init_random_number_generator(temp_key.contents); 351 krb5_free_keyblock_contents(rdp->realm_context, &temp_key); 352 #endif 353 rkey_init_done = 1; 354 } 355 whoops: 356 /* 357 * If we choked, then clean up any dirt we may have dropped on the floor. 358 */ 359 if (kret) { 360 361 finish_realm(rdp); 362 } 363 364 /* 365 * Solaris Kerberos: 366 * Set the current context back to the general context 367 */ 368 krb5_klog_set_context(kcontext); 369 370 return(kret); 371 } 372 373 krb5_sigtype 374 request_exit(int signo) 375 { 376 signal_requests_exit = 1; 377 378 #ifdef POSIX_SIGTYPE 379 return; 380 #else 381 return(0); 382 #endif 383 } 384 385 krb5_sigtype 386 request_hup(int signo) 387 { 388 signal_requests_hup = 1; 389 390 #ifdef POSIX_SIGTYPE 391 return; 392 #else 393 return(0); 394 #endif 395 } 396 397 void 398 setup_signal_handlers(void) 399 { 400 #ifdef POSIX_SIGNALS 401 (void) sigemptyset(&s_action.sa_mask); 402 s_action.sa_flags = 0; 403 s_action.sa_handler = request_exit; 404 (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL); 405 (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL); 406 s_action.sa_handler = request_hup; 407 (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL); 408 s_action.sa_handler = SIG_IGN; 409 (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL); 410 #else /* POSIX_SIGNALS */ 411 signal(SIGINT, request_exit); 412 signal(SIGTERM, request_exit); 413 signal(SIGHUP, request_hup); 414 signal(SIGPIPE, SIG_IGN); 415 #endif /* POSIX_SIGNALS */ 416 417 return; 418 } 419 420 krb5_error_code 421 setup_sam(void) 422 { 423 return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key); 424 } 425 426 void 427 usage(char *name) 428 { 429 fprintf(stderr, gettext("usage: %s [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-n]\n"), name); 430 fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-X] [-n]\n" 431 "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n" 432 "\t\t\tLook at each database documentation for supported arguments\n", 433 name); 434 return; 435 } 436 437 void 438 initialize_realms(krb5_context kcontext, int argc, char **argv) 439 { 440 int c; 441 char *db_name = (char *) NULL; 442 char *mkey_name = (char *) NULL; 443 char *rcname __unused; 444 char *lrealm = NULL; 445 krb5_error_code retval; 446 krb5_enctype menctype = ENCTYPE_UNKNOWN; 447 kdc_realm_t *rdatap; 448 krb5_boolean manual = FALSE; 449 char *default_udp_ports = 0; 450 char *default_tcp_ports = 0; 451 krb5_pointer aprof; 452 const char *hierarchy[3]; 453 char **db_args = NULL; 454 int db_args_size = 0; 455 456 #ifdef KRB5_KRB4_COMPAT 457 char *v4mode = 0; 458 #endif 459 extern char *optarg; 460 461 rcname = KDCRCACHE; 462 463 if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { 464 hierarchy[0] = "kdcdefaults"; 465 hierarchy[1] = "kdc_ports"; 466 hierarchy[2] = (char *) NULL; 467 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) 468 default_udp_ports = 0; 469 hierarchy[1] = "kdc_tcp_ports"; 470 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) 471 default_tcp_ports = 0; 472 hierarchy[1] = "kdc_max_tcp_connections"; 473 if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, 474 &max_tcp_data_connections)) { 475 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 476 } else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) { 477 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 478 } 479 #ifdef KRB5_KRB4_COMPAT 480 hierarchy[1] = "v4_mode"; 481 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode)) 482 v4mode = 0; 483 #endif 484 /* aprof_init can return 0 with aprof == NULL */ 485 if (aprof) 486 krb5_aprof_finish(aprof); 487 } 488 if (default_udp_ports == 0) 489 default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); 490 if (default_tcp_ports == 0) 491 default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST); 492 /* 493 * Loop through the option list. Each time we encounter a realm name, 494 * use the previously scanned options to fill in for defaults. 495 */ 496 while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:p:s:n4:X3")) != -1) { 497 switch(c) { 498 case 'x': 499 db_args_size++; 500 { 501 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 502 if( temp == NULL ) 503 { 504 /* Solaris Kerberos: Keep error messages consistent */ 505 com_err(argv[0], errno, gettext("while initializing KDC")); 506 exit(1); 507 } 508 509 db_args = temp; 510 } 511 db_args[db_args_size-1] = optarg; 512 db_args[db_args_size] = NULL; 513 break; 514 515 case 'r': /* realm name for db */ 516 if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { 517 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 518 if ((retval = init_realm(kcontext, argv[0], rdatap, optarg, 519 mkey_name, menctype, 520 default_udp_ports, 521 default_tcp_ports, manual, db_args))) { 522 /* Solaris Kerberos: Keep error messages consistent */ 523 com_err(argv[0], retval, gettext("while initializing realm %s"), optarg); 524 exit(1); 525 } 526 kdc_realmlist[kdc_numrealms] = rdatap; 527 kdc_numrealms++; 528 free(db_args), db_args=NULL, db_args_size = 0; 529 } 530 else 531 { 532 /* Solaris Kerberos: Keep error messages consistent */ 533 com_err(argv[0], errno, gettext("while initializing realm %s"), optarg); 534 exit(1); 535 } 536 } 537 break; 538 case 'd': /* pathname for db */ 539 /* now db_name is not a seperate argument. It has to be passed as part of the db_args */ 540 if( db_name == NULL ) 541 { 542 db_name = malloc(sizeof("dbname=") + strlen(optarg)); 543 if( db_name == NULL ) 544 { 545 /* Solaris Kerberos: Keep error messages consistent */ 546 com_err(argv[0], errno, gettext("while initializing KDC")); 547 exit(1); 548 } 549 550 sprintf( db_name, "dbname=%s", optarg); 551 } 552 553 db_args_size++; 554 { 555 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 556 if( temp == NULL ) 557 { 558 /* Solaris Kerberos: Keep error messages consistent */ 559 com_err(argv[0], errno, gettext("while initializing KDC")); 560 exit(1); 561 } 562 563 db_args = temp; 564 } 565 db_args[db_args_size-1] = db_name; 566 db_args[db_args_size] = NULL; 567 break; 568 case 'm': /* manual type-in of master key */ 569 manual = TRUE; 570 if (menctype == ENCTYPE_UNKNOWN) 571 menctype = ENCTYPE_DES_CBC_CRC; 572 break; 573 case 'M': /* master key name in DB */ 574 mkey_name = optarg; 575 break; 576 case 'n': 577 nofork++; /* don't detach from terminal */ 578 break; 579 case 'k': /* enctype for master key */ 580 /* Solaris Kerberos: Keep error messages consistent */ 581 if (retval = krb5_string_to_enctype(optarg, &menctype)) 582 com_err(argv[0], retval, 583 gettext("while converting %s to an enctype"), optarg); 584 break; 585 case 'R': 586 rcname = optarg; 587 break; 588 case 'p': 589 if (default_udp_ports) 590 free(default_udp_ports); 591 default_udp_ports = strdup(optarg); 592 593 if (default_tcp_ports) 594 free(default_tcp_ports); 595 default_tcp_ports = strdup(optarg); 596 597 break; 598 case '4': 599 #ifdef KRB5_KRB4_COMPAT 600 if (v4mode) 601 free(v4mode); 602 v4mode = strdup(optarg); 603 #endif 604 break; 605 case 'X': 606 #ifdef KRB5_KRB4_COMPAT 607 enable_v4_crossrealm(argv[0]); 608 #endif 609 break; 610 case '?': 611 default: 612 usage(argv[0]); 613 exit(1); 614 } 615 } 616 617 #ifdef KRB5_KRB4_COMPAT 618 /* 619 * Setup the v4 mode 620 */ 621 process_v4_mode(argv[0], v4mode); 622 free(v4mode); 623 #endif 624 625 /* 626 * Check to see if we processed any realms. 627 */ 628 if (kdc_numrealms == 0) { 629 /* no realm specified, use default realm */ 630 if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { 631 com_err(argv[0], retval, 632 gettext("while attempting to retrieve default realm")); 633 /* Solaris Kerberos: avoid double logging */ 634 #if 0 635 fprintf (stderr, "%s: %s, %s", argv[0], error_message (retval), 636 gettext("attempting to retrieve default realm\n")); 637 #endif 638 exit(1); 639 } 640 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 641 if ((retval = init_realm(kcontext, argv[0], rdatap, lrealm, 642 mkey_name, menctype, default_udp_ports, 643 default_tcp_ports, manual, db_args))) { 644 /* Solaris Kerberos: Keep error messages consistent */ 645 com_err(argv[0], retval, gettext("while initializing realm %s"), lrealm); 646 exit(1); 647 } 648 kdc_realmlist[0] = rdatap; 649 kdc_numrealms++; 650 } else { 651 if (lrealm) 652 free(lrealm); 653 } 654 } 655 656 #ifdef USE_RCACHE 657 /* 658 * Now handle the replay cache. 659 */ 660 if ((retval = kdc_initialize_rcache(kcontext, rcname))) { 661 com_err(argv[0], retval, gettext("while initializing KDC replay cache '%s'"), 662 rcname); 663 exit(1); 664 } 665 #endif 666 667 /* Ensure that this is set for our first request. */ 668 kdc_active_realm = kdc_realmlist[0]; 669 670 if (default_udp_ports) 671 free(default_udp_ports); 672 if (default_tcp_ports) 673 free(default_tcp_ports); 674 if (db_args) 675 free(db_args); 676 if (db_name) 677 free(db_name); 678 679 return; 680 } 681 682 void 683 finish_realms(char *prog) 684 { 685 int i; 686 687 for (i = 0; i < kdc_numrealms; i++) { 688 finish_realm(kdc_realmlist[i]); 689 kdc_realmlist[i] = 0; 690 } 691 } 692 693 /* 694 outline: 695 696 process args & setup 697 698 initialize database access (fetch master key, open DB) 699 700 initialize network 701 702 loop: 703 listen for packet 704 705 determine packet type, dispatch to handling routine 706 (AS or TGS (or V4?)) 707 708 reflect response 709 710 exit on signal 711 712 clean up secrets, close db 713 714 shut down network 715 716 exit 717 */ 718 719 int main(int argc, char **argv) 720 { 721 krb5_error_code retval; 722 krb5_context kcontext; 723 int errout = 0; 724 725 krb5_boolean log_stderr_set; 726 727 (void) setlocale(LC_ALL, ""); 728 729 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 730 #define TEXT_DOMAIN "KRB5KDC_TEST" /* Use this only if it weren't */ 731 #endif 732 733 (void) textdomain(TEXT_DOMAIN); 734 735 if (strrchr(argv[0], '/')) 736 argv[0] = strrchr(argv[0], '/')+1; 737 738 if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * 739 KRB5_KDC_MAX_REALMS))) { 740 fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]); 741 exit(1); 742 } 743 memset((char *) kdc_realmlist, 0, 744 (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); 745 746 /* 747 * A note about Kerberos contexts: This context, "kcontext", is used 748 * for the KDC operations, i.e. setup, network connection and error 749 * reporting. The per-realm operations use the "realm_context" 750 * associated with each realm. 751 */ 752 retval = krb5int_init_context_kdc(&kcontext); 753 if (retval) { 754 com_err(argv[0], retval, gettext("while initializing krb5")); 755 exit(1); 756 } 757 krb5_klog_init(kcontext, "kdc", argv[0], 1); 758 759 /* 760 * Solaris Kerberos: 761 * In the early stages of krb5kdc it is desirable to log error messages 762 * to stderr as well as any other logging locations specified in config 763 * files. 764 */ 765 log_stderr_set = krb5_klog_logging_to_stderr(); 766 if (log_stderr_set != TRUE) { 767 krb5_klog_add_stderr(); 768 } 769 770 /* initialize_kdc5_error_table(); SUNWresync121 XXX */ 771 772 /* 773 * Scan through the argument list 774 */ 775 initialize_realms(kcontext, argc, argv); 776 777 setup_signal_handlers(); 778 779 load_preauth_plugins(kcontext); 780 781 retval = setup_sam(); 782 if (retval) { 783 com_err(argv[0], retval, gettext("while initializing SAM")); 784 finish_realms(argv[0]); 785 return 1; 786 } 787 788 if ((retval = setup_network(argv[0]))) { 789 com_err(argv[0], retval, gettext("while initializing network")); 790 finish_realms(argv[0]); 791 return 1; 792 } 793 794 /* Solaris Kerberos: Remove the extra stderr logging */ 795 if (log_stderr_set != TRUE) 796 krb5_klog_remove_stderr(); 797 798 /* 799 * Solaris Kerberos: 800 * List the logs (FILE, STDERR, etc) which are currently being 801 * logged to and print that to stderr. Useful when trying to 802 * track down a failure via SMF. 803 */ 804 if (retval = krb5_klog_list_logs(argv[0])) { 805 com_err(argv[0], retval, gettext("while listing logs")); 806 if (log_stderr_set != TRUE) { 807 fprintf(stderr, gettext("%s: %s while listing logs\n"), 808 argv[0], error_message(retval)); 809 } 810 } 811 812 if (!nofork && daemon(0, 0)) { 813 com_err(argv[0], errno, gettext("while detaching from tty")); 814 if (log_stderr_set != TRUE) { 815 fprintf(stderr, gettext("%s: %s while detaching from tty\n"), 816 argv[0], strerror(errno)); 817 } 818 finish_realms(argv[0]); 819 return 1; 820 } 821 if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) { 822 com_err(argv[0], retval, gettext("while logging message")); 823 errout++; 824 }; 825 826 if ((retval = listen_and_process(argv[0]))) { 827 com_err(argv[0], retval, gettext("while processing network requests")); 828 errout++; 829 } 830 if ((retval = closedown_network(argv[0]))) { 831 com_err(argv[0], retval, gettext("while shutting down network")); 832 errout++; 833 } 834 krb5_klog_syslog(LOG_INFO, "shutting down"); 835 unload_preauth_plugins(kcontext); 836 krb5_klog_close(kdc_context); 837 finish_realms(argv[0]); 838 if (kdc_realmlist) 839 free(kdc_realmlist); 840 #ifdef USE_RCACHE 841 (void) krb5_rc_close(kcontext, kdc_rcache); 842 #endif 843 #ifndef NOCACHE 844 kdc_free_lookaside(kcontext); 845 #endif 846 krb5_free_context(kcontext); 847 return errout; 848 } 849 850 851 852 853