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 *
find_realm_data(char * rname,krb5_ui_4 rsize)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
setup_server_realm(krb5_principal sprinc)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
finish_realm(kdc_realm_t * rdp)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
init_realm(krb5_context kcontext,char * progname,kdc_realm_t * rdp,char * realm,char * def_mpname,krb5_enctype def_enctype,char * def_udp_ports,char * def_tcp_ports,krb5_boolean def_manual,char ** db_args)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