xref: /onnv-gate/usr/src/cmd/krb5/krb5kdc/main.c (revision 781:57319a72b15f)
10Sstevel@tonic-gate /*
2*781Sgtb  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate 
80Sstevel@tonic-gate /*
90Sstevel@tonic-gate  * kdc/main.c
100Sstevel@tonic-gate  *
110Sstevel@tonic-gate  * Copyright 1990,2001 by the Massachusetts Institute of Technology.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * Export of this software from the United States of America may
140Sstevel@tonic-gate  *   require a specific license from the United States Government.
150Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
160Sstevel@tonic-gate  *   export to obtain such a license before exporting.
170Sstevel@tonic-gate  *
180Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
190Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
200Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
210Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
220Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
230Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
240Sstevel@tonic-gate  * to distribution of the software without specific, written prior
250Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
260Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
270Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
280Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
290Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
300Sstevel@tonic-gate  * or implied warranty.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  * Main procedure body for the KDC server process.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <syslog.h>
380Sstevel@tonic-gate #include <signal.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <netdb.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include "k5-int.h"
430Sstevel@tonic-gate #include "com_err.h"
440Sstevel@tonic-gate #include "adm.h"
450Sstevel@tonic-gate #include "adm_proto.h"
460Sstevel@tonic-gate #include "kdc_util.h"
470Sstevel@tonic-gate #include "extern.h"
480Sstevel@tonic-gate #include "kdc5_err.h"
490Sstevel@tonic-gate #include <libintl.h>
500Sstevel@tonic-gate #include <locale.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #ifdef HAVE_NETINET_IN_H
530Sstevel@tonic-gate #include <netinet/in.h>
540Sstevel@tonic-gate #endif
550Sstevel@tonic-gate 
56*781Sgtb kdc_realm_t *find_realm_data (char *, krb5_ui_4);
570Sstevel@tonic-gate 
58*781Sgtb void usage (char *);
590Sstevel@tonic-gate 
60*781Sgtb krb5_sigtype request_exit (int);
61*781Sgtb krb5_sigtype request_hup  (int);
620Sstevel@tonic-gate 
63*781Sgtb void setup_signal_handlers (void);
640Sstevel@tonic-gate 
65*781Sgtb krb5_error_code setup_sam (void);
660Sstevel@tonic-gate 
67*781Sgtb void initialize_realms (krb5_context, int, char **);
680Sstevel@tonic-gate 
69*781Sgtb void finish_realms (char *);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static int nofork = 0;
720Sstevel@tonic-gate static int rkey_init_done = 0;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /* Solaris Kerberos: global here that other functions access */
750Sstevel@tonic-gate int max_tcp_data_connections;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate #ifdef POSIX_SIGNALS
780Sstevel@tonic-gate static struct sigaction s_action;
790Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
800Sstevel@tonic-gate 
810Sstevel@tonic-gate #define	KRB5_KDC_MAX_REALMS	32
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * Find the realm entry for a given realm.
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate kdc_realm_t *
870Sstevel@tonic-gate find_realm_data(rname, rsize)
880Sstevel@tonic-gate     char 	*rname;
890Sstevel@tonic-gate     krb5_ui_4	rsize;
900Sstevel@tonic-gate {
910Sstevel@tonic-gate     int i;
920Sstevel@tonic-gate     for (i=0; i<kdc_numrealms; i++) {
930Sstevel@tonic-gate 	if ((rsize == strlen(kdc_realmlist[i]->realm_name)) &&
940Sstevel@tonic-gate 	    !strncmp(rname, kdc_realmlist[i]->realm_name, rsize))
950Sstevel@tonic-gate 	    return(kdc_realmlist[i]);
960Sstevel@tonic-gate     }
970Sstevel@tonic-gate     return((kdc_realm_t *) NULL);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate krb5_error_code
1010Sstevel@tonic-gate setup_server_realm(sprinc)
1020Sstevel@tonic-gate     krb5_principal	sprinc;
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate     krb5_error_code	kret;
1050Sstevel@tonic-gate     kdc_realm_t		*newrealm;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate     kret = 0;
1080Sstevel@tonic-gate     if (kdc_numrealms > 1) {
1090Sstevel@tonic-gate 	if (!(newrealm = find_realm_data(sprinc->realm.data,
1100Sstevel@tonic-gate 					 (krb5_ui_4) sprinc->realm.length)))
1110Sstevel@tonic-gate 	    kret = ENOENT;
1120Sstevel@tonic-gate 	else
1130Sstevel@tonic-gate 	    kdc_active_realm = newrealm;
1140Sstevel@tonic-gate     }
1150Sstevel@tonic-gate     else
1160Sstevel@tonic-gate 	kdc_active_realm = kdc_realmlist[0];
1170Sstevel@tonic-gate     return(kret);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate static void
1210Sstevel@tonic-gate finish_realm(rdp)
1220Sstevel@tonic-gate     kdc_realm_t *rdp;
1230Sstevel@tonic-gate {
1240Sstevel@tonic-gate     if (rdp->realm_dbname)
1250Sstevel@tonic-gate 	free(rdp->realm_dbname);
1260Sstevel@tonic-gate     if (rdp->realm_mpname)
1270Sstevel@tonic-gate 	free(rdp->realm_mpname);
1280Sstevel@tonic-gate     if (rdp->realm_stash)
1290Sstevel@tonic-gate 	free(rdp->realm_stash);
1300Sstevel@tonic-gate     if (rdp->realm_ports)
1310Sstevel@tonic-gate 	free(rdp->realm_ports);
1320Sstevel@tonic-gate     if (rdp->realm_tcp_ports)
1330Sstevel@tonic-gate 	free(rdp->realm_tcp_ports);
1340Sstevel@tonic-gate     if (rdp->realm_kstypes)
1350Sstevel@tonic-gate 	free(rdp->realm_kstypes);
1360Sstevel@tonic-gate     if (rdp->realm_keytab)
1370Sstevel@tonic-gate 	krb5_kt_close(rdp->realm_context, rdp->realm_keytab);
1380Sstevel@tonic-gate     if (rdp->realm_context) {
1390Sstevel@tonic-gate 	if (rdp->realm_mprinc)
1400Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
1410Sstevel@tonic-gate 	if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
1420Sstevel@tonic-gate 	    memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
1430Sstevel@tonic-gate 	    free(rdp->realm_mkey.contents);
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 	if (rdp->realm_tgskey.length && rdp->realm_tgskey.contents) {
1460Sstevel@tonic-gate 	    memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length);
1470Sstevel@tonic-gate 	    free(rdp->realm_tgskey.contents);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	krb5_db_fini(rdp->realm_context);
1500Sstevel@tonic-gate 	if (rdp->realm_tgsprinc)
1510Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
1520Sstevel@tonic-gate 	krb5_free_context(rdp->realm_context);
1530Sstevel@tonic-gate     }
1540Sstevel@tonic-gate     free(rdp);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate  * Initialize a realm control structure from the alternate profile or from
1590Sstevel@tonic-gate  * the specified defaults.
1600Sstevel@tonic-gate  *
1610Sstevel@tonic-gate  * After we're complete here, the essence of the realm is embodied in the
1620Sstevel@tonic-gate  * realm data and we should be all set to begin operation for that realm.
1630Sstevel@tonic-gate  */
1640Sstevel@tonic-gate static krb5_error_code
1650Sstevel@tonic-gate init_realm(progname, rdp, realm, def_dbname, def_mpname,
1660Sstevel@tonic-gate 		 def_enctype, def_udp_ports, def_tcp_ports, def_manual)
1670Sstevel@tonic-gate     char		*progname;
1680Sstevel@tonic-gate     kdc_realm_t		*rdp;
1690Sstevel@tonic-gate     char		*realm;
1700Sstevel@tonic-gate     char		*def_dbname;
1710Sstevel@tonic-gate     char		*def_mpname;
1720Sstevel@tonic-gate     krb5_enctype	def_enctype;
1730Sstevel@tonic-gate     char		*def_udp_ports;
1740Sstevel@tonic-gate     char		*def_tcp_ports;
1750Sstevel@tonic-gate     krb5_boolean	def_manual;
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate     krb5_error_code	kret;
1780Sstevel@tonic-gate     krb5_boolean	manual;
1790Sstevel@tonic-gate     krb5_db_entry	db_entry;
1800Sstevel@tonic-gate     int			num2get;
1810Sstevel@tonic-gate     krb5_boolean	more;
1820Sstevel@tonic-gate     krb5_boolean	db_inited;
1830Sstevel@tonic-gate     krb5_realm_params	*rparams;
1840Sstevel@tonic-gate     krb5_key_data	*kdata;
1850Sstevel@tonic-gate     krb5_key_salt_tuple	*kslist;
1860Sstevel@tonic-gate     krb5_int32		nkslist;
1870Sstevel@tonic-gate     int			i;
1880Sstevel@tonic-gate     krb5_deltat		now, krb5_kdb_max_time;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate     db_inited = 0;
1910Sstevel@tonic-gate     memset((char *) rdp, 0, sizeof(kdc_realm_t));
1920Sstevel@tonic-gate     if (!realm) {
1930Sstevel@tonic-gate 	kret = EINVAL;
1940Sstevel@tonic-gate 	goto whoops;
1950Sstevel@tonic-gate     }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate     rdp->realm_name = realm;
1980Sstevel@tonic-gate     kret = krb5_init_context(&rdp->realm_context);
1990Sstevel@tonic-gate     if (kret) {
2000Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting context for realm %s"),
2010Sstevel@tonic-gate 		realm);
2020Sstevel@tonic-gate 	goto whoops;
2030Sstevel@tonic-gate     }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate     kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name,
2060Sstevel@tonic-gate 				  (char *) NULL, (char *) NULL, &rparams);
2070Sstevel@tonic-gate     if (kret) {
2080Sstevel@tonic-gate 	com_err(progname, kret, gettext("while reading realm parameters"));
2090Sstevel@tonic-gate 	goto whoops;
2100Sstevel@tonic-gate     }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate     /* Handle profile file name */
2130Sstevel@tonic-gate     if (rparams && rparams->realm_profile)
2140Sstevel@tonic-gate 	rdp->realm_profile = strdup(rparams->realm_profile);
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate     /* Handle database name */
2170Sstevel@tonic-gate     if (rparams && rparams->realm_dbname)
2180Sstevel@tonic-gate 	rdp->realm_dbname = strdup(rparams->realm_dbname);
2190Sstevel@tonic-gate     else
2200Sstevel@tonic-gate 	rdp->realm_dbname = (def_dbname) ? strdup(def_dbname) :
2210Sstevel@tonic-gate 	    strdup(DEFAULT_KDB_FILE);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate     /* Handle master key name */
2240Sstevel@tonic-gate     if (rparams && rparams->realm_mkey_name)
2250Sstevel@tonic-gate 	rdp->realm_mpname = strdup(rparams->realm_mkey_name);
2260Sstevel@tonic-gate     else
2270Sstevel@tonic-gate 	rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) :
2280Sstevel@tonic-gate 	    strdup(KRB5_KDB_M_NAME);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate     /* Handle KDC ports */
2310Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_ports)
2320Sstevel@tonic-gate 	rdp->realm_ports = strdup(rparams->realm_kdc_ports);
2330Sstevel@tonic-gate     else
2340Sstevel@tonic-gate 	rdp->realm_ports = strdup(def_udp_ports);
2350Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_tcp_ports)
2360Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports);
2370Sstevel@tonic-gate     else
2380Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(def_tcp_ports);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate     /* Handle stash file */
2410Sstevel@tonic-gate     if (rparams && rparams->realm_stash_file) {
2420Sstevel@tonic-gate 	rdp->realm_stash = strdup(rparams->realm_stash_file);
2430Sstevel@tonic-gate 	manual = FALSE;
2440Sstevel@tonic-gate     } else
2450Sstevel@tonic-gate 	manual = def_manual;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate     /* Handle master key type */
2480Sstevel@tonic-gate     if (rparams && rparams->realm_enctype_valid)
2490Sstevel@tonic-gate 	rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
2500Sstevel@tonic-gate     else
2510Sstevel@tonic-gate 	rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN;
2520Sstevel@tonic-gate     if ((kret = krb5_timeofday(rdp->realm_context, &now))) {
2530Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting timeofday"));
2540Sstevel@tonic-gate 	goto whoops;
2550Sstevel@tonic-gate     }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate     /* Handle ticket maximum life */
2580Sstevel@tonic-gate     if (rparams && rparams->realm_max_life_valid)
2590Sstevel@tonic-gate    	rdp->realm_maxlife = rparams->realm_max_life;
2600Sstevel@tonic-gate     else
2610Sstevel@tonic-gate 	rdp->realm_maxlife = KRB5_KDB_EXPIRATION - now - 3600;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate     /* Handle ticket renewable maximum life */
2640Sstevel@tonic-gate     if (rparams && rparams->realm_max_rlife_valid)
2650Sstevel@tonic-gate    	rdp->realm_maxrlife = rparams->realm_max_rlife;
2660Sstevel@tonic-gate     else
2670Sstevel@tonic-gate    	rdp->realm_maxrlife = KRB5_KDB_EXPIRATION - now - 3600;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate     /* Handle key/salt list */
2700Sstevel@tonic-gate     if (rparams && rparams->realm_num_keysalts) {
2710Sstevel@tonic-gate 	rdp->realm_kstypes = rparams->realm_keysalts;
2720Sstevel@tonic-gate 	rdp->realm_nkstypes = rparams->realm_num_keysalts;
2730Sstevel@tonic-gate 	rparams->realm_keysalts = NULL;
2740Sstevel@tonic-gate 	rparams->realm_num_keysalts = 0;
2750Sstevel@tonic-gate 	kslist = (krb5_key_salt_tuple *) rdp->realm_kstypes;
2760Sstevel@tonic-gate 	nkslist = rdp->realm_nkstypes;
2770Sstevel@tonic-gate     } else {
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * XXX  Initialize default key/salt list.
2800Sstevel@tonic-gate 	 */
2810Sstevel@tonic-gate 	if ((kslist = (krb5_key_salt_tuple *)
2820Sstevel@tonic-gate 	     malloc(sizeof(krb5_key_salt_tuple)))) {
2830Sstevel@tonic-gate 	    kslist->ks_enctype = ENCTYPE_DES_CBC_CRC;
2840Sstevel@tonic-gate 	    kslist->ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
2850Sstevel@tonic-gate 	    rdp->realm_kstypes = kslist;
2860Sstevel@tonic-gate 	    rdp->realm_nkstypes = 1;
2870Sstevel@tonic-gate 	    nkslist = 1;
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 	else {
2900Sstevel@tonic-gate 	    com_err(progname, ENOMEM,
2910Sstevel@tonic-gate 		    gettext("while setting up key/salt list for realm %s"),
2920Sstevel@tonic-gate 		    realm);
2930Sstevel@tonic-gate 	    exit(1);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate     }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate     if (rparams)
2980Sstevel@tonic-gate 	krb5_free_realm_params(rdp->realm_context, rparams);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate     /*
3010Sstevel@tonic-gate      * We've got our parameters, now go and setup our realm context.
3020Sstevel@tonic-gate      */
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate     /* Set the default realm of this context */
3050Sstevel@tonic-gate     if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) {
3060Sstevel@tonic-gate 	com_err(progname, kret, gettext("while setting default realm to %s"),
3070Sstevel@tonic-gate 		realm);
3080Sstevel@tonic-gate 	goto whoops;
3090Sstevel@tonic-gate     }
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate     /* Assemble and parse the master key name */
3120Sstevel@tonic-gate     if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname,
3130Sstevel@tonic-gate 					rdp->realm_name, (char **) NULL,
3140Sstevel@tonic-gate 					&rdp->realm_mprinc))) {
3150Sstevel@tonic-gate 	com_err(progname, kret,
3160Sstevel@tonic-gate 		gettext("while setting up master key name %s for realm %s"),
3170Sstevel@tonic-gate 		rdp->realm_mpname, realm);
3180Sstevel@tonic-gate 	goto whoops;
3190Sstevel@tonic-gate     }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate     /*
3220Sstevel@tonic-gate      * Get the master key.
3230Sstevel@tonic-gate      */
3240Sstevel@tonic-gate     if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
3250Sstevel@tonic-gate 				   rdp->realm_mkey.enctype, manual,
3260Sstevel@tonic-gate 				   FALSE, rdp->realm_stash,
3270Sstevel@tonic-gate 				   0, &rdp->realm_mkey))) {
3280Sstevel@tonic-gate 	com_err(progname, kret,
3290Sstevel@tonic-gate 		gettext("while fetching master key %s for realm %s"),
3300Sstevel@tonic-gate 		rdp->realm_mpname, realm);
3310Sstevel@tonic-gate 	goto whoops;
3320Sstevel@tonic-gate     }
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate     /* Set and open the database. */
3350Sstevel@tonic-gate     if (rdp->realm_dbname &&
3360Sstevel@tonic-gate 	(kret = krb5_db_set_name(rdp->realm_context, rdp->realm_dbname))) {
3370Sstevel@tonic-gate 	com_err(progname, kret,
3380Sstevel@tonic-gate 		gettext("while setting database name to %s for realm %s"),
3390Sstevel@tonic-gate 		rdp->realm_dbname, realm);
3400Sstevel@tonic-gate 	goto whoops;
3410Sstevel@tonic-gate     }
3420Sstevel@tonic-gate     if ((kret = krb5_db_init(rdp->realm_context))) {
3430Sstevel@tonic-gate 	com_err(progname, kret,
3440Sstevel@tonic-gate 		gettext("while initializing database "),
3450Sstevel@tonic-gate 		gettext("for realm %s"), realm);
3460Sstevel@tonic-gate 	goto whoops;
3470Sstevel@tonic-gate     } else
3480Sstevel@tonic-gate 	db_inited = 1;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate     /* Verify the master key */
3510Sstevel@tonic-gate     if ((kret = krb5_db_verify_master_key(rdp->realm_context,
3520Sstevel@tonic-gate 					  rdp->realm_mprinc,
3530Sstevel@tonic-gate 					  &rdp->realm_mkey))) {
3540Sstevel@tonic-gate 	com_err(progname, kret,
3550Sstevel@tonic-gate 		gettext("while verifying master key for realm %s"),
3560Sstevel@tonic-gate 		realm);
3570Sstevel@tonic-gate 	goto whoops;
3580Sstevel@tonic-gate     }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate     /* Fetch the master key and get its version number */
3610Sstevel@tonic-gate     num2get = 1;
3620Sstevel@tonic-gate     kret = krb5_db_get_principal(rdp->realm_context, rdp->realm_mprinc,
3630Sstevel@tonic-gate 				 &db_entry, &num2get, &more);
3640Sstevel@tonic-gate     if (!kret) {
3650Sstevel@tonic-gate 	if (num2get != 1)
3660Sstevel@tonic-gate 	    kret = KRB5_KDB_NOMASTERKEY;
3670Sstevel@tonic-gate 	else {
3680Sstevel@tonic-gate 	    if (more) {
3690Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
3700Sstevel@tonic-gate 				       &db_entry,
3710Sstevel@tonic-gate 				       num2get);
3720Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
3730Sstevel@tonic-gate 	    }
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate     }
3760Sstevel@tonic-gate     if (kret) {
3770Sstevel@tonic-gate 	com_err(progname, kret,
3780Sstevel@tonic-gate 		gettext("while fetching master entry for realm %s"),
3790Sstevel@tonic-gate 		realm);
3800Sstevel@tonic-gate 	goto whoops;
3810Sstevel@tonic-gate     }
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate     /*
3840Sstevel@tonic-gate      * Get the most recent master key.  Search the key list in
3850Sstevel@tonic-gate      * the order specified by the key/salt list.
3860Sstevel@tonic-gate      */
3870Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
3880Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
3890Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
3900Sstevel@tonic-gate 					   &db_entry,
3910Sstevel@tonic-gate 					   kslist[i].ks_enctype,
3920Sstevel@tonic-gate 					   -1,
3930Sstevel@tonic-gate 					   -1,
3940Sstevel@tonic-gate 					   &kdata)))
3950Sstevel@tonic-gate 	    break;
3960Sstevel@tonic-gate     }
3970Sstevel@tonic-gate     if (!kdata) {
3980Sstevel@tonic-gate 	com_err(progname, kret,
3990Sstevel@tonic-gate 		gettext("while finding master key for realm %s"),
4000Sstevel@tonic-gate 		realm);
4010Sstevel@tonic-gate 	goto whoops;
4020Sstevel@tonic-gate     }
4030Sstevel@tonic-gate     rdp->realm_mkvno = kdata->key_data_kvno;
4040Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context, &db_entry, num2get);
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate     if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) {
4070Sstevel@tonic-gate 	com_err(progname, kret,
4080Sstevel@tonic-gate 		gettext("while processing master key for realm %s"),
4090Sstevel@tonic-gate 		realm);
4100Sstevel@tonic-gate 	goto whoops;
4110Sstevel@tonic-gate     }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate     /* Set up the keytab */
4140Sstevel@tonic-gate     if ((kret = krb5_ktkdb_resolve(rdp->realm_context,
4150Sstevel@tonic-gate 				   NULL,
4160Sstevel@tonic-gate 				   &rdp->realm_keytab))) {
4170Sstevel@tonic-gate 	com_err(progname, kret,
4180Sstevel@tonic-gate 		gettext("while resolving kdb keytab for realm %s"),
4190Sstevel@tonic-gate 		realm);
4200Sstevel@tonic-gate 	goto whoops;
4210Sstevel@tonic-gate     }
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate     /* Preformat the TGS name */
4240Sstevel@tonic-gate     if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc,
4250Sstevel@tonic-gate 				     strlen(realm), realm, KRB5_TGS_NAME,
4260Sstevel@tonic-gate 				     realm, (char *) NULL))) {
4270Sstevel@tonic-gate 	com_err(progname, kret,
4280Sstevel@tonic-gate 		gettext("while building TGS name for realm %s"),
4290Sstevel@tonic-gate 		realm);
4300Sstevel@tonic-gate 	goto whoops;
4310Sstevel@tonic-gate     }
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate     /* Get the TGS database entry */
4340Sstevel@tonic-gate     num2get = 1;
4350Sstevel@tonic-gate     if (!(kret = krb5_db_get_principal(rdp->realm_context,
4360Sstevel@tonic-gate 				       rdp->realm_tgsprinc,
4370Sstevel@tonic-gate 				       &db_entry,
4380Sstevel@tonic-gate 				       &num2get,
4390Sstevel@tonic-gate 				       &more))) {
4400Sstevel@tonic-gate 	if (num2get != 1)
4410Sstevel@tonic-gate 	    kret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
4420Sstevel@tonic-gate 	else {
4430Sstevel@tonic-gate 	    if (more) {
4440Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
4450Sstevel@tonic-gate 				       &db_entry,
4460Sstevel@tonic-gate 				       num2get);
4470Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
4480Sstevel@tonic-gate 	    }
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate     }
4510Sstevel@tonic-gate     if (kret) {
4520Sstevel@tonic-gate 	com_err(progname, kret,
4530Sstevel@tonic-gate 		gettext("while fetching TGS entry for realm %s"),
4540Sstevel@tonic-gate 		realm);
4550Sstevel@tonic-gate 	goto whoops;
4560Sstevel@tonic-gate     }
4570Sstevel@tonic-gate     /*
4580Sstevel@tonic-gate      * Get the most recent TGS key.  Search the key list in
4590Sstevel@tonic-gate      * the order specified by the key/salt list.
4600Sstevel@tonic-gate      */
4610Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
4620Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
4630Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
4640Sstevel@tonic-gate 					   &db_entry,
4650Sstevel@tonic-gate 					   kslist[i].ks_enctype,
4660Sstevel@tonic-gate 					   -1,
4670Sstevel@tonic-gate 					   -1,
4680Sstevel@tonic-gate 					   &kdata)))
4690Sstevel@tonic-gate 	    break;
4700Sstevel@tonic-gate     }
4710Sstevel@tonic-gate     if (!kdata) {
4720Sstevel@tonic-gate 	com_err(progname, kret,
4730Sstevel@tonic-gate 		gettext("while finding TGS key for realm %s"),
4740Sstevel@tonic-gate 		realm);
4750Sstevel@tonic-gate 	goto whoops;
4760Sstevel@tonic-gate     }
4770Sstevel@tonic-gate     if (!(kret = krb5_dbekd_decrypt_key_data(rdp->realm_context,
4780Sstevel@tonic-gate 					     &rdp->realm_mkey,
4790Sstevel@tonic-gate 					     kdata,
4800Sstevel@tonic-gate 					     &rdp->realm_tgskey, NULL))){
4810Sstevel@tonic-gate 	rdp->realm_tgskvno = kdata->key_data_kvno;
4820Sstevel@tonic-gate     }
4830Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context,
4840Sstevel@tonic-gate 			   &db_entry,
4850Sstevel@tonic-gate 			   num2get);
4860Sstevel@tonic-gate     if (kret) {
4870Sstevel@tonic-gate 	com_err(progname, kret,
4880Sstevel@tonic-gate 		gettext("while decrypting TGS key for realm %s"),
4890Sstevel@tonic-gate 		realm);
4900Sstevel@tonic-gate 	goto whoops;
4910Sstevel@tonic-gate     }
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate     if (!rkey_init_done) {
4940Sstevel@tonic-gate 	krb5_timestamp now;
4950Sstevel@tonic-gate 	krb5_data seed;
4960Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
4970Sstevel@tonic-gate 	krb5_keyblock temp_key;
4980Sstevel@tonic-gate #endif
4990Sstevel@tonic-gate 	/*
5000Sstevel@tonic-gate 	 * If all that worked, then initialize the random key
5010Sstevel@tonic-gate 	 * generators.
5020Sstevel@tonic-gate 	 */
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	if ((kret = krb5_timeofday(rdp->realm_context, &now)))
5050Sstevel@tonic-gate 	    goto whoops;
5060Sstevel@tonic-gate 	seed.length = sizeof(now);
5070Sstevel@tonic-gate 	seed.data = (char *) &now;
5080Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
5090Sstevel@tonic-gate 	    goto whoops;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	seed.length = rdp->realm_mkey.length;
5120Sstevel@tonic-gate 	seed.data = (char *)rdp->realm_mkey.contents;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
5150Sstevel@tonic-gate 	    goto whoops;
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
5180Sstevel@tonic-gate 	if ((kret = krb5_c_make_random_key(rdp->realm_context,
5190Sstevel@tonic-gate 					   ENCTYPE_DES_CBC_CRC, &temp_key))) {
5200Sstevel@tonic-gate 	    com_err(progname, kret,
5210Sstevel@tonic-gate 		    "while initializing V4 random key generator");
5220Sstevel@tonic-gate 	    goto whoops;
5230Sstevel@tonic-gate 	}
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	(void) des_init_random_number_generator(temp_key.contents);
5260Sstevel@tonic-gate 	krb5_free_keyblock_contents(rdp->realm_context, &temp_key);
5270Sstevel@tonic-gate #endif
5280Sstevel@tonic-gate 	rkey_init_done = 1;
5290Sstevel@tonic-gate     }
5300Sstevel@tonic-gate  whoops:
5310Sstevel@tonic-gate     /*
5320Sstevel@tonic-gate      * If we choked, then clean up any dirt we may have dropped on the floor.
5330Sstevel@tonic-gate      */
5340Sstevel@tonic-gate     if (kret) {
5350Sstevel@tonic-gate 	finish_realm(rdp);
5360Sstevel@tonic-gate     }
5370Sstevel@tonic-gate     return(kret);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate krb5_sigtype
5410Sstevel@tonic-gate request_exit(signo)
5420Sstevel@tonic-gate     int signo;
5430Sstevel@tonic-gate {
5440Sstevel@tonic-gate     signal_requests_exit = 1;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
5470Sstevel@tonic-gate     return;
5480Sstevel@tonic-gate #else
5490Sstevel@tonic-gate     return(0);
5500Sstevel@tonic-gate #endif
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate krb5_sigtype
5540Sstevel@tonic-gate request_hup(signo)
5550Sstevel@tonic-gate     int signo;
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate     signal_requests_hup = 1;
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
5600Sstevel@tonic-gate     return;
5610Sstevel@tonic-gate #else
5620Sstevel@tonic-gate     return(0);
5630Sstevel@tonic-gate #endif
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate void
5670Sstevel@tonic-gate setup_signal_handlers()
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate #ifdef POSIX_SIGNALS
5700Sstevel@tonic-gate     (void) sigemptyset(&s_action.sa_mask);
5710Sstevel@tonic-gate     s_action.sa_flags = 0;
5720Sstevel@tonic-gate     s_action.sa_handler = request_exit;
5730Sstevel@tonic-gate     (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
5740Sstevel@tonic-gate     (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
5750Sstevel@tonic-gate     s_action.sa_handler = request_hup;
5760Sstevel@tonic-gate     (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL);
5770Sstevel@tonic-gate #else  /* POSIX_SIGNALS */
5780Sstevel@tonic-gate     signal(SIGINT, request_exit);
5790Sstevel@tonic-gate     signal(SIGTERM, request_exit);
5800Sstevel@tonic-gate     signal(SIGHUP, request_hup);
5810Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate     return;
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate krb5_error_code
5870Sstevel@tonic-gate setup_sam()
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate     return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key);
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate void
5930Sstevel@tonic-gate usage(name)
5940Sstevel@tonic-gate char *name;
5950Sstevel@tonic-gate {
5960Sstevel@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);
5970Sstevel@tonic-gate     return;
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate void
6010Sstevel@tonic-gate initialize_realms(kcontext, argc, argv)
6020Sstevel@tonic-gate     krb5_context 	kcontext;
6030Sstevel@tonic-gate     int			argc;
6040Sstevel@tonic-gate     char		**argv;
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate     int 		c;
6070Sstevel@tonic-gate     char		*db_name = (char *) NULL;
6080Sstevel@tonic-gate     char		*mkey_name = (char *) NULL;
6090Sstevel@tonic-gate     char		*rcname = KDCRCACHE;
6100Sstevel@tonic-gate     char		*lrealm;
6110Sstevel@tonic-gate     krb5_error_code	retval;
6120Sstevel@tonic-gate     krb5_enctype	menctype = ENCTYPE_UNKNOWN;
6130Sstevel@tonic-gate     kdc_realm_t		*rdatap;
6140Sstevel@tonic-gate     krb5_boolean	manual = FALSE;
6150Sstevel@tonic-gate     char		*default_udp_ports = 0;
6160Sstevel@tonic-gate     char		*default_tcp_ports = 0;
6170Sstevel@tonic-gate     krb5_pointer	aprof;
6180Sstevel@tonic-gate     const char		*hierarchy[3];
6190Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
6200Sstevel@tonic-gate     char                *v4mode = 0;
6210Sstevel@tonic-gate #endif
6220Sstevel@tonic-gate     extern char *optarg;
6230Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
6240Sstevel@tonic-gate     extern struct krb5_keytypes krb5_enctypes_list[];
6250Sstevel@tonic-gate     extern int krb5_enctypes_length;
6260Sstevel@tonic-gate #endif
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate     if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) {
6290Sstevel@tonic-gate 	hierarchy[0] = "kdcdefaults";
6300Sstevel@tonic-gate 	hierarchy[1] = "kdc_ports";
6310Sstevel@tonic-gate 	hierarchy[2] = (char *) NULL;
6320Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports))
6330Sstevel@tonic-gate 	    default_udp_ports = 0;
6340Sstevel@tonic-gate 	hierarchy[1] = "kdc_tcp_ports";
6350Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports))
6360Sstevel@tonic-gate 	    default_tcp_ports = 0;
6370Sstevel@tonic-gate 	hierarchy[1] = "kdc_max_tcp_connections";
6380Sstevel@tonic-gate 	if (krb5_aprof_get_int32(aprof, hierarchy, TRUE,
6390Sstevel@tonic-gate 		&max_tcp_data_connections)) {
6400Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
6410Sstevel@tonic-gate 	} else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) {
6420Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
6430Sstevel@tonic-gate 	}
6440Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
6450Sstevel@tonic-gate 	hierarchy[1] = "v4_mode";
6460Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
6470Sstevel@tonic-gate 	    v4mode = 0;
6480Sstevel@tonic-gate #endif
6490Sstevel@tonic-gate 	/* aprof_init can return 0 with aprof == NULL */
6500Sstevel@tonic-gate 	if (aprof)
6510Sstevel@tonic-gate 	     krb5_aprof_finish(aprof);
6520Sstevel@tonic-gate     }
6530Sstevel@tonic-gate     if (default_udp_ports == 0)
6540Sstevel@tonic-gate 	default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST);
6550Sstevel@tonic-gate     if (default_tcp_ports == 0)
6560Sstevel@tonic-gate 	default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST);
6570Sstevel@tonic-gate     /*
6580Sstevel@tonic-gate      * Loop through the option list.  Each time we encounter a realm name,
6590Sstevel@tonic-gate      * use the previously scanned options to fill in for defaults.
6600Sstevel@tonic-gate      */
6610Sstevel@tonic-gate     while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:n")) != -1) { /* SUNW */
6620Sstevel@tonic-gate 	switch(c) {
6630Sstevel@tonic-gate 	case 'r':			/* realm name for db */
6640Sstevel@tonic-gate 	    if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
6650Sstevel@tonic-gate 		if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
6660Sstevel@tonic-gate 		    if ((retval = init_realm(argv[0], rdatap, optarg, db_name,
6670Sstevel@tonic-gate 					     mkey_name, menctype,
6680Sstevel@tonic-gate 					     default_udp_ports,
6690Sstevel@tonic-gate 					     default_tcp_ports, manual))) {
6700Sstevel@tonic-gate 			fprintf(stderr,gettext("%s: cannot initialize realm %s\n"),
6710Sstevel@tonic-gate 				argv[0], optarg);
6720Sstevel@tonic-gate 			exit(1);
6730Sstevel@tonic-gate 		    }
6740Sstevel@tonic-gate 		    kdc_realmlist[kdc_numrealms] = rdatap;
6750Sstevel@tonic-gate 		    kdc_numrealms++;
6760Sstevel@tonic-gate 		}
6770Sstevel@tonic-gate 	    }
6780Sstevel@tonic-gate 	    break;
6790Sstevel@tonic-gate 	case 'd':			/* pathname for db */
6800Sstevel@tonic-gate 	    db_name = optarg;
6810Sstevel@tonic-gate 	    break;
6820Sstevel@tonic-gate 	case 'm':			/* manual type-in of master key */
6830Sstevel@tonic-gate 	    manual = TRUE;
6840Sstevel@tonic-gate 	    if (menctype == ENCTYPE_UNKNOWN)
6850Sstevel@tonic-gate 		menctype = ENCTYPE_DES_CBC_CRC;
6860Sstevel@tonic-gate 	    break;
6870Sstevel@tonic-gate 	case 'M':			/* master key name in DB */
6880Sstevel@tonic-gate 	    mkey_name = optarg;
6890Sstevel@tonic-gate 	    break;
6900Sstevel@tonic-gate 	case 'n':
6910Sstevel@tonic-gate 	    nofork++;			/* don't detach from terminal */
6920Sstevel@tonic-gate 	    break;
6930Sstevel@tonic-gate 	case 'k':			/* enctype for master key */
6940Sstevel@tonic-gate 	    if (krb5_string_to_enctype(optarg, &menctype))
6950Sstevel@tonic-gate 		com_err(argv[0], 0,
6960Sstevel@tonic-gate 		gettext("invalid enctype %s"), optarg);
6970Sstevel@tonic-gate 	    break;
6980Sstevel@tonic-gate 	case 'R':
6990Sstevel@tonic-gate 	    rcname = optarg;
7000Sstevel@tonic-gate 	    break;
7010Sstevel@tonic-gate 	case 'p':
7020Sstevel@tonic-gate 	    if (default_udp_ports)
7030Sstevel@tonic-gate 		free(default_udp_ports);
7040Sstevel@tonic-gate 	    default_udp_ports = strdup(optarg);
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	    if (default_tcp_ports)
7070Sstevel@tonic-gate 		free(default_tcp_ports);
7080Sstevel@tonic-gate 	    default_tcp_ports = strdup(optarg);
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	    break;
7110Sstevel@tonic-gate 	case '4':
7120Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7130Sstevel@tonic-gate 	    if (v4mode)
7140Sstevel@tonic-gate 		free(v4mode);
7150Sstevel@tonic-gate 	    v4mode = strdup(optarg);
7160Sstevel@tonic-gate #endif
7170Sstevel@tonic-gate 	    break;
7180Sstevel@tonic-gate 	case '3':
7190Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
7200Sstevel@tonic-gate 	    if (krb5_enctypes_list[krb5_enctypes_length-1].etype
7210Sstevel@tonic-gate 		!= ENCTYPE_LOCAL_DES3_HMAC_SHA1) {
7220Sstevel@tonic-gate 		fprintf(stderr,
7230Sstevel@tonic-gate 			"internal inconsistency in enctypes_list"
7240Sstevel@tonic-gate 			" while disabling\n"
7250Sstevel@tonic-gate 			"des3-marc-hmac-sha1 enctype\n");
7260Sstevel@tonic-gate 		exit(1);
7270Sstevel@tonic-gate 	    }
7280Sstevel@tonic-gate 	    krb5_enctypes_length--;
7290Sstevel@tonic-gate 	    break;
7300Sstevel@tonic-gate #endif
7310Sstevel@tonic-gate 	case '?':
7320Sstevel@tonic-gate 	default:
7330Sstevel@tonic-gate 	    usage(argv[0]);
7340Sstevel@tonic-gate 	    exit(1);
7350Sstevel@tonic-gate 	}
7360Sstevel@tonic-gate     }
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7390Sstevel@tonic-gate     /*
7400Sstevel@tonic-gate      * Setup the v4 mode
7410Sstevel@tonic-gate      */
7420Sstevel@tonic-gate     process_v4_mode(argv[0], v4mode);
7430Sstevel@tonic-gate #endif
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate     /*
7460Sstevel@tonic-gate      * Check to see if we processed any realms.
7470Sstevel@tonic-gate      */
7480Sstevel@tonic-gate     if (kdc_numrealms == 0) {
7490Sstevel@tonic-gate 	/* no realm specified, use default realm */
7500Sstevel@tonic-gate 	if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
7510Sstevel@tonic-gate 	    com_err(argv[0], retval,
7520Sstevel@tonic-gate 		gettext("while attempting to retrieve default realm"));
7530Sstevel@tonic-gate 	    exit(1);
7540Sstevel@tonic-gate 	}
7550Sstevel@tonic-gate 	if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
7560Sstevel@tonic-gate 	    if ((retval = init_realm(argv[0], rdatap, lrealm, db_name,
7570Sstevel@tonic-gate 				     mkey_name, menctype, default_udp_ports,
7580Sstevel@tonic-gate 				     default_tcp_ports, manual))) {
7590Sstevel@tonic-gate 		fprintf(stderr,
7600Sstevel@tonic-gate 			gettext("%s: cannot initialize realm %s\n"),
7610Sstevel@tonic-gate 			argv[0], lrealm);
7620Sstevel@tonic-gate 		exit(1);
7630Sstevel@tonic-gate 	    }
7640Sstevel@tonic-gate 	    kdc_realmlist[0] = rdatap;
7650Sstevel@tonic-gate 	    kdc_numrealms++;
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate     }
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate #ifdef USE_RCACHE
7700Sstevel@tonic-gate     /*
7710Sstevel@tonic-gate      * Now handle the replay cache.
7720Sstevel@tonic-gate      */
7730Sstevel@tonic-gate     if ((retval = kdc_initialize_rcache(kcontext, rcname))) {
7740Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing KDC replay cache"));
7750Sstevel@tonic-gate 	exit(1);
7760Sstevel@tonic-gate     }
7770Sstevel@tonic-gate #endif
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate     /* Ensure that this is set for our first request. */
7800Sstevel@tonic-gate     kdc_active_realm = kdc_realmlist[0];
7810Sstevel@tonic-gate     if (default_udp_ports)
7820Sstevel@tonic-gate 	free(default_udp_ports);
7830Sstevel@tonic-gate     if (default_tcp_ports)
7840Sstevel@tonic-gate 	free(default_tcp_ports);
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate     return;
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate void
7900Sstevel@tonic-gate finish_realms(prog)
7910Sstevel@tonic-gate     char *prog;
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate     int i;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate     for (i = 0; i < kdc_numrealms; i++) {
7960Sstevel@tonic-gate 	finish_realm(kdc_realmlist[i]);
7970Sstevel@tonic-gate 	kdc_realmlist[i] = 0;
7980Sstevel@tonic-gate     }
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate /*
8020Sstevel@tonic-gate  outline:
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate  process args & setup
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate  initialize database access (fetch master key, open DB)
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate  initialize network
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate  loop:
8110Sstevel@tonic-gate  	listen for packet
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	determine packet type, dispatch to handling routine
8140Sstevel@tonic-gate 		(AS or TGS (or V4?))
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	reflect response
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	exit on signal
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate  clean up secrets, close db
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate  shut down network
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate  exit
8250Sstevel@tonic-gate  */
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate int main(argc, argv)
8280Sstevel@tonic-gate      int argc;
8290Sstevel@tonic-gate      char *argv[];
8300Sstevel@tonic-gate {
8310Sstevel@tonic-gate     krb5_error_code	retval;
8320Sstevel@tonic-gate     krb5_context	kcontext;
8330Sstevel@tonic-gate     int			*port_list;
8340Sstevel@tonic-gate     int errout = 0;
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
8390Sstevel@tonic-gate #define	TEXT_DOMAIN	"KRB5KDC_TEST"	/* Use this only if it weren't */
8400Sstevel@tonic-gate #endif
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate     if (strrchr(argv[0], '/'))
8450Sstevel@tonic-gate 	argv[0] = strrchr(argv[0], '/')+1;
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate     if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) *
8480Sstevel@tonic-gate 						  KRB5_KDC_MAX_REALMS))) {
8490Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]);
8500Sstevel@tonic-gate 	exit(1);
8510Sstevel@tonic-gate     }
8520Sstevel@tonic-gate     memset((char *) kdc_realmlist, 0,
8530Sstevel@tonic-gate 	   (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));
8540Sstevel@tonic-gate     port_list = NULL;
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate     /*
8570Sstevel@tonic-gate      * A note about Kerberos contexts: This context, "kcontext", is used
8580Sstevel@tonic-gate      * for the KDC operations, i.e. setup, network connection and error
8590Sstevel@tonic-gate      * reporting.  The per-realm operations use the "realm_context"
8600Sstevel@tonic-gate      * associated with each realm.
8610Sstevel@tonic-gate      */
8620Sstevel@tonic-gate     retval = krb5_init_context(&kcontext);
8630Sstevel@tonic-gate     if (retval) {
8640Sstevel@tonic-gate 	    com_err(argv[0], retval, gettext("while initializing krb5"));
8650Sstevel@tonic-gate 	    exit(1);
8660Sstevel@tonic-gate     }
8670Sstevel@tonic-gate     krb5_klog_init(kcontext, "kdc", argv[0], 1);
8680Sstevel@tonic-gate     /* initialize_kdc5_error_table();  SUNWresync121 XXX */
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate     /*
8710Sstevel@tonic-gate      * Scan through the argument list
8720Sstevel@tonic-gate      */
8730Sstevel@tonic-gate     initialize_realms(kcontext, argc, argv);
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate     setup_signal_handlers();
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate     if (retval = setup_sam()) {
8780Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing SAM"));
8790Sstevel@tonic-gate 	finish_realms(argv[0]);
8800Sstevel@tonic-gate 	return 1;
8810Sstevel@tonic-gate     }
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate     if ((retval = setup_network(argv[0]))) {
8840Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing network"));
8850Sstevel@tonic-gate 	finish_realms(argv[0]);
8860Sstevel@tonic-gate 	return 1;
8870Sstevel@tonic-gate     }
8880Sstevel@tonic-gate     if (!nofork && daemon(0, 0)) {
8890Sstevel@tonic-gate 	com_err(argv[0], errno, gettext("while detaching from tty"));
8900Sstevel@tonic-gate 	finish_realms(argv[0]);
8910Sstevel@tonic-gate 	return 1;
8920Sstevel@tonic-gate     }
8930Sstevel@tonic-gate     if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) {
8940Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while logging message"));
8950Sstevel@tonic-gate 	errout++;
8960Sstevel@tonic-gate 	};
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate     if ((retval = listen_and_process(argv[0]))) {
8990Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while processing network requests"));
9000Sstevel@tonic-gate 	errout++;
9010Sstevel@tonic-gate     }
9020Sstevel@tonic-gate     if ((retval = closedown_network(argv[0]))) {
9030Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while shutting down network"));
9040Sstevel@tonic-gate 	errout++;
9050Sstevel@tonic-gate     }
9060Sstevel@tonic-gate     krb5_klog_syslog(LOG_INFO, "shutting down");
9070Sstevel@tonic-gate     krb5_klog_close(kdc_context);
9080Sstevel@tonic-gate     finish_realms(argv[0]);
9090Sstevel@tonic-gate     krb5_free_context(kcontext);
9100Sstevel@tonic-gate     return errout;
9110Sstevel@tonic-gate }
912