xref: /titanic_52/usr/src/cmd/krb5/krb5kdc/main.c (revision 505d05c73a6e56769f263d4803b22eddd168ee24)
17c478bd9Sstevel@tonic-gate /*
2*505d05c7Sgtb  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate  * kdc/main.c
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * Copyright 1990,2001 by the Massachusetts Institute of Technology.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Main procedure body for the KDC server process.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <syslog.h>
387c478bd9Sstevel@tonic-gate #include <signal.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <netdb.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include "k5-int.h"
437c478bd9Sstevel@tonic-gate #include "com_err.h"
447c478bd9Sstevel@tonic-gate #include "adm.h"
457c478bd9Sstevel@tonic-gate #include "adm_proto.h"
467c478bd9Sstevel@tonic-gate #include "kdc_util.h"
477c478bd9Sstevel@tonic-gate #include "extern.h"
487c478bd9Sstevel@tonic-gate #include "kdc5_err.h"
497c478bd9Sstevel@tonic-gate #include <libintl.h>
507c478bd9Sstevel@tonic-gate #include <locale.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #ifdef HAVE_NETINET_IN_H
537c478bd9Sstevel@tonic-gate #include <netinet/in.h>
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate 
56*505d05c7Sgtb kdc_realm_t *find_realm_data (char *, krb5_ui_4);
577c478bd9Sstevel@tonic-gate 
58*505d05c7Sgtb void usage (char *);
597c478bd9Sstevel@tonic-gate 
60*505d05c7Sgtb krb5_sigtype request_exit (int);
61*505d05c7Sgtb krb5_sigtype request_hup  (int);
627c478bd9Sstevel@tonic-gate 
63*505d05c7Sgtb void setup_signal_handlers (void);
647c478bd9Sstevel@tonic-gate 
65*505d05c7Sgtb krb5_error_code setup_sam (void);
667c478bd9Sstevel@tonic-gate 
67*505d05c7Sgtb void initialize_realms (krb5_context, int, char **);
687c478bd9Sstevel@tonic-gate 
69*505d05c7Sgtb void finish_realms (char *);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static int nofork = 0;
727c478bd9Sstevel@tonic-gate static int rkey_init_done = 0;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /* Solaris Kerberos: global here that other functions access */
757c478bd9Sstevel@tonic-gate int max_tcp_data_connections;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGNALS
787c478bd9Sstevel@tonic-gate static struct sigaction s_action;
797c478bd9Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #define	KRB5_KDC_MAX_REALMS	32
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * Find the realm entry for a given realm.
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate kdc_realm_t *
877c478bd9Sstevel@tonic-gate find_realm_data(rname, rsize)
887c478bd9Sstevel@tonic-gate     char 	*rname;
897c478bd9Sstevel@tonic-gate     krb5_ui_4	rsize;
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate     int i;
927c478bd9Sstevel@tonic-gate     for (i=0; i<kdc_numrealms; i++) {
937c478bd9Sstevel@tonic-gate 	if ((rsize == strlen(kdc_realmlist[i]->realm_name)) &&
947c478bd9Sstevel@tonic-gate 	    !strncmp(rname, kdc_realmlist[i]->realm_name, rsize))
957c478bd9Sstevel@tonic-gate 	    return(kdc_realmlist[i]);
967c478bd9Sstevel@tonic-gate     }
977c478bd9Sstevel@tonic-gate     return((kdc_realm_t *) NULL);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate krb5_error_code
1017c478bd9Sstevel@tonic-gate setup_server_realm(sprinc)
1027c478bd9Sstevel@tonic-gate     krb5_principal	sprinc;
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
1057c478bd9Sstevel@tonic-gate     kdc_realm_t		*newrealm;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate     kret = 0;
1087c478bd9Sstevel@tonic-gate     if (kdc_numrealms > 1) {
1097c478bd9Sstevel@tonic-gate 	if (!(newrealm = find_realm_data(sprinc->realm.data,
1107c478bd9Sstevel@tonic-gate 					 (krb5_ui_4) sprinc->realm.length)))
1117c478bd9Sstevel@tonic-gate 	    kret = ENOENT;
1127c478bd9Sstevel@tonic-gate 	else
1137c478bd9Sstevel@tonic-gate 	    kdc_active_realm = newrealm;
1147c478bd9Sstevel@tonic-gate     }
1157c478bd9Sstevel@tonic-gate     else
1167c478bd9Sstevel@tonic-gate 	kdc_active_realm = kdc_realmlist[0];
1177c478bd9Sstevel@tonic-gate     return(kret);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate static void
1217c478bd9Sstevel@tonic-gate finish_realm(rdp)
1227c478bd9Sstevel@tonic-gate     kdc_realm_t *rdp;
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate     if (rdp->realm_dbname)
1257c478bd9Sstevel@tonic-gate 	free(rdp->realm_dbname);
1267c478bd9Sstevel@tonic-gate     if (rdp->realm_mpname)
1277c478bd9Sstevel@tonic-gate 	free(rdp->realm_mpname);
1287c478bd9Sstevel@tonic-gate     if (rdp->realm_stash)
1297c478bd9Sstevel@tonic-gate 	free(rdp->realm_stash);
1307c478bd9Sstevel@tonic-gate     if (rdp->realm_ports)
1317c478bd9Sstevel@tonic-gate 	free(rdp->realm_ports);
1327c478bd9Sstevel@tonic-gate     if (rdp->realm_tcp_ports)
1337c478bd9Sstevel@tonic-gate 	free(rdp->realm_tcp_ports);
1347c478bd9Sstevel@tonic-gate     if (rdp->realm_kstypes)
1357c478bd9Sstevel@tonic-gate 	free(rdp->realm_kstypes);
1367c478bd9Sstevel@tonic-gate     if (rdp->realm_keytab)
1377c478bd9Sstevel@tonic-gate 	krb5_kt_close(rdp->realm_context, rdp->realm_keytab);
1387c478bd9Sstevel@tonic-gate     if (rdp->realm_context) {
1397c478bd9Sstevel@tonic-gate 	if (rdp->realm_mprinc)
1407c478bd9Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
1417c478bd9Sstevel@tonic-gate 	if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
1427c478bd9Sstevel@tonic-gate 	    memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
1437c478bd9Sstevel@tonic-gate 	    free(rdp->realm_mkey.contents);
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	if (rdp->realm_tgskey.length && rdp->realm_tgskey.contents) {
1467c478bd9Sstevel@tonic-gate 	    memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length);
1477c478bd9Sstevel@tonic-gate 	    free(rdp->realm_tgskey.contents);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	krb5_db_fini(rdp->realm_context);
1507c478bd9Sstevel@tonic-gate 	if (rdp->realm_tgsprinc)
1517c478bd9Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
1527c478bd9Sstevel@tonic-gate 	krb5_free_context(rdp->realm_context);
1537c478bd9Sstevel@tonic-gate     }
1547c478bd9Sstevel@tonic-gate     free(rdp);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * Initialize a realm control structure from the alternate profile or from
1597c478bd9Sstevel@tonic-gate  * the specified defaults.
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  * After we're complete here, the essence of the realm is embodied in the
1627c478bd9Sstevel@tonic-gate  * realm data and we should be all set to begin operation for that realm.
1637c478bd9Sstevel@tonic-gate  */
1647c478bd9Sstevel@tonic-gate static krb5_error_code
1657c478bd9Sstevel@tonic-gate init_realm(progname, rdp, realm, def_dbname, def_mpname,
1667c478bd9Sstevel@tonic-gate 		 def_enctype, def_udp_ports, def_tcp_ports, def_manual)
1677c478bd9Sstevel@tonic-gate     char		*progname;
1687c478bd9Sstevel@tonic-gate     kdc_realm_t		*rdp;
1697c478bd9Sstevel@tonic-gate     char		*realm;
1707c478bd9Sstevel@tonic-gate     char		*def_dbname;
1717c478bd9Sstevel@tonic-gate     char		*def_mpname;
1727c478bd9Sstevel@tonic-gate     krb5_enctype	def_enctype;
1737c478bd9Sstevel@tonic-gate     char		*def_udp_ports;
1747c478bd9Sstevel@tonic-gate     char		*def_tcp_ports;
1757c478bd9Sstevel@tonic-gate     krb5_boolean	def_manual;
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
1787c478bd9Sstevel@tonic-gate     krb5_boolean	manual;
1797c478bd9Sstevel@tonic-gate     krb5_db_entry	db_entry;
1807c478bd9Sstevel@tonic-gate     int			num2get;
1817c478bd9Sstevel@tonic-gate     krb5_boolean	more;
1827c478bd9Sstevel@tonic-gate     krb5_boolean	db_inited;
1837c478bd9Sstevel@tonic-gate     krb5_realm_params	*rparams;
1847c478bd9Sstevel@tonic-gate     krb5_key_data	*kdata;
1857c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple	*kslist;
1867c478bd9Sstevel@tonic-gate     krb5_int32		nkslist;
1877c478bd9Sstevel@tonic-gate     int			i;
1887c478bd9Sstevel@tonic-gate     krb5_deltat		now, krb5_kdb_max_time;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate     db_inited = 0;
1917c478bd9Sstevel@tonic-gate     memset((char *) rdp, 0, sizeof(kdc_realm_t));
1927c478bd9Sstevel@tonic-gate     if (!realm) {
1937c478bd9Sstevel@tonic-gate 	kret = EINVAL;
1947c478bd9Sstevel@tonic-gate 	goto whoops;
1957c478bd9Sstevel@tonic-gate     }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate     rdp->realm_name = realm;
1987c478bd9Sstevel@tonic-gate     kret = krb5_init_context(&rdp->realm_context);
1997c478bd9Sstevel@tonic-gate     if (kret) {
2007c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting context for realm %s"),
2017c478bd9Sstevel@tonic-gate 		realm);
2027c478bd9Sstevel@tonic-gate 	goto whoops;
2037c478bd9Sstevel@tonic-gate     }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate     kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name,
2067c478bd9Sstevel@tonic-gate 				  (char *) NULL, (char *) NULL, &rparams);
2077c478bd9Sstevel@tonic-gate     if (kret) {
2087c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while reading realm parameters"));
2097c478bd9Sstevel@tonic-gate 	goto whoops;
2107c478bd9Sstevel@tonic-gate     }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate     /* Handle profile file name */
2137c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_profile)
2147c478bd9Sstevel@tonic-gate 	rdp->realm_profile = strdup(rparams->realm_profile);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate     /* Handle database name */
2177c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_dbname)
2187c478bd9Sstevel@tonic-gate 	rdp->realm_dbname = strdup(rparams->realm_dbname);
2197c478bd9Sstevel@tonic-gate     else
2207c478bd9Sstevel@tonic-gate 	rdp->realm_dbname = (def_dbname) ? strdup(def_dbname) :
2217c478bd9Sstevel@tonic-gate 	    strdup(DEFAULT_KDB_FILE);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate     /* Handle master key name */
2247c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_mkey_name)
2257c478bd9Sstevel@tonic-gate 	rdp->realm_mpname = strdup(rparams->realm_mkey_name);
2267c478bd9Sstevel@tonic-gate     else
2277c478bd9Sstevel@tonic-gate 	rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) :
2287c478bd9Sstevel@tonic-gate 	    strdup(KRB5_KDB_M_NAME);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate     /* Handle KDC ports */
2317c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_ports)
2327c478bd9Sstevel@tonic-gate 	rdp->realm_ports = strdup(rparams->realm_kdc_ports);
2337c478bd9Sstevel@tonic-gate     else
2347c478bd9Sstevel@tonic-gate 	rdp->realm_ports = strdup(def_udp_ports);
2357c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_tcp_ports)
2367c478bd9Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports);
2377c478bd9Sstevel@tonic-gate     else
2387c478bd9Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(def_tcp_ports);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate     /* Handle stash file */
2417c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_stash_file) {
2427c478bd9Sstevel@tonic-gate 	rdp->realm_stash = strdup(rparams->realm_stash_file);
2437c478bd9Sstevel@tonic-gate 	manual = FALSE;
2447c478bd9Sstevel@tonic-gate     } else
2457c478bd9Sstevel@tonic-gate 	manual = def_manual;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate     /* Handle master key type */
2487c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_enctype_valid)
2497c478bd9Sstevel@tonic-gate 	rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
2507c478bd9Sstevel@tonic-gate     else
2517c478bd9Sstevel@tonic-gate 	rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN;
2527c478bd9Sstevel@tonic-gate     if ((kret = krb5_timeofday(rdp->realm_context, &now))) {
2537c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting timeofday"));
2547c478bd9Sstevel@tonic-gate 	goto whoops;
2557c478bd9Sstevel@tonic-gate     }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate     /* Handle ticket maximum life */
2587c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_max_life_valid)
2597c478bd9Sstevel@tonic-gate    	rdp->realm_maxlife = rparams->realm_max_life;
2607c478bd9Sstevel@tonic-gate     else
2617c478bd9Sstevel@tonic-gate 	rdp->realm_maxlife = KRB5_KDB_EXPIRATION - now - 3600;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate     /* Handle ticket renewable maximum life */
2647c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_max_rlife_valid)
2657c478bd9Sstevel@tonic-gate    	rdp->realm_maxrlife = rparams->realm_max_rlife;
2667c478bd9Sstevel@tonic-gate     else
2677c478bd9Sstevel@tonic-gate    	rdp->realm_maxrlife = KRB5_KDB_EXPIRATION - now - 3600;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate     /* Handle key/salt list */
2707c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_num_keysalts) {
2717c478bd9Sstevel@tonic-gate 	rdp->realm_kstypes = rparams->realm_keysalts;
2727c478bd9Sstevel@tonic-gate 	rdp->realm_nkstypes = rparams->realm_num_keysalts;
2737c478bd9Sstevel@tonic-gate 	rparams->realm_keysalts = NULL;
2747c478bd9Sstevel@tonic-gate 	rparams->realm_num_keysalts = 0;
2757c478bd9Sstevel@tonic-gate 	kslist = (krb5_key_salt_tuple *) rdp->realm_kstypes;
2767c478bd9Sstevel@tonic-gate 	nkslist = rdp->realm_nkstypes;
2777c478bd9Sstevel@tonic-gate     } else {
2787c478bd9Sstevel@tonic-gate 	/*
2797c478bd9Sstevel@tonic-gate 	 * XXX  Initialize default key/salt list.
2807c478bd9Sstevel@tonic-gate 	 */
2817c478bd9Sstevel@tonic-gate 	if ((kslist = (krb5_key_salt_tuple *)
2827c478bd9Sstevel@tonic-gate 	     malloc(sizeof(krb5_key_salt_tuple)))) {
2837c478bd9Sstevel@tonic-gate 	    kslist->ks_enctype = ENCTYPE_DES_CBC_CRC;
2847c478bd9Sstevel@tonic-gate 	    kslist->ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
2857c478bd9Sstevel@tonic-gate 	    rdp->realm_kstypes = kslist;
2867c478bd9Sstevel@tonic-gate 	    rdp->realm_nkstypes = 1;
2877c478bd9Sstevel@tonic-gate 	    nkslist = 1;
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	else {
2907c478bd9Sstevel@tonic-gate 	    com_err(progname, ENOMEM,
2917c478bd9Sstevel@tonic-gate 		    gettext("while setting up key/salt list for realm %s"),
2927c478bd9Sstevel@tonic-gate 		    realm);
2937c478bd9Sstevel@tonic-gate 	    exit(1);
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate     }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate     if (rparams)
2987c478bd9Sstevel@tonic-gate 	krb5_free_realm_params(rdp->realm_context, rparams);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate     /*
3017c478bd9Sstevel@tonic-gate      * We've got our parameters, now go and setup our realm context.
3027c478bd9Sstevel@tonic-gate      */
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate     /* Set the default realm of this context */
3057c478bd9Sstevel@tonic-gate     if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) {
3067c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while setting default realm to %s"),
3077c478bd9Sstevel@tonic-gate 		realm);
3087c478bd9Sstevel@tonic-gate 	goto whoops;
3097c478bd9Sstevel@tonic-gate     }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate     /* Assemble and parse the master key name */
3127c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname,
3137c478bd9Sstevel@tonic-gate 					rdp->realm_name, (char **) NULL,
3147c478bd9Sstevel@tonic-gate 					&rdp->realm_mprinc))) {
3157c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3167c478bd9Sstevel@tonic-gate 		gettext("while setting up master key name %s for realm %s"),
3177c478bd9Sstevel@tonic-gate 		rdp->realm_mpname, realm);
3187c478bd9Sstevel@tonic-gate 	goto whoops;
3197c478bd9Sstevel@tonic-gate     }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate     /*
3227c478bd9Sstevel@tonic-gate      * Get the master key.
3237c478bd9Sstevel@tonic-gate      */
3247c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
3257c478bd9Sstevel@tonic-gate 				   rdp->realm_mkey.enctype, manual,
3267c478bd9Sstevel@tonic-gate 				   FALSE, rdp->realm_stash,
3277c478bd9Sstevel@tonic-gate 				   0, &rdp->realm_mkey))) {
3287c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3297c478bd9Sstevel@tonic-gate 		gettext("while fetching master key %s for realm %s"),
3307c478bd9Sstevel@tonic-gate 		rdp->realm_mpname, realm);
3317c478bd9Sstevel@tonic-gate 	goto whoops;
3327c478bd9Sstevel@tonic-gate     }
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate     /* Set and open the database. */
3357c478bd9Sstevel@tonic-gate     if (rdp->realm_dbname &&
3367c478bd9Sstevel@tonic-gate 	(kret = krb5_db_set_name(rdp->realm_context, rdp->realm_dbname))) {
3377c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3387c478bd9Sstevel@tonic-gate 		gettext("while setting database name to %s for realm %s"),
3397c478bd9Sstevel@tonic-gate 		rdp->realm_dbname, realm);
3407c478bd9Sstevel@tonic-gate 	goto whoops;
3417c478bd9Sstevel@tonic-gate     }
3427c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_init(rdp->realm_context))) {
3437c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3447c478bd9Sstevel@tonic-gate 		gettext("while initializing database "),
3457c478bd9Sstevel@tonic-gate 		gettext("for realm %s"), realm);
3467c478bd9Sstevel@tonic-gate 	goto whoops;
3477c478bd9Sstevel@tonic-gate     } else
3487c478bd9Sstevel@tonic-gate 	db_inited = 1;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate     /* Verify the master key */
3517c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_verify_master_key(rdp->realm_context,
3527c478bd9Sstevel@tonic-gate 					  rdp->realm_mprinc,
3537c478bd9Sstevel@tonic-gate 					  &rdp->realm_mkey))) {
3547c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3557c478bd9Sstevel@tonic-gate 		gettext("while verifying master key for realm %s"),
3567c478bd9Sstevel@tonic-gate 		realm);
3577c478bd9Sstevel@tonic-gate 	goto whoops;
3587c478bd9Sstevel@tonic-gate     }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     /* Fetch the master key and get its version number */
3617c478bd9Sstevel@tonic-gate     num2get = 1;
3627c478bd9Sstevel@tonic-gate     kret = krb5_db_get_principal(rdp->realm_context, rdp->realm_mprinc,
3637c478bd9Sstevel@tonic-gate 				 &db_entry, &num2get, &more);
3647c478bd9Sstevel@tonic-gate     if (!kret) {
3657c478bd9Sstevel@tonic-gate 	if (num2get != 1)
3667c478bd9Sstevel@tonic-gate 	    kret = KRB5_KDB_NOMASTERKEY;
3677c478bd9Sstevel@tonic-gate 	else {
3687c478bd9Sstevel@tonic-gate 	    if (more) {
3697c478bd9Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
3707c478bd9Sstevel@tonic-gate 				       &db_entry,
3717c478bd9Sstevel@tonic-gate 				       num2get);
3727c478bd9Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
3737c478bd9Sstevel@tonic-gate 	    }
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate     }
3767c478bd9Sstevel@tonic-gate     if (kret) {
3777c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3787c478bd9Sstevel@tonic-gate 		gettext("while fetching master entry for realm %s"),
3797c478bd9Sstevel@tonic-gate 		realm);
3807c478bd9Sstevel@tonic-gate 	goto whoops;
3817c478bd9Sstevel@tonic-gate     }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate     /*
3847c478bd9Sstevel@tonic-gate      * Get the most recent master key.  Search the key list in
3857c478bd9Sstevel@tonic-gate      * the order specified by the key/salt list.
3867c478bd9Sstevel@tonic-gate      */
3877c478bd9Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
3887c478bd9Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
3897c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
3907c478bd9Sstevel@tonic-gate 					   &db_entry,
3917c478bd9Sstevel@tonic-gate 					   kslist[i].ks_enctype,
3927c478bd9Sstevel@tonic-gate 					   -1,
3937c478bd9Sstevel@tonic-gate 					   -1,
3947c478bd9Sstevel@tonic-gate 					   &kdata)))
3957c478bd9Sstevel@tonic-gate 	    break;
3967c478bd9Sstevel@tonic-gate     }
3977c478bd9Sstevel@tonic-gate     if (!kdata) {
3987c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
3997c478bd9Sstevel@tonic-gate 		gettext("while finding master key for realm %s"),
4007c478bd9Sstevel@tonic-gate 		realm);
4017c478bd9Sstevel@tonic-gate 	goto whoops;
4027c478bd9Sstevel@tonic-gate     }
4037c478bd9Sstevel@tonic-gate     rdp->realm_mkvno = kdata->key_data_kvno;
4047c478bd9Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context, &db_entry, num2get);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) {
4077c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4087c478bd9Sstevel@tonic-gate 		gettext("while processing master key for realm %s"),
4097c478bd9Sstevel@tonic-gate 		realm);
4107c478bd9Sstevel@tonic-gate 	goto whoops;
4117c478bd9Sstevel@tonic-gate     }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate     /* Set up the keytab */
4147c478bd9Sstevel@tonic-gate     if ((kret = krb5_ktkdb_resolve(rdp->realm_context,
4157c478bd9Sstevel@tonic-gate 				   NULL,
4167c478bd9Sstevel@tonic-gate 				   &rdp->realm_keytab))) {
4177c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4187c478bd9Sstevel@tonic-gate 		gettext("while resolving kdb keytab for realm %s"),
4197c478bd9Sstevel@tonic-gate 		realm);
4207c478bd9Sstevel@tonic-gate 	goto whoops;
4217c478bd9Sstevel@tonic-gate     }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate     /* Preformat the TGS name */
4247c478bd9Sstevel@tonic-gate     if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc,
4257c478bd9Sstevel@tonic-gate 				     strlen(realm), realm, KRB5_TGS_NAME,
4267c478bd9Sstevel@tonic-gate 				     realm, (char *) NULL))) {
4277c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4287c478bd9Sstevel@tonic-gate 		gettext("while building TGS name for realm %s"),
4297c478bd9Sstevel@tonic-gate 		realm);
4307c478bd9Sstevel@tonic-gate 	goto whoops;
4317c478bd9Sstevel@tonic-gate     }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate     /* Get the TGS database entry */
4347c478bd9Sstevel@tonic-gate     num2get = 1;
4357c478bd9Sstevel@tonic-gate     if (!(kret = krb5_db_get_principal(rdp->realm_context,
4367c478bd9Sstevel@tonic-gate 				       rdp->realm_tgsprinc,
4377c478bd9Sstevel@tonic-gate 				       &db_entry,
4387c478bd9Sstevel@tonic-gate 				       &num2get,
4397c478bd9Sstevel@tonic-gate 				       &more))) {
4407c478bd9Sstevel@tonic-gate 	if (num2get != 1)
4417c478bd9Sstevel@tonic-gate 	    kret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
4427c478bd9Sstevel@tonic-gate 	else {
4437c478bd9Sstevel@tonic-gate 	    if (more) {
4447c478bd9Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
4457c478bd9Sstevel@tonic-gate 				       &db_entry,
4467c478bd9Sstevel@tonic-gate 				       num2get);
4477c478bd9Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
4487c478bd9Sstevel@tonic-gate 	    }
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate     }
4517c478bd9Sstevel@tonic-gate     if (kret) {
4527c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4537c478bd9Sstevel@tonic-gate 		gettext("while fetching TGS entry for realm %s"),
4547c478bd9Sstevel@tonic-gate 		realm);
4557c478bd9Sstevel@tonic-gate 	goto whoops;
4567c478bd9Sstevel@tonic-gate     }
4577c478bd9Sstevel@tonic-gate     /*
4587c478bd9Sstevel@tonic-gate      * Get the most recent TGS key.  Search the key list in
4597c478bd9Sstevel@tonic-gate      * the order specified by the key/salt list.
4607c478bd9Sstevel@tonic-gate      */
4617c478bd9Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
4627c478bd9Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
4637c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
4647c478bd9Sstevel@tonic-gate 					   &db_entry,
4657c478bd9Sstevel@tonic-gate 					   kslist[i].ks_enctype,
4667c478bd9Sstevel@tonic-gate 					   -1,
4677c478bd9Sstevel@tonic-gate 					   -1,
4687c478bd9Sstevel@tonic-gate 					   &kdata)))
4697c478bd9Sstevel@tonic-gate 	    break;
4707c478bd9Sstevel@tonic-gate     }
4717c478bd9Sstevel@tonic-gate     if (!kdata) {
4727c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4737c478bd9Sstevel@tonic-gate 		gettext("while finding TGS key for realm %s"),
4747c478bd9Sstevel@tonic-gate 		realm);
4757c478bd9Sstevel@tonic-gate 	goto whoops;
4767c478bd9Sstevel@tonic-gate     }
4777c478bd9Sstevel@tonic-gate     if (!(kret = krb5_dbekd_decrypt_key_data(rdp->realm_context,
4787c478bd9Sstevel@tonic-gate 					     &rdp->realm_mkey,
4797c478bd9Sstevel@tonic-gate 					     kdata,
4807c478bd9Sstevel@tonic-gate 					     &rdp->realm_tgskey, NULL))){
4817c478bd9Sstevel@tonic-gate 	rdp->realm_tgskvno = kdata->key_data_kvno;
4827c478bd9Sstevel@tonic-gate     }
4837c478bd9Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context,
4847c478bd9Sstevel@tonic-gate 			   &db_entry,
4857c478bd9Sstevel@tonic-gate 			   num2get);
4867c478bd9Sstevel@tonic-gate     if (kret) {
4877c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
4887c478bd9Sstevel@tonic-gate 		gettext("while decrypting TGS key for realm %s"),
4897c478bd9Sstevel@tonic-gate 		realm);
4907c478bd9Sstevel@tonic-gate 	goto whoops;
4917c478bd9Sstevel@tonic-gate     }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate     if (!rkey_init_done) {
4947c478bd9Sstevel@tonic-gate 	krb5_timestamp now;
4957c478bd9Sstevel@tonic-gate 	krb5_data seed;
4967c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
4977c478bd9Sstevel@tonic-gate 	krb5_keyblock temp_key;
4987c478bd9Sstevel@tonic-gate #endif
4997c478bd9Sstevel@tonic-gate 	/*
5007c478bd9Sstevel@tonic-gate 	 * If all that worked, then initialize the random key
5017c478bd9Sstevel@tonic-gate 	 * generators.
5027c478bd9Sstevel@tonic-gate 	 */
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if ((kret = krb5_timeofday(rdp->realm_context, &now)))
5057c478bd9Sstevel@tonic-gate 	    goto whoops;
5067c478bd9Sstevel@tonic-gate 	seed.length = sizeof(now);
5077c478bd9Sstevel@tonic-gate 	seed.data = (char *) &now;
5087c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
5097c478bd9Sstevel@tonic-gate 	    goto whoops;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	seed.length = rdp->realm_mkey.length;
5127c478bd9Sstevel@tonic-gate 	seed.data = (char *)rdp->realm_mkey.contents;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
5157c478bd9Sstevel@tonic-gate 	    goto whoops;
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
5187c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_make_random_key(rdp->realm_context,
5197c478bd9Sstevel@tonic-gate 					   ENCTYPE_DES_CBC_CRC, &temp_key))) {
5207c478bd9Sstevel@tonic-gate 	    com_err(progname, kret,
5217c478bd9Sstevel@tonic-gate 		    "while initializing V4 random key generator");
5227c478bd9Sstevel@tonic-gate 	    goto whoops;
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	(void) des_init_random_number_generator(temp_key.contents);
5267c478bd9Sstevel@tonic-gate 	krb5_free_keyblock_contents(rdp->realm_context, &temp_key);
5277c478bd9Sstevel@tonic-gate #endif
5287c478bd9Sstevel@tonic-gate 	rkey_init_done = 1;
5297c478bd9Sstevel@tonic-gate     }
5307c478bd9Sstevel@tonic-gate  whoops:
5317c478bd9Sstevel@tonic-gate     /*
5327c478bd9Sstevel@tonic-gate      * If we choked, then clean up any dirt we may have dropped on the floor.
5337c478bd9Sstevel@tonic-gate      */
5347c478bd9Sstevel@tonic-gate     if (kret) {
5357c478bd9Sstevel@tonic-gate 	finish_realm(rdp);
5367c478bd9Sstevel@tonic-gate     }
5377c478bd9Sstevel@tonic-gate     return(kret);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate krb5_sigtype
5417c478bd9Sstevel@tonic-gate request_exit(signo)
5427c478bd9Sstevel@tonic-gate     int signo;
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate     signal_requests_exit = 1;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
5477c478bd9Sstevel@tonic-gate     return;
5487c478bd9Sstevel@tonic-gate #else
5497c478bd9Sstevel@tonic-gate     return(0);
5507c478bd9Sstevel@tonic-gate #endif
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate krb5_sigtype
5547c478bd9Sstevel@tonic-gate request_hup(signo)
5557c478bd9Sstevel@tonic-gate     int signo;
5567c478bd9Sstevel@tonic-gate {
5577c478bd9Sstevel@tonic-gate     signal_requests_hup = 1;
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
5607c478bd9Sstevel@tonic-gate     return;
5617c478bd9Sstevel@tonic-gate #else
5627c478bd9Sstevel@tonic-gate     return(0);
5637c478bd9Sstevel@tonic-gate #endif
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate void
5677c478bd9Sstevel@tonic-gate setup_signal_handlers()
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGNALS
5707c478bd9Sstevel@tonic-gate     (void) sigemptyset(&s_action.sa_mask);
5717c478bd9Sstevel@tonic-gate     s_action.sa_flags = 0;
5727c478bd9Sstevel@tonic-gate     s_action.sa_handler = request_exit;
5737c478bd9Sstevel@tonic-gate     (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
5747c478bd9Sstevel@tonic-gate     (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
5757c478bd9Sstevel@tonic-gate     s_action.sa_handler = request_hup;
5767c478bd9Sstevel@tonic-gate     (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL);
5777c478bd9Sstevel@tonic-gate #else  /* POSIX_SIGNALS */
5787c478bd9Sstevel@tonic-gate     signal(SIGINT, request_exit);
5797c478bd9Sstevel@tonic-gate     signal(SIGTERM, request_exit);
5807c478bd9Sstevel@tonic-gate     signal(SIGHUP, request_hup);
5817c478bd9Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate     return;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate krb5_error_code
5877c478bd9Sstevel@tonic-gate setup_sam()
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate     return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key);
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate void
5937c478bd9Sstevel@tonic-gate usage(name)
5947c478bd9Sstevel@tonic-gate char *name;
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate     fprintf(stderr, gettext("usage: %s [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-n]\n"), name);
5977c478bd9Sstevel@tonic-gate     return;
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate void
6017c478bd9Sstevel@tonic-gate initialize_realms(kcontext, argc, argv)
6027c478bd9Sstevel@tonic-gate     krb5_context 	kcontext;
6037c478bd9Sstevel@tonic-gate     int			argc;
6047c478bd9Sstevel@tonic-gate     char		**argv;
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate     int 		c;
6077c478bd9Sstevel@tonic-gate     char		*db_name = (char *) NULL;
6087c478bd9Sstevel@tonic-gate     char		*mkey_name = (char *) NULL;
6097c478bd9Sstevel@tonic-gate     char		*rcname = KDCRCACHE;
6107c478bd9Sstevel@tonic-gate     char		*lrealm;
6117c478bd9Sstevel@tonic-gate     krb5_error_code	retval;
6127c478bd9Sstevel@tonic-gate     krb5_enctype	menctype = ENCTYPE_UNKNOWN;
6137c478bd9Sstevel@tonic-gate     kdc_realm_t		*rdatap;
6147c478bd9Sstevel@tonic-gate     krb5_boolean	manual = FALSE;
6157c478bd9Sstevel@tonic-gate     char		*default_udp_ports = 0;
6167c478bd9Sstevel@tonic-gate     char		*default_tcp_ports = 0;
6177c478bd9Sstevel@tonic-gate     krb5_pointer	aprof;
6187c478bd9Sstevel@tonic-gate     const char		*hierarchy[3];
6197c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
6207c478bd9Sstevel@tonic-gate     char                *v4mode = 0;
6217c478bd9Sstevel@tonic-gate #endif
6227c478bd9Sstevel@tonic-gate     extern char *optarg;
6237c478bd9Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
6247c478bd9Sstevel@tonic-gate     extern struct krb5_keytypes krb5_enctypes_list[];
6257c478bd9Sstevel@tonic-gate     extern int krb5_enctypes_length;
6267c478bd9Sstevel@tonic-gate #endif
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate     if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) {
6297c478bd9Sstevel@tonic-gate 	hierarchy[0] = "kdcdefaults";
6307c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_ports";
6317c478bd9Sstevel@tonic-gate 	hierarchy[2] = (char *) NULL;
6327c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports))
6337c478bd9Sstevel@tonic-gate 	    default_udp_ports = 0;
6347c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_tcp_ports";
6357c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports))
6367c478bd9Sstevel@tonic-gate 	    default_tcp_ports = 0;
6377c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_max_tcp_connections";
6387c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_int32(aprof, hierarchy, TRUE,
6397c478bd9Sstevel@tonic-gate 		&max_tcp_data_connections)) {
6407c478bd9Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
6417c478bd9Sstevel@tonic-gate 	} else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) {
6427c478bd9Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
6457c478bd9Sstevel@tonic-gate 	hierarchy[1] = "v4_mode";
6467c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
6477c478bd9Sstevel@tonic-gate 	    v4mode = 0;
6487c478bd9Sstevel@tonic-gate #endif
6497c478bd9Sstevel@tonic-gate 	/* aprof_init can return 0 with aprof == NULL */
6507c478bd9Sstevel@tonic-gate 	if (aprof)
6517c478bd9Sstevel@tonic-gate 	     krb5_aprof_finish(aprof);
6527c478bd9Sstevel@tonic-gate     }
6537c478bd9Sstevel@tonic-gate     if (default_udp_ports == 0)
6547c478bd9Sstevel@tonic-gate 	default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST);
6557c478bd9Sstevel@tonic-gate     if (default_tcp_ports == 0)
6567c478bd9Sstevel@tonic-gate 	default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST);
6577c478bd9Sstevel@tonic-gate     /*
6587c478bd9Sstevel@tonic-gate      * Loop through the option list.  Each time we encounter a realm name,
6597c478bd9Sstevel@tonic-gate      * use the previously scanned options to fill in for defaults.
6607c478bd9Sstevel@tonic-gate      */
6617c478bd9Sstevel@tonic-gate     while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:n")) != -1) { /* SUNW */
6627c478bd9Sstevel@tonic-gate 	switch(c) {
6637c478bd9Sstevel@tonic-gate 	case 'r':			/* realm name for db */
6647c478bd9Sstevel@tonic-gate 	    if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
6657c478bd9Sstevel@tonic-gate 		if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
6667c478bd9Sstevel@tonic-gate 		    if ((retval = init_realm(argv[0], rdatap, optarg, db_name,
6677c478bd9Sstevel@tonic-gate 					     mkey_name, menctype,
6687c478bd9Sstevel@tonic-gate 					     default_udp_ports,
6697c478bd9Sstevel@tonic-gate 					     default_tcp_ports, manual))) {
6707c478bd9Sstevel@tonic-gate 			fprintf(stderr,gettext("%s: cannot initialize realm %s\n"),
6717c478bd9Sstevel@tonic-gate 				argv[0], optarg);
6727c478bd9Sstevel@tonic-gate 			exit(1);
6737c478bd9Sstevel@tonic-gate 		    }
6747c478bd9Sstevel@tonic-gate 		    kdc_realmlist[kdc_numrealms] = rdatap;
6757c478bd9Sstevel@tonic-gate 		    kdc_numrealms++;
6767c478bd9Sstevel@tonic-gate 		}
6777c478bd9Sstevel@tonic-gate 	    }
6787c478bd9Sstevel@tonic-gate 	    break;
6797c478bd9Sstevel@tonic-gate 	case 'd':			/* pathname for db */
6807c478bd9Sstevel@tonic-gate 	    db_name = optarg;
6817c478bd9Sstevel@tonic-gate 	    break;
6827c478bd9Sstevel@tonic-gate 	case 'm':			/* manual type-in of master key */
6837c478bd9Sstevel@tonic-gate 	    manual = TRUE;
6847c478bd9Sstevel@tonic-gate 	    if (menctype == ENCTYPE_UNKNOWN)
6857c478bd9Sstevel@tonic-gate 		menctype = ENCTYPE_DES_CBC_CRC;
6867c478bd9Sstevel@tonic-gate 	    break;
6877c478bd9Sstevel@tonic-gate 	case 'M':			/* master key name in DB */
6887c478bd9Sstevel@tonic-gate 	    mkey_name = optarg;
6897c478bd9Sstevel@tonic-gate 	    break;
6907c478bd9Sstevel@tonic-gate 	case 'n':
6917c478bd9Sstevel@tonic-gate 	    nofork++;			/* don't detach from terminal */
6927c478bd9Sstevel@tonic-gate 	    break;
6937c478bd9Sstevel@tonic-gate 	case 'k':			/* enctype for master key */
6947c478bd9Sstevel@tonic-gate 	    if (krb5_string_to_enctype(optarg, &menctype))
6957c478bd9Sstevel@tonic-gate 		com_err(argv[0], 0,
6967c478bd9Sstevel@tonic-gate 		gettext("invalid enctype %s"), optarg);
6977c478bd9Sstevel@tonic-gate 	    break;
6987c478bd9Sstevel@tonic-gate 	case 'R':
6997c478bd9Sstevel@tonic-gate 	    rcname = optarg;
7007c478bd9Sstevel@tonic-gate 	    break;
7017c478bd9Sstevel@tonic-gate 	case 'p':
7027c478bd9Sstevel@tonic-gate 	    if (default_udp_ports)
7037c478bd9Sstevel@tonic-gate 		free(default_udp_ports);
7047c478bd9Sstevel@tonic-gate 	    default_udp_ports = strdup(optarg);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	    if (default_tcp_ports)
7077c478bd9Sstevel@tonic-gate 		free(default_tcp_ports);
7087c478bd9Sstevel@tonic-gate 	    default_tcp_ports = strdup(optarg);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	    break;
7117c478bd9Sstevel@tonic-gate 	case '4':
7127c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7137c478bd9Sstevel@tonic-gate 	    if (v4mode)
7147c478bd9Sstevel@tonic-gate 		free(v4mode);
7157c478bd9Sstevel@tonic-gate 	    v4mode = strdup(optarg);
7167c478bd9Sstevel@tonic-gate #endif
7177c478bd9Sstevel@tonic-gate 	    break;
7187c478bd9Sstevel@tonic-gate 	case '3':
7197c478bd9Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
7207c478bd9Sstevel@tonic-gate 	    if (krb5_enctypes_list[krb5_enctypes_length-1].etype
7217c478bd9Sstevel@tonic-gate 		!= ENCTYPE_LOCAL_DES3_HMAC_SHA1) {
7227c478bd9Sstevel@tonic-gate 		fprintf(stderr,
7237c478bd9Sstevel@tonic-gate 			"internal inconsistency in enctypes_list"
7247c478bd9Sstevel@tonic-gate 			" while disabling\n"
7257c478bd9Sstevel@tonic-gate 			"des3-marc-hmac-sha1 enctype\n");
7267c478bd9Sstevel@tonic-gate 		exit(1);
7277c478bd9Sstevel@tonic-gate 	    }
7287c478bd9Sstevel@tonic-gate 	    krb5_enctypes_length--;
7297c478bd9Sstevel@tonic-gate 	    break;
7307c478bd9Sstevel@tonic-gate #endif
7317c478bd9Sstevel@tonic-gate 	case '?':
7327c478bd9Sstevel@tonic-gate 	default:
7337c478bd9Sstevel@tonic-gate 	    usage(argv[0]);
7347c478bd9Sstevel@tonic-gate 	    exit(1);
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate     }
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7397c478bd9Sstevel@tonic-gate     /*
7407c478bd9Sstevel@tonic-gate      * Setup the v4 mode
7417c478bd9Sstevel@tonic-gate      */
7427c478bd9Sstevel@tonic-gate     process_v4_mode(argv[0], v4mode);
7437c478bd9Sstevel@tonic-gate #endif
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate     /*
7467c478bd9Sstevel@tonic-gate      * Check to see if we processed any realms.
7477c478bd9Sstevel@tonic-gate      */
7487c478bd9Sstevel@tonic-gate     if (kdc_numrealms == 0) {
7497c478bd9Sstevel@tonic-gate 	/* no realm specified, use default realm */
7507c478bd9Sstevel@tonic-gate 	if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
7517c478bd9Sstevel@tonic-gate 	    com_err(argv[0], retval,
7527c478bd9Sstevel@tonic-gate 		gettext("while attempting to retrieve default realm"));
7537c478bd9Sstevel@tonic-gate 	    exit(1);
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 	if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
7567c478bd9Sstevel@tonic-gate 	    if ((retval = init_realm(argv[0], rdatap, lrealm, db_name,
7577c478bd9Sstevel@tonic-gate 				     mkey_name, menctype, default_udp_ports,
7587c478bd9Sstevel@tonic-gate 				     default_tcp_ports, manual))) {
7597c478bd9Sstevel@tonic-gate 		fprintf(stderr,
7607c478bd9Sstevel@tonic-gate 			gettext("%s: cannot initialize realm %s\n"),
7617c478bd9Sstevel@tonic-gate 			argv[0], lrealm);
7627c478bd9Sstevel@tonic-gate 		exit(1);
7637c478bd9Sstevel@tonic-gate 	    }
7647c478bd9Sstevel@tonic-gate 	    kdc_realmlist[0] = rdatap;
7657c478bd9Sstevel@tonic-gate 	    kdc_numrealms++;
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate     }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate #ifdef USE_RCACHE
7707c478bd9Sstevel@tonic-gate     /*
7717c478bd9Sstevel@tonic-gate      * Now handle the replay cache.
7727c478bd9Sstevel@tonic-gate      */
7737c478bd9Sstevel@tonic-gate     if ((retval = kdc_initialize_rcache(kcontext, rcname))) {
7747c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing KDC replay cache"));
7757c478bd9Sstevel@tonic-gate 	exit(1);
7767c478bd9Sstevel@tonic-gate     }
7777c478bd9Sstevel@tonic-gate #endif
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate     /* Ensure that this is set for our first request. */
7807c478bd9Sstevel@tonic-gate     kdc_active_realm = kdc_realmlist[0];
7817c478bd9Sstevel@tonic-gate     if (default_udp_ports)
7827c478bd9Sstevel@tonic-gate 	free(default_udp_ports);
7837c478bd9Sstevel@tonic-gate     if (default_tcp_ports)
7847c478bd9Sstevel@tonic-gate 	free(default_tcp_ports);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate     return;
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate void
7907c478bd9Sstevel@tonic-gate finish_realms(prog)
7917c478bd9Sstevel@tonic-gate     char *prog;
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate     int i;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate     for (i = 0; i < kdc_numrealms; i++) {
7967c478bd9Sstevel@tonic-gate 	finish_realm(kdc_realmlist[i]);
7977c478bd9Sstevel@tonic-gate 	kdc_realmlist[i] = 0;
7987c478bd9Sstevel@tonic-gate     }
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate /*
8027c478bd9Sstevel@tonic-gate  outline:
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate  process args & setup
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate  initialize database access (fetch master key, open DB)
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate  initialize network
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate  loop:
8117c478bd9Sstevel@tonic-gate  	listen for packet
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	determine packet type, dispatch to handling routine
8147c478bd9Sstevel@tonic-gate 		(AS or TGS (or V4?))
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	reflect response
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	exit on signal
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate  clean up secrets, close db
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate  shut down network
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate  exit
8257c478bd9Sstevel@tonic-gate  */
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate int main(argc, argv)
8287c478bd9Sstevel@tonic-gate      int argc;
8297c478bd9Sstevel@tonic-gate      char *argv[];
8307c478bd9Sstevel@tonic-gate {
8317c478bd9Sstevel@tonic-gate     krb5_error_code	retval;
8327c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
8337c478bd9Sstevel@tonic-gate     int			*port_list;
8347c478bd9Sstevel@tonic-gate     int errout = 0;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
8397c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"KRB5KDC_TEST"	/* Use this only if it weren't */
8407c478bd9Sstevel@tonic-gate #endif
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate     if (strrchr(argv[0], '/'))
8457c478bd9Sstevel@tonic-gate 	argv[0] = strrchr(argv[0], '/')+1;
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate     if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) *
8487c478bd9Sstevel@tonic-gate 						  KRB5_KDC_MAX_REALMS))) {
8497c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]);
8507c478bd9Sstevel@tonic-gate 	exit(1);
8517c478bd9Sstevel@tonic-gate     }
8527c478bd9Sstevel@tonic-gate     memset((char *) kdc_realmlist, 0,
8537c478bd9Sstevel@tonic-gate 	   (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));
8547c478bd9Sstevel@tonic-gate     port_list = NULL;
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate     /*
8577c478bd9Sstevel@tonic-gate      * A note about Kerberos contexts: This context, "kcontext", is used
8587c478bd9Sstevel@tonic-gate      * for the KDC operations, i.e. setup, network connection and error
8597c478bd9Sstevel@tonic-gate      * reporting.  The per-realm operations use the "realm_context"
8607c478bd9Sstevel@tonic-gate      * associated with each realm.
8617c478bd9Sstevel@tonic-gate      */
8627c478bd9Sstevel@tonic-gate     retval = krb5_init_context(&kcontext);
8637c478bd9Sstevel@tonic-gate     if (retval) {
8647c478bd9Sstevel@tonic-gate 	    com_err(argv[0], retval, gettext("while initializing krb5"));
8657c478bd9Sstevel@tonic-gate 	    exit(1);
8667c478bd9Sstevel@tonic-gate     }
8677c478bd9Sstevel@tonic-gate     krb5_klog_init(kcontext, "kdc", argv[0], 1);
8687c478bd9Sstevel@tonic-gate     /* initialize_kdc5_error_table();  SUNWresync121 XXX */
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate     /*
8717c478bd9Sstevel@tonic-gate      * Scan through the argument list
8727c478bd9Sstevel@tonic-gate      */
8737c478bd9Sstevel@tonic-gate     initialize_realms(kcontext, argc, argv);
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate     setup_signal_handlers();
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate     if (retval = setup_sam()) {
8787c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing SAM"));
8797c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
8807c478bd9Sstevel@tonic-gate 	return 1;
8817c478bd9Sstevel@tonic-gate     }
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate     if ((retval = setup_network(argv[0]))) {
8847c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing network"));
8857c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
8867c478bd9Sstevel@tonic-gate 	return 1;
8877c478bd9Sstevel@tonic-gate     }
8887c478bd9Sstevel@tonic-gate     if (!nofork && daemon(0, 0)) {
8897c478bd9Sstevel@tonic-gate 	com_err(argv[0], errno, gettext("while detaching from tty"));
8907c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
8917c478bd9Sstevel@tonic-gate 	return 1;
8927c478bd9Sstevel@tonic-gate     }
8937c478bd9Sstevel@tonic-gate     if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) {
8947c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while logging message"));
8957c478bd9Sstevel@tonic-gate 	errout++;
8967c478bd9Sstevel@tonic-gate 	};
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate     if ((retval = listen_and_process(argv[0]))) {
8997c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while processing network requests"));
9007c478bd9Sstevel@tonic-gate 	errout++;
9017c478bd9Sstevel@tonic-gate     }
9027c478bd9Sstevel@tonic-gate     if ((retval = closedown_network(argv[0]))) {
9037c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while shutting down network"));
9047c478bd9Sstevel@tonic-gate 	errout++;
9057c478bd9Sstevel@tonic-gate     }
9067c478bd9Sstevel@tonic-gate     krb5_klog_syslog(LOG_INFO, "shutting down");
9077c478bd9Sstevel@tonic-gate     krb5_klog_close(kdc_context);
9087c478bd9Sstevel@tonic-gate     finish_realms(argv[0]);
9097c478bd9Sstevel@tonic-gate     krb5_free_context(kcontext);
9107c478bd9Sstevel@tonic-gate     return errout;
9117c478bd9Sstevel@tonic-gate }
912