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