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 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