1 /* 2 * Copyright 2007 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(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 kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name, 185 (char *) NULL, (char *) NULL, &rparams); 186 if (kret) { 187 com_err(progname, kret, gettext("while reading realm parameters")); 188 goto whoops; 189 } 190 191 /* Handle profile file name */ 192 if (rparams && rparams->realm_profile) 193 rdp->realm_profile = strdup(rparams->realm_profile); 194 195 /* Handle master key name */ 196 if (rparams && rparams->realm_mkey_name) 197 rdp->realm_mpname = strdup(rparams->realm_mkey_name); 198 else 199 rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : 200 strdup(KRB5_KDB_M_NAME); 201 202 /* Handle KDC ports */ 203 if (rparams && rparams->realm_kdc_ports) 204 rdp->realm_ports = strdup(rparams->realm_kdc_ports); 205 else 206 rdp->realm_ports = strdup(def_udp_ports); 207 if (rparams && rparams->realm_kdc_tcp_ports) 208 rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports); 209 else 210 rdp->realm_tcp_ports = strdup(def_tcp_ports); 211 212 /* Handle stash file */ 213 if (rparams && rparams->realm_stash_file) { 214 rdp->realm_stash = strdup(rparams->realm_stash_file); 215 manual = FALSE; 216 } else 217 manual = def_manual; 218 219 /* Handle master key type */ 220 if (rparams && rparams->realm_enctype_valid) 221 rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype; 222 else 223 rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; 224 225 /* Handle reject-bad-transit flag */ 226 if (rparams && rparams->realm_reject_bad_transit_valid) 227 rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit; 228 else 229 rdp->realm_reject_bad_transit = 1; 230 231 /* Handle ticket maximum life */ 232 rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ? 233 rparams->realm_max_life : KRB5_KDB_MAX_LIFE; 234 235 /* Handle ticket renewable maximum life */ 236 rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ? 237 rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; 238 239 if (rparams) 240 krb5_free_realm_params(rdp->realm_context, rparams); 241 242 /* 243 * We've got our parameters, now go and setup our realm context. 244 */ 245 246 /* Set the default realm of this context */ 247 if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) { 248 com_err(progname, kret, gettext("while setting default realm to %s"), 249 realm); 250 goto whoops; 251 } 252 253 /* first open the database before doing anything */ 254 #ifdef KRBCONF_KDC_MODIFIES_KDB 255 if ((kret = krb5_db_open(rdp->realm_context, db_args, 256 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC))) { 257 #else 258 if ((kret = krb5_db_open(rdp->realm_context, db_args, 259 KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC))) { 260 #endif 261 com_err(progname, kret, 262 "while initializing database for realm %s", realm); 263 goto whoops; 264 } 265 266 /* Assemble and parse the master key name */ 267 if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname, 268 rdp->realm_name, (char **) NULL, 269 &rdp->realm_mprinc))) { 270 com_err(progname, kret, 271 gettext("while setting up master key name %s for realm %s"), 272 rdp->realm_mpname, realm); 273 goto whoops; 274 } 275 276 /* 277 * Get the master key. 278 */ 279 if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, 280 rdp->realm_mkey.enctype, manual, 281 FALSE, rdp->realm_stash, 282 0, &rdp->realm_mkey))) { 283 com_err(progname, kret, 284 gettext("while fetching master key %s for realm %s"), 285 rdp->realm_mpname, realm); 286 goto whoops; 287 } 288 289 /* Verify the master key */ 290 if ((kret = krb5_db_verify_master_key(rdp->realm_context, 291 rdp->realm_mprinc, 292 &rdp->realm_mkey))) { 293 com_err(progname, kret, 294 gettext("while verifying master key for realm %s"), 295 realm); 296 goto whoops; 297 } 298 299 if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { 300 com_err(progname, kret, 301 gettext("while processing master key for realm %s"), 302 realm); 303 goto whoops; 304 } 305 306 /* Set up the keytab */ 307 if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, 308 &rdp->realm_keytab))) { 309 com_err(progname, kret, 310 gettext("while resolving kdb keytab for realm %s"), 311 realm); 312 goto whoops; 313 } 314 315 /* Preformat the TGS name */ 316 if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc, 317 strlen(realm), realm, KRB5_TGS_NAME, 318 realm, (char *) NULL))) { 319 com_err(progname, kret, 320 gettext("while building TGS name for realm %s"), 321 realm); 322 goto whoops; 323 } 324 325 if (!rkey_init_done) { 326 krb5_data seed; 327 #ifdef KRB5_KRB4_COMPAT 328 krb5_keyblock temp_key; 329 #endif 330 /* 331 * If all that worked, then initialize the random key 332 * generators. 333 */ 334 335 seed.length = rdp->realm_mkey.length; 336 seed.data = (char *)rdp->realm_mkey.contents; 337 /* SUNW14resync - XXX */ 338 #if 0 339 if ((kret = krb5_c_random_add_entropy(rdp->realm_context, 340 KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) 341 goto whoops; 342 #endif 343 344 #ifdef KRB5_KRB4_COMPAT 345 if ((kret = krb5_c_make_random_key(rdp->realm_context, 346 ENCTYPE_DES_CBC_CRC, &temp_key))) { 347 com_err(progname, kret, 348 "while initializing V4 random key generator"); 349 goto whoops; 350 } 351 352 (void) des_init_random_number_generator(temp_key.contents); 353 krb5_free_keyblock_contents(rdp->realm_context, &temp_key); 354 #endif 355 rkey_init_done = 1; 356 } 357 whoops: 358 /* 359 * If we choked, then clean up any dirt we may have dropped on the floor. 360 */ 361 if (kret) { 362 363 finish_realm(rdp); 364 } 365 return(kret); 366 } 367 368 krb5_sigtype 369 request_exit(int signo) 370 { 371 signal_requests_exit = 1; 372 373 #ifdef POSIX_SIGTYPE 374 return; 375 #else 376 return(0); 377 #endif 378 } 379 380 krb5_sigtype 381 request_hup(int signo) 382 { 383 signal_requests_hup = 1; 384 385 #ifdef POSIX_SIGTYPE 386 return; 387 #else 388 return(0); 389 #endif 390 } 391 392 void 393 setup_signal_handlers(void) 394 { 395 #ifdef POSIX_SIGNALS 396 (void) sigemptyset(&s_action.sa_mask); 397 s_action.sa_flags = 0; 398 s_action.sa_handler = request_exit; 399 (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL); 400 (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL); 401 s_action.sa_handler = request_hup; 402 (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL); 403 s_action.sa_handler = SIG_IGN; 404 (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL); 405 #else /* POSIX_SIGNALS */ 406 signal(SIGINT, request_exit); 407 signal(SIGTERM, request_exit); 408 signal(SIGHUP, request_hup); 409 signal(SIGPIPE, SIG_IGN); 410 #endif /* POSIX_SIGNALS */ 411 412 return; 413 } 414 415 krb5_error_code 416 setup_sam(void) 417 { 418 return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key); 419 } 420 421 void 422 usage(char *name) 423 { 424 fprintf(stderr, gettext("usage: %s [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-n]\n"), name); 425 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" 426 "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n" 427 "\t\t\tLook at each database documentation for supported arguments\n", 428 name); 429 return; 430 } 431 432 void 433 initialize_realms(krb5_context kcontext, int argc, char **argv) 434 { 435 int c; 436 char *db_name = (char *) NULL; 437 char *mkey_name = (char *) NULL; 438 char *rcname = KDCRCACHE; 439 char *lrealm; 440 krb5_error_code retval; 441 krb5_enctype menctype = ENCTYPE_UNKNOWN; 442 kdc_realm_t *rdatap; 443 krb5_boolean manual = FALSE; 444 char *default_udp_ports = 0; 445 char *default_tcp_ports = 0; 446 krb5_pointer aprof; 447 const char *hierarchy[3]; 448 char **db_args = NULL; 449 int db_args_size = 0; 450 451 #ifdef KRB5_KRB4_COMPAT 452 char *v4mode = 0; 453 #endif 454 extern char *optarg; 455 456 if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { 457 hierarchy[0] = "kdcdefaults"; 458 hierarchy[1] = "kdc_ports"; 459 hierarchy[2] = (char *) NULL; 460 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) 461 default_udp_ports = 0; 462 hierarchy[1] = "kdc_tcp_ports"; 463 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) 464 default_tcp_ports = 0; 465 hierarchy[1] = "kdc_max_tcp_connections"; 466 if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, 467 &max_tcp_data_connections)) { 468 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 469 } else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) { 470 max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS; 471 } 472 #ifdef KRB5_KRB4_COMPAT 473 hierarchy[1] = "v4_mode"; 474 if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode)) 475 v4mode = 0; 476 #endif 477 /* aprof_init can return 0 with aprof == NULL */ 478 if (aprof) 479 krb5_aprof_finish(aprof); 480 } 481 if (default_udp_ports == 0) 482 default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); 483 if (default_tcp_ports == 0) 484 default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST); 485 /* 486 * Loop through the option list. Each time we encounter a realm name, 487 * use the previously scanned options to fill in for defaults. 488 */ 489 while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:p:s:n4:X3")) != -1) { 490 switch(c) { 491 case 'x': 492 db_args_size++; 493 { 494 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 495 if( temp == NULL ) 496 { 497 fprintf(stderr, gettext("%s: KDC cannot initialize. Not enough memory\n"), 498 argv[0]); 499 exit(1); 500 } 501 502 db_args = temp; 503 } 504 db_args[db_args_size-1] = optarg; 505 db_args[db_args_size] = NULL; 506 break; 507 508 case 'r': /* realm name for db */ 509 if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { 510 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 511 if ((retval = init_realm(argv[0], rdatap, optarg, 512 mkey_name, menctype, 513 default_udp_ports, 514 default_tcp_ports, manual, db_args))) { 515 fprintf(stderr,gettext("%s: cannot initialize realm %s\n"), 516 argv[0], optarg); 517 exit(1); 518 } 519 kdc_realmlist[kdc_numrealms] = rdatap; 520 kdc_numrealms++; 521 free(db_args), db_args=NULL, db_args_size = 0; 522 } 523 else 524 { 525 fprintf(stderr, gettext("%s: cannot initialize realm %s. Not enough memory\n"), 526 argv[0], optarg); 527 exit(1); 528 } 529 } 530 break; 531 case 'd': /* pathname for db */ 532 /* now db_name is not a seperate argument. It has to be passed as part of the db_args */ 533 if( db_name == NULL ) 534 { 535 db_name = malloc(sizeof("dbname=") + strlen(optarg)); 536 if( db_name == NULL ) 537 { 538 fprintf(stderr, gettext("%s: KDC cannot initialize. Not enough memory\n"), 539 argv[0] ); 540 exit(1); 541 } 542 543 sprintf( db_name, "dbname=%s", optarg); 544 } 545 546 db_args_size++; 547 { 548 char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ 549 if( temp == NULL ) 550 { 551 fprintf(stderr, gettext("%s: KDC cannot initialize. Not enough memory\n"), 552 argv[0]); 553 exit(1); 554 } 555 556 db_args = temp; 557 } 558 db_args[db_args_size-1] = db_name; 559 db_args[db_args_size] = NULL; 560 break; 561 case 'm': /* manual type-in of master key */ 562 manual = TRUE; 563 if (menctype == ENCTYPE_UNKNOWN) 564 menctype = ENCTYPE_DES_CBC_CRC; 565 break; 566 case 'M': /* master key name in DB */ 567 mkey_name = optarg; 568 break; 569 case 'n': 570 nofork++; /* don't detach from terminal */ 571 break; 572 case 'k': /* enctype for master key */ 573 if (krb5_string_to_enctype(optarg, &menctype)) 574 com_err(argv[0], 0, 575 gettext("invalid enctype %s"), optarg); 576 break; 577 case 'R': 578 rcname = optarg; 579 break; 580 case 'p': 581 if (default_udp_ports) 582 free(default_udp_ports); 583 default_udp_ports = strdup(optarg); 584 585 if (default_tcp_ports) 586 free(default_tcp_ports); 587 default_tcp_ports = strdup(optarg); 588 589 break; 590 case '4': 591 #ifdef KRB5_KRB4_COMPAT 592 if (v4mode) 593 free(v4mode); 594 v4mode = strdup(optarg); 595 #endif 596 break; 597 case 'X': 598 #ifdef KRB5_KRB4_COMPAT 599 enable_v4_crossrealm(argv[0]); 600 #endif 601 break; 602 case '?': 603 default: 604 usage(argv[0]); 605 exit(1); 606 } 607 } 608 609 #ifdef KRB5_KRB4_COMPAT 610 /* 611 * Setup the v4 mode 612 */ 613 process_v4_mode(argv[0], v4mode); 614 free(v4mode); 615 #endif 616 617 /* 618 * Check to see if we processed any realms. 619 */ 620 if (kdc_numrealms == 0) { 621 /* no realm specified, use default realm */ 622 if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { 623 com_err(argv[0], retval, 624 gettext("while attempting to retrieve default realm")); 625 fprintf (stderr, "%s: %s, %s", argv[0], error_message (retval), 626 gettext("attempting to retrieve default realm\n")); 627 exit(1); 628 } 629 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { 630 if ((retval = init_realm(argv[0], rdatap, lrealm, 631 mkey_name, menctype, default_udp_ports, 632 default_tcp_ports, manual, db_args))) { 633 fprintf(stderr, 634 gettext("%s: cannot initialize realm %s\n"), 635 argv[0], lrealm); 636 exit(1); 637 } 638 kdc_realmlist[0] = rdatap; 639 kdc_numrealms++; 640 } 641 } 642 643 #ifdef USE_RCACHE 644 /* 645 * Now handle the replay cache. 646 */ 647 if ((retval = kdc_initialize_rcache(kcontext, rcname))) { 648 com_err(argv[0], retval, gettext("while initializing KDC replay cache '%s'"), 649 rcname); 650 exit(1); 651 } 652 #endif 653 654 /* Ensure that this is set for our first request. */ 655 kdc_active_realm = kdc_realmlist[0]; 656 if (default_udp_ports) 657 free(default_udp_ports); 658 if (default_tcp_ports) 659 free(default_tcp_ports); 660 if (db_args) 661 free(db_args); 662 if (db_name) 663 free(db_name); 664 665 return; 666 } 667 668 void 669 finish_realms(char *prog) 670 { 671 int i; 672 673 for (i = 0; i < kdc_numrealms; i++) { 674 finish_realm(kdc_realmlist[i]); 675 kdc_realmlist[i] = 0; 676 } 677 } 678 679 /* 680 outline: 681 682 process args & setup 683 684 initialize database access (fetch master key, open DB) 685 686 initialize network 687 688 loop: 689 listen for packet 690 691 determine packet type, dispatch to handling routine 692 (AS or TGS (or V4?)) 693 694 reflect response 695 696 exit on signal 697 698 clean up secrets, close db 699 700 shut down network 701 702 exit 703 */ 704 705 int main(int argc, char **argv) 706 { 707 krb5_error_code retval; 708 krb5_context kcontext; 709 int errout = 0; 710 711 (void) setlocale(LC_ALL, ""); 712 713 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 714 #define TEXT_DOMAIN "KRB5KDC_TEST" /* Use this only if it weren't */ 715 #endif 716 717 (void) textdomain(TEXT_DOMAIN); 718 719 if (strrchr(argv[0], '/')) 720 argv[0] = strrchr(argv[0], '/')+1; 721 722 if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * 723 KRB5_KDC_MAX_REALMS))) { 724 fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]); 725 exit(1); 726 } 727 memset((char *) kdc_realmlist, 0, 728 (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); 729 730 /* 731 * A note about Kerberos contexts: This context, "kcontext", is used 732 * for the KDC operations, i.e. setup, network connection and error 733 * reporting. The per-realm operations use the "realm_context" 734 * associated with each realm. 735 */ 736 retval = krb5int_init_context_kdc(&kcontext); 737 if (retval) { 738 com_err(argv[0], retval, gettext("while initializing krb5")); 739 exit(1); 740 } 741 krb5_klog_init(kcontext, "kdc", argv[0], 1); 742 /* initialize_kdc5_error_table(); SUNWresync121 XXX */ 743 744 /* 745 * Scan through the argument list 746 */ 747 initialize_realms(kcontext, argc, argv); 748 749 setup_signal_handlers(); 750 751 retval = setup_sam(); 752 if (retval) { 753 com_err(argv[0], retval, gettext("while initializing SAM")); 754 finish_realms(argv[0]); 755 return 1; 756 } 757 758 if ((retval = setup_network(argv[0]))) { 759 com_err(argv[0], retval, gettext("while initializing network")); 760 finish_realms(argv[0]); 761 return 1; 762 } 763 if (!nofork && daemon(0, 0)) { 764 com_err(argv[0], errno, gettext("while detaching from tty")); 765 finish_realms(argv[0]); 766 return 1; 767 } 768 if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) { 769 com_err(argv[0], retval, gettext("while logging message")); 770 errout++; 771 }; 772 773 if ((retval = listen_and_process(argv[0]))) { 774 com_err(argv[0], retval, gettext("while processing network requests")); 775 errout++; 776 } 777 if ((retval = closedown_network(argv[0]))) { 778 com_err(argv[0], retval, gettext("while shutting down network")); 779 errout++; 780 } 781 krb5_klog_syslog(LOG_INFO, "shutting down"); 782 krb5_klog_close(kdc_context); 783 finish_realms(argv[0]); 784 if (kdc_realmlist) 785 free(kdc_realmlist); 786 #ifdef USE_RCACHE 787 (void) krb5_rc_close(kcontext, kdc_rcache); 788 #endif 789 #ifndef NOCACHE 790 kdc_free_lookaside(kcontext); 791 #endif 792 krb5_free_context(kcontext); 793 return errout; 794 } 795 796 797 798 799