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 krb5_data seed; 336 #ifdef KRB5_KRB4_COMPAT 337 krb5_keyblock temp_key; 338 #endif 339 /* 340 * If all that worked, then initialize the random key 341 * generators. 342 */ 343 344 seed.length = rdp->realm_mkey.length; 345 seed.data = (char *)rdp->realm_mkey.contents; 346 /* SUNW14resync - XXX */ 347 #if 0 348 if ((kret = krb5_c_random_add_entropy(rdp->realm_context, 349 KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) 350 goto whoops; 351 #endif 352 353 #ifdef KRB5_KRB4_COMPAT 354 if ((kret = krb5_c_make_random_key(rdp->realm_context, 355 ENCTYPE_DES_CBC_CRC, &temp_key))) { 356 com_err(progname, kret, 357 "while initializing V4 random key generator"); 358 goto whoops; 359 } 360 361 (void) des_init_random_number_generator(temp_key.contents); 362 krb5_free_keyblock_contents(rdp->realm_context, &temp_key); 363 #endif 364 rkey_init_done = 1; 365 } 366 whoops: 367 /* 368 * If we choked, then clean up any dirt we may have dropped on the floor. 369 */ 370 if (kret) { 371 372 finish_realm(rdp); 373 } 374 375 /* 376 * Solaris Kerberos: 377 * Set the current context back to the general context 378 */ 379 krb5_klog_set_context(kcontext); 380 381 return(kret); 382 } 383 384 krb5_sigtype 385 request_exit(int signo) 386 { 387 signal_requests_exit = 1; 388 389 #ifdef POSIX_SIGTYPE 390 return; 391 #else 392 return(0); 393 #endif 394 } 395 396 krb5_sigtype 397 request_hup(int signo) 398 { 399 signal_requests_hup = 1; 400 401 #ifdef POSIX_SIGTYPE 402 return; 403 #else 404 return(0); 405 #endif 406 } 407 408 void 409 setup_signal_handlers(void) 410 { 411 #ifdef POSIX_SIGNALS 412 (void) sigemptyset(&s_action.sa_mask); 413 s_action.sa_flags = 0; 414 s_action.sa_handler = request_exit; 415 (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL); 416 (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL); 417 s_action.sa_handler = request_hup; 418 (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL); 419 s_action.sa_handler = SIG_IGN; 420 (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL); 421 #else /* POSIX_SIGNALS */ 422 signal(SIGINT, request_exit); 423 signal(SIGTERM, request_exit); 424 signal(SIGHUP, request_hup); 425 signal(SIGPIPE, SIG_IGN); 426 #endif /* POSIX_SIGNALS */ 427 428 return; 429 } 430 431 krb5_error_code 432 setup_sam(void) 433 { 434 return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key); 435 } 436 437 void 438 usage(char *name) 439 { 440 fprintf(stderr, gettext("usage: %s [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-n]\n"), name); 441 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" 442 "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n" 443 "\t\t\tLook at each database documentation for supported arguments\n", 444 name); 445 return; 446 } 447 448 void 449 initialize_realms(krb5_context kcontext, int argc, char **argv) 450 { 451 int c; 452 char *db_name = (char *) NULL; 453 char *mkey_name = (char *) NULL; 454 char *rcname = KDCRCACHE; 455 char *lrealm = NULL; 456 krb5_error_code retval; 457 krb5_enctype menctype = ENCTYPE_UNKNOWN; 458 kdc_realm_t *rdatap; 459 krb5_boolean manual = FALSE; 460 char *default_udp_ports = 0; 461 char *default_tcp_ports = 0; 462 krb5_pointer aprof; 463 const char *hierarchy[3]; 464 char **db_args = NULL; 465 int db_args_size = 0; 466 467 #ifdef KRB5_KRB4_COMPAT 468 char *v4mode = 0; 469 #endif 470 extern char *optarg; 471 472 if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { 473 hierarchy[0] = "kdcdefaults"; 474 hierarchy[1] = "kdc_ports"; 475 hierarchy[2] = (char *) NULL; 476 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) 477 default_udp_ports = 0; 478 hierarchy[1] = "kdc_tcp_ports"; 479 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) 480 default_tcp_ports = 0; 481 hierarchy[1] = "kdc_max_tcp_connections"; 482 if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, 483 &max_tcp_data_connections)) { 484 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 485 } else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) { 486 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 487 } 488 #ifdef KRB5_KRB4_COMPAT 489 hierarchy[1] = "v4_mode"; 490 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode)) 491 v4mode = 0; 492 #endif 493 /* aprof_init can return 0 with aprof == NULL */ 494 if (aprof) 495 krb5_aprof_finish(aprof); 496 } 497 if (default_udp_ports == 0) 498 default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); 499 if (default_tcp_ports == 0) 500 default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST); 501 /* 502 * Loop through the option list. Each time we encounter a realm name, 503 * use the previously scanned options to fill in for defaults. 504 */ 505 while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:p:s:n4:X3")) != -1) { 506 switch(c) { 507 case 'x': 508 db_args_size++; 509 { 510 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 511 if( temp == NULL ) 512 { 513 /* Solaris Kerberos: Keep error messages consistent */ 514 com_err(argv[0], errno, gettext("while initializing KDC")); 515 exit(1); 516 } 517 518 db_args = temp; 519 } 520 db_args[db_args_size-1] = optarg; 521 db_args[db_args_size] = NULL; 522 break; 523 524 case 'r': /* realm name for db */ 525 if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { 526 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 527 if ((retval = init_realm(kcontext, argv[0], rdatap, optarg, 528 mkey_name, menctype, 529 default_udp_ports, 530 default_tcp_ports, manual, db_args))) { 531 /* Solaris Kerberos: Keep error messages consistent */ 532 com_err(argv[0], retval, gettext("while initializing realm %s"), optarg); 533 exit(1); 534 } 535 kdc_realmlist[kdc_numrealms] = rdatap; 536 kdc_numrealms++; 537 free(db_args), db_args=NULL, db_args_size = 0; 538 } 539 else 540 { 541 /* Solaris Kerberos: Keep error messages consistent */ 542 com_err(argv[0], errno, gettext("while initializing realm %s"), optarg); 543 exit(1); 544 } 545 } 546 break; 547 case 'd': /* pathname for db */ 548 /* now db_name is not a seperate argument. It has to be passed as part of the db_args */ 549 if( db_name == NULL ) 550 { 551 db_name = malloc(sizeof("dbname=") + strlen(optarg)); 552 if( db_name == NULL ) 553 { 554 /* Solaris Kerberos: Keep error messages consistent */ 555 com_err(argv[0], errno, gettext("while initializing KDC")); 556 exit(1); 557 } 558 559 sprintf( db_name, "dbname=%s", optarg); 560 } 561 562 db_args_size++; 563 { 564 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 565 if( temp == NULL ) 566 { 567 /* Solaris Kerberos: Keep error messages consistent */ 568 com_err(argv[0], errno, gettext("while initializing KDC")); 569 exit(1); 570 } 571 572 db_args = temp; 573 } 574 db_args[db_args_size-1] = db_name; 575 db_args[db_args_size] = NULL; 576 break; 577 case 'm': /* manual type-in of master key */ 578 manual = TRUE; 579 if (menctype == ENCTYPE_UNKNOWN) 580 menctype = ENCTYPE_DES_CBC_CRC; 581 break; 582 case 'M': /* master key name in DB */ 583 mkey_name = optarg; 584 break; 585 case 'n': 586 nofork++; /* don't detach from terminal */ 587 break; 588 case 'k': /* enctype for master key */ 589 /* Solaris Kerberos: Keep error messages consistent */ 590 if (retval = krb5_string_to_enctype(optarg, &menctype)) 591 com_err(argv[0], retval, 592 gettext("while converting %s to an enctype"), optarg); 593 break; 594 case 'R': 595 rcname = optarg; 596 break; 597 case 'p': 598 if (default_udp_ports) 599 free(default_udp_ports); 600 default_udp_ports = strdup(optarg); 601 602 if (default_tcp_ports) 603 free(default_tcp_ports); 604 default_tcp_ports = strdup(optarg); 605 606 break; 607 case '4': 608 #ifdef KRB5_KRB4_COMPAT 609 if (v4mode) 610 free(v4mode); 611 v4mode = strdup(optarg); 612 #endif 613 break; 614 case 'X': 615 #ifdef KRB5_KRB4_COMPAT 616 enable_v4_crossrealm(argv[0]); 617 #endif 618 break; 619 case '?': 620 default: 621 usage(argv[0]); 622 exit(1); 623 } 624 } 625 626 #ifdef KRB5_KRB4_COMPAT 627 /* 628 * Setup the v4 mode 629 */ 630 process_v4_mode(argv[0], v4mode); 631 free(v4mode); 632 #endif 633 634 /* 635 * Check to see if we processed any realms. 636 */ 637 if (kdc_numrealms == 0) { 638 /* no realm specified, use default realm */ 639 if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { 640 com_err(argv[0], retval, 641 gettext("while attempting to retrieve default realm")); 642 /* Solaris Kerberos: avoid double logging */ 643 #if 0 644 fprintf (stderr, "%s: %s, %s", argv[0], error_message (retval), 645 gettext("attempting to retrieve default realm\n")); 646 #endif 647 exit(1); 648 } 649 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 650 if ((retval = init_realm(kcontext, argv[0], rdatap, lrealm, 651 mkey_name, menctype, default_udp_ports, 652 default_tcp_ports, manual, db_args))) { 653 /* Solaris Kerberos: Keep error messages consistent */ 654 com_err(argv[0], retval, gettext("while initializing realm %s"), lrealm); 655 exit(1); 656 } 657 kdc_realmlist[0] = rdatap; 658 kdc_numrealms++; 659 } else { 660 if (lrealm) 661 free(lrealm); 662 } 663 } 664 665 #ifdef USE_RCACHE 666 /* 667 * Now handle the replay cache. 668 */ 669 if ((retval = kdc_initialize_rcache(kcontext, rcname))) { 670 com_err(argv[0], retval, gettext("while initializing KDC replay cache '%s'"), 671 rcname); 672 exit(1); 673 } 674 #endif 675 676 /* Ensure that this is set for our first request. */ 677 kdc_active_realm = kdc_realmlist[0]; 678 679 if (default_udp_ports) 680 free(default_udp_ports); 681 if (default_tcp_ports) 682 free(default_tcp_ports); 683 if (db_args) 684 free(db_args); 685 if (db_name) 686 free(db_name); 687 688 return; 689 } 690 691 void 692 finish_realms(char *prog) 693 { 694 int i; 695 696 for (i = 0; i < kdc_numrealms; i++) { 697 finish_realm(kdc_realmlist[i]); 698 kdc_realmlist[i] = 0; 699 } 700 } 701 702 /* 703 outline: 704 705 process args & setup 706 707 initialize database access (fetch master key, open DB) 708 709 initialize network 710 711 loop: 712 listen for packet 713 714 determine packet type, dispatch to handling routine 715 (AS or TGS (or V4?)) 716 717 reflect response 718 719 exit on signal 720 721 clean up secrets, close db 722 723 shut down network 724 725 exit 726 */ 727 728 int main(int argc, char **argv) 729 { 730 krb5_error_code retval; 731 krb5_context kcontext; 732 int errout = 0; 733 734 krb5_boolean log_stderr_set; 735 736 (void) setlocale(LC_ALL, ""); 737 738 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 739 #define TEXT_DOMAIN "KRB5KDC_TEST" /* Use this only if it weren't */ 740 #endif 741 742 (void) textdomain(TEXT_DOMAIN); 743 744 if (strrchr(argv[0], '/')) 745 argv[0] = strrchr(argv[0], '/')+1; 746 747 if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * 748 KRB5_KDC_MAX_REALMS))) { 749 fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]); 750 exit(1); 751 } 752 memset((char *) kdc_realmlist, 0, 753 (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); 754 755 /* 756 * A note about Kerberos contexts: This context, "kcontext", is used 757 * for the KDC operations, i.e. setup, network connection and error 758 * reporting. The per-realm operations use the "realm_context" 759 * associated with each realm. 760 */ 761 retval = krb5int_init_context_kdc(&kcontext); 762 if (retval) { 763 com_err(argv[0], retval, gettext("while initializing krb5")); 764 exit(1); 765 } 766 krb5_klog_init(kcontext, "kdc", argv[0], 1); 767 768 /* 769 * Solaris Kerberos: 770 * In the early stages of krb5kdc it is desirable to log error messages 771 * to stderr as well as any other logging locations specified in config 772 * files. 773 */ 774 log_stderr_set = krb5_klog_logging_to_stderr(); 775 if (log_stderr_set != TRUE) { 776 krb5_klog_add_stderr(); 777 } 778 779 /* initialize_kdc5_error_table(); SUNWresync121 XXX */ 780 781 /* 782 * Scan through the argument list 783 */ 784 initialize_realms(kcontext, argc, argv); 785 786 setup_signal_handlers(); 787 788 load_preauth_plugins(kcontext); 789 790 retval = setup_sam(); 791 if (retval) { 792 com_err(argv[0], retval, gettext("while initializing SAM")); 793 finish_realms(argv[0]); 794 return 1; 795 } 796 797 if ((retval = setup_network(argv[0]))) { 798 com_err(argv[0], retval, gettext("while initializing network")); 799 finish_realms(argv[0]); 800 return 1; 801 } 802 803 /* Solaris Kerberos: Remove the extra stderr logging */ 804 if (log_stderr_set != TRUE) 805 krb5_klog_remove_stderr(); 806 807 /* 808 * Solaris Kerberos: 809 * List the logs (FILE, STDERR, etc) which are currently being 810 * logged to and print that to stderr. Useful when trying to 811 * track down a failure via SMF. 812 */ 813 if (retval = krb5_klog_list_logs(argv[0])) { 814 com_err(argv[0], retval, gettext("while listing logs")); 815 if (log_stderr_set != TRUE) { 816 fprintf(stderr, gettext("%s: %s while listing logs\n"), 817 argv[0], error_message(retval)); 818 } 819 } 820 821 if (!nofork && daemon(0, 0)) { 822 com_err(argv[0], errno, gettext("while detaching from tty")); 823 if (log_stderr_set != TRUE) { 824 fprintf(stderr, gettext("%s: %s while detaching from tty\n"), 825 argv[0], strerror(errno)); 826 } 827 finish_realms(argv[0]); 828 return 1; 829 } 830 if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) { 831 com_err(argv[0], retval, gettext("while logging message")); 832 errout++; 833 }; 834 835 if ((retval = listen_and_process(argv[0]))) { 836 com_err(argv[0], retval, gettext("while processing network requests")); 837 errout++; 838 } 839 if ((retval = closedown_network(argv[0]))) { 840 com_err(argv[0], retval, gettext("while shutting down network")); 841 errout++; 842 } 843 krb5_klog_syslog(LOG_INFO, "shutting down"); 844 unload_preauth_plugins(kcontext); 845 krb5_klog_close(kdc_context); 846 finish_realms(argv[0]); 847 if (kdc_realmlist) 848 free(kdc_realmlist); 849 #ifdef USE_RCACHE 850 (void) krb5_rc_close(kcontext, kdc_rcache); 851 #endif 852 #ifndef NOCACHE 853 kdc_free_lookaside(kcontext); 854 #endif 855 krb5_free_context(kcontext); 856 return errout; 857 } 858 859 860 861 862