xref: /titanic_50/usr/src/cmd/krb5/krb5kdc/main.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate /*
9*7c478bd9Sstevel@tonic-gate  * kdc/main.c
10*7c478bd9Sstevel@tonic-gate  *
11*7c478bd9Sstevel@tonic-gate  * Copyright 1990,2001 by the Massachusetts Institute of Technology.
12*7c478bd9Sstevel@tonic-gate  *
13*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
14*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
15*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
16*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*7c478bd9Sstevel@tonic-gate  *
18*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
20*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
21*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
22*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
23*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
24*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
25*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
26*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
27*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
28*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
29*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
30*7c478bd9Sstevel@tonic-gate  * or implied warranty.
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * Main procedure body for the KDC server process.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include <stdio.h>
37*7c478bd9Sstevel@tonic-gate #include <syslog.h>
38*7c478bd9Sstevel@tonic-gate #include <signal.h>
39*7c478bd9Sstevel@tonic-gate #include <errno.h>
40*7c478bd9Sstevel@tonic-gate #include <netdb.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include "k5-int.h"
43*7c478bd9Sstevel@tonic-gate #include "com_err.h"
44*7c478bd9Sstevel@tonic-gate #include "adm.h"
45*7c478bd9Sstevel@tonic-gate #include "adm_proto.h"
46*7c478bd9Sstevel@tonic-gate #include "kdc_util.h"
47*7c478bd9Sstevel@tonic-gate #include "extern.h"
48*7c478bd9Sstevel@tonic-gate #include "kdc5_err.h"
49*7c478bd9Sstevel@tonic-gate #include <libintl.h>
50*7c478bd9Sstevel@tonic-gate #include <locale.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #ifdef HAVE_NETINET_IN_H
53*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
54*7c478bd9Sstevel@tonic-gate #endif
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate kdc_realm_t *find_realm_data PROTOTYPE((char *, krb5_ui_4));
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate void usage PROTOTYPE((char *));
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate krb5_sigtype request_exit PROTOTYPE((int));
61*7c478bd9Sstevel@tonic-gate krb5_sigtype request_hup  PROTOTYPE((int));
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate void setup_signal_handlers PROTOTYPE((void));
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate krb5_error_code setup_sam PROTOTYPE((void));
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate void initialize_realms PROTOTYPE((krb5_context, int, char **));
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate void finish_realms PROTOTYPE((char *));
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static int nofork = 0;
72*7c478bd9Sstevel@tonic-gate static int rkey_init_done = 0;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: global here that other functions access */
75*7c478bd9Sstevel@tonic-gate int max_tcp_data_connections;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGNALS
78*7c478bd9Sstevel@tonic-gate static struct sigaction s_action;
79*7c478bd9Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate #define	KRB5_KDC_MAX_REALMS	32
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /*
84*7c478bd9Sstevel@tonic-gate  * Find the realm entry for a given realm.
85*7c478bd9Sstevel@tonic-gate  */
86*7c478bd9Sstevel@tonic-gate kdc_realm_t *
87*7c478bd9Sstevel@tonic-gate find_realm_data(rname, rsize)
88*7c478bd9Sstevel@tonic-gate     char 	*rname;
89*7c478bd9Sstevel@tonic-gate     krb5_ui_4	rsize;
90*7c478bd9Sstevel@tonic-gate {
91*7c478bd9Sstevel@tonic-gate     int i;
92*7c478bd9Sstevel@tonic-gate     for (i=0; i<kdc_numrealms; i++) {
93*7c478bd9Sstevel@tonic-gate 	if ((rsize == strlen(kdc_realmlist[i]->realm_name)) &&
94*7c478bd9Sstevel@tonic-gate 	    !strncmp(rname, kdc_realmlist[i]->realm_name, rsize))
95*7c478bd9Sstevel@tonic-gate 	    return(kdc_realmlist[i]);
96*7c478bd9Sstevel@tonic-gate     }
97*7c478bd9Sstevel@tonic-gate     return((kdc_realm_t *) NULL);
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate krb5_error_code
101*7c478bd9Sstevel@tonic-gate setup_server_realm(sprinc)
102*7c478bd9Sstevel@tonic-gate     krb5_principal	sprinc;
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
105*7c478bd9Sstevel@tonic-gate     kdc_realm_t		*newrealm;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate     kret = 0;
108*7c478bd9Sstevel@tonic-gate     if (kdc_numrealms > 1) {
109*7c478bd9Sstevel@tonic-gate 	if (!(newrealm = find_realm_data(sprinc->realm.data,
110*7c478bd9Sstevel@tonic-gate 					 (krb5_ui_4) sprinc->realm.length)))
111*7c478bd9Sstevel@tonic-gate 	    kret = ENOENT;
112*7c478bd9Sstevel@tonic-gate 	else
113*7c478bd9Sstevel@tonic-gate 	    kdc_active_realm = newrealm;
114*7c478bd9Sstevel@tonic-gate     }
115*7c478bd9Sstevel@tonic-gate     else
116*7c478bd9Sstevel@tonic-gate 	kdc_active_realm = kdc_realmlist[0];
117*7c478bd9Sstevel@tonic-gate     return(kret);
118*7c478bd9Sstevel@tonic-gate }
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate static void
121*7c478bd9Sstevel@tonic-gate finish_realm(rdp)
122*7c478bd9Sstevel@tonic-gate     kdc_realm_t *rdp;
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate     if (rdp->realm_dbname)
125*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_dbname);
126*7c478bd9Sstevel@tonic-gate     if (rdp->realm_mpname)
127*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_mpname);
128*7c478bd9Sstevel@tonic-gate     if (rdp->realm_stash)
129*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_stash);
130*7c478bd9Sstevel@tonic-gate     if (rdp->realm_ports)
131*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_ports);
132*7c478bd9Sstevel@tonic-gate     if (rdp->realm_tcp_ports)
133*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_tcp_ports);
134*7c478bd9Sstevel@tonic-gate     if (rdp->realm_kstypes)
135*7c478bd9Sstevel@tonic-gate 	free(rdp->realm_kstypes);
136*7c478bd9Sstevel@tonic-gate     if (rdp->realm_keytab)
137*7c478bd9Sstevel@tonic-gate 	krb5_kt_close(rdp->realm_context, rdp->realm_keytab);
138*7c478bd9Sstevel@tonic-gate     if (rdp->realm_context) {
139*7c478bd9Sstevel@tonic-gate 	if (rdp->realm_mprinc)
140*7c478bd9Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
141*7c478bd9Sstevel@tonic-gate 	if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
142*7c478bd9Sstevel@tonic-gate 	    memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
143*7c478bd9Sstevel@tonic-gate 	    free(rdp->realm_mkey.contents);
144*7c478bd9Sstevel@tonic-gate 	}
145*7c478bd9Sstevel@tonic-gate 	if (rdp->realm_tgskey.length && rdp->realm_tgskey.contents) {
146*7c478bd9Sstevel@tonic-gate 	    memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length);
147*7c478bd9Sstevel@tonic-gate 	    free(rdp->realm_tgskey.contents);
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 	krb5_db_fini(rdp->realm_context);
150*7c478bd9Sstevel@tonic-gate 	if (rdp->realm_tgsprinc)
151*7c478bd9Sstevel@tonic-gate 	    krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
152*7c478bd9Sstevel@tonic-gate 	krb5_free_context(rdp->realm_context);
153*7c478bd9Sstevel@tonic-gate     }
154*7c478bd9Sstevel@tonic-gate     free(rdp);
155*7c478bd9Sstevel@tonic-gate }
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate /*
158*7c478bd9Sstevel@tonic-gate  * Initialize a realm control structure from the alternate profile or from
159*7c478bd9Sstevel@tonic-gate  * the specified defaults.
160*7c478bd9Sstevel@tonic-gate  *
161*7c478bd9Sstevel@tonic-gate  * After we're complete here, the essence of the realm is embodied in the
162*7c478bd9Sstevel@tonic-gate  * realm data and we should be all set to begin operation for that realm.
163*7c478bd9Sstevel@tonic-gate  */
164*7c478bd9Sstevel@tonic-gate static krb5_error_code
165*7c478bd9Sstevel@tonic-gate init_realm(progname, rdp, realm, def_dbname, def_mpname,
166*7c478bd9Sstevel@tonic-gate 		 def_enctype, def_udp_ports, def_tcp_ports, def_manual)
167*7c478bd9Sstevel@tonic-gate     char		*progname;
168*7c478bd9Sstevel@tonic-gate     kdc_realm_t		*rdp;
169*7c478bd9Sstevel@tonic-gate     char		*realm;
170*7c478bd9Sstevel@tonic-gate     char		*def_dbname;
171*7c478bd9Sstevel@tonic-gate     char		*def_mpname;
172*7c478bd9Sstevel@tonic-gate     krb5_enctype	def_enctype;
173*7c478bd9Sstevel@tonic-gate     char		*def_udp_ports;
174*7c478bd9Sstevel@tonic-gate     char		*def_tcp_ports;
175*7c478bd9Sstevel@tonic-gate     krb5_boolean	def_manual;
176*7c478bd9Sstevel@tonic-gate {
177*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
178*7c478bd9Sstevel@tonic-gate     krb5_boolean	manual;
179*7c478bd9Sstevel@tonic-gate     krb5_db_entry	db_entry;
180*7c478bd9Sstevel@tonic-gate     int			num2get;
181*7c478bd9Sstevel@tonic-gate     krb5_boolean	more;
182*7c478bd9Sstevel@tonic-gate     krb5_boolean	db_inited;
183*7c478bd9Sstevel@tonic-gate     krb5_realm_params	*rparams;
184*7c478bd9Sstevel@tonic-gate     krb5_key_data	*kdata;
185*7c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple	*kslist;
186*7c478bd9Sstevel@tonic-gate     krb5_int32		nkslist;
187*7c478bd9Sstevel@tonic-gate     int			i;
188*7c478bd9Sstevel@tonic-gate     krb5_deltat		now, krb5_kdb_max_time;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate     db_inited = 0;
191*7c478bd9Sstevel@tonic-gate     memset((char *) rdp, 0, sizeof(kdc_realm_t));
192*7c478bd9Sstevel@tonic-gate     if (!realm) {
193*7c478bd9Sstevel@tonic-gate 	kret = EINVAL;
194*7c478bd9Sstevel@tonic-gate 	goto whoops;
195*7c478bd9Sstevel@tonic-gate     }
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate     rdp->realm_name = realm;
198*7c478bd9Sstevel@tonic-gate     kret = krb5_init_context(&rdp->realm_context);
199*7c478bd9Sstevel@tonic-gate     if (kret) {
200*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting context for realm %s"),
201*7c478bd9Sstevel@tonic-gate 		realm);
202*7c478bd9Sstevel@tonic-gate 	goto whoops;
203*7c478bd9Sstevel@tonic-gate     }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate     kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name,
206*7c478bd9Sstevel@tonic-gate 				  (char *) NULL, (char *) NULL, &rparams);
207*7c478bd9Sstevel@tonic-gate     if (kret) {
208*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while reading realm parameters"));
209*7c478bd9Sstevel@tonic-gate 	goto whoops;
210*7c478bd9Sstevel@tonic-gate     }
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate     /* Handle profile file name */
213*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_profile)
214*7c478bd9Sstevel@tonic-gate 	rdp->realm_profile = strdup(rparams->realm_profile);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate     /* Handle database name */
217*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_dbname)
218*7c478bd9Sstevel@tonic-gate 	rdp->realm_dbname = strdup(rparams->realm_dbname);
219*7c478bd9Sstevel@tonic-gate     else
220*7c478bd9Sstevel@tonic-gate 	rdp->realm_dbname = (def_dbname) ? strdup(def_dbname) :
221*7c478bd9Sstevel@tonic-gate 	    strdup(DEFAULT_KDB_FILE);
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate     /* Handle master key name */
224*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_mkey_name)
225*7c478bd9Sstevel@tonic-gate 	rdp->realm_mpname = strdup(rparams->realm_mkey_name);
226*7c478bd9Sstevel@tonic-gate     else
227*7c478bd9Sstevel@tonic-gate 	rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) :
228*7c478bd9Sstevel@tonic-gate 	    strdup(KRB5_KDB_M_NAME);
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate     /* Handle KDC ports */
231*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_ports)
232*7c478bd9Sstevel@tonic-gate 	rdp->realm_ports = strdup(rparams->realm_kdc_ports);
233*7c478bd9Sstevel@tonic-gate     else
234*7c478bd9Sstevel@tonic-gate 	rdp->realm_ports = strdup(def_udp_ports);
235*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_kdc_tcp_ports)
236*7c478bd9Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports);
237*7c478bd9Sstevel@tonic-gate     else
238*7c478bd9Sstevel@tonic-gate 	rdp->realm_tcp_ports = strdup(def_tcp_ports);
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate     /* Handle stash file */
241*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_stash_file) {
242*7c478bd9Sstevel@tonic-gate 	rdp->realm_stash = strdup(rparams->realm_stash_file);
243*7c478bd9Sstevel@tonic-gate 	manual = FALSE;
244*7c478bd9Sstevel@tonic-gate     } else
245*7c478bd9Sstevel@tonic-gate 	manual = def_manual;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate     /* Handle master key type */
248*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_enctype_valid)
249*7c478bd9Sstevel@tonic-gate 	rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
250*7c478bd9Sstevel@tonic-gate     else
251*7c478bd9Sstevel@tonic-gate 	rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN;
252*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_timeofday(rdp->realm_context, &now))) {
253*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while getting timeofday"));
254*7c478bd9Sstevel@tonic-gate 	goto whoops;
255*7c478bd9Sstevel@tonic-gate     }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate     /* Handle ticket maximum life */
258*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_max_life_valid)
259*7c478bd9Sstevel@tonic-gate    	rdp->realm_maxlife = rparams->realm_max_life;
260*7c478bd9Sstevel@tonic-gate     else
261*7c478bd9Sstevel@tonic-gate 	rdp->realm_maxlife = KRB5_KDB_EXPIRATION - now - 3600;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate     /* Handle ticket renewable maximum life */
264*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_max_rlife_valid)
265*7c478bd9Sstevel@tonic-gate    	rdp->realm_maxrlife = rparams->realm_max_rlife;
266*7c478bd9Sstevel@tonic-gate     else
267*7c478bd9Sstevel@tonic-gate    	rdp->realm_maxrlife = KRB5_KDB_EXPIRATION - now - 3600;
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate     /* Handle key/salt list */
270*7c478bd9Sstevel@tonic-gate     if (rparams && rparams->realm_num_keysalts) {
271*7c478bd9Sstevel@tonic-gate 	rdp->realm_kstypes = rparams->realm_keysalts;
272*7c478bd9Sstevel@tonic-gate 	rdp->realm_nkstypes = rparams->realm_num_keysalts;
273*7c478bd9Sstevel@tonic-gate 	rparams->realm_keysalts = NULL;
274*7c478bd9Sstevel@tonic-gate 	rparams->realm_num_keysalts = 0;
275*7c478bd9Sstevel@tonic-gate 	kslist = (krb5_key_salt_tuple *) rdp->realm_kstypes;
276*7c478bd9Sstevel@tonic-gate 	nkslist = rdp->realm_nkstypes;
277*7c478bd9Sstevel@tonic-gate     } else {
278*7c478bd9Sstevel@tonic-gate 	/*
279*7c478bd9Sstevel@tonic-gate 	 * XXX  Initialize default key/salt list.
280*7c478bd9Sstevel@tonic-gate 	 */
281*7c478bd9Sstevel@tonic-gate 	if ((kslist = (krb5_key_salt_tuple *)
282*7c478bd9Sstevel@tonic-gate 	     malloc(sizeof(krb5_key_salt_tuple)))) {
283*7c478bd9Sstevel@tonic-gate 	    kslist->ks_enctype = ENCTYPE_DES_CBC_CRC;
284*7c478bd9Sstevel@tonic-gate 	    kslist->ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
285*7c478bd9Sstevel@tonic-gate 	    rdp->realm_kstypes = kslist;
286*7c478bd9Sstevel@tonic-gate 	    rdp->realm_nkstypes = 1;
287*7c478bd9Sstevel@tonic-gate 	    nkslist = 1;
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 	else {
290*7c478bd9Sstevel@tonic-gate 	    com_err(progname, ENOMEM,
291*7c478bd9Sstevel@tonic-gate 		    gettext("while setting up key/salt list for realm %s"),
292*7c478bd9Sstevel@tonic-gate 		    realm);
293*7c478bd9Sstevel@tonic-gate 	    exit(1);
294*7c478bd9Sstevel@tonic-gate 	}
295*7c478bd9Sstevel@tonic-gate     }
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate     if (rparams)
298*7c478bd9Sstevel@tonic-gate 	krb5_free_realm_params(rdp->realm_context, rparams);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate     /*
301*7c478bd9Sstevel@tonic-gate      * We've got our parameters, now go and setup our realm context.
302*7c478bd9Sstevel@tonic-gate      */
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate     /* Set the default realm of this context */
305*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) {
306*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret, gettext("while setting default realm to %s"),
307*7c478bd9Sstevel@tonic-gate 		realm);
308*7c478bd9Sstevel@tonic-gate 	goto whoops;
309*7c478bd9Sstevel@tonic-gate     }
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate     /* Assemble and parse the master key name */
312*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname,
313*7c478bd9Sstevel@tonic-gate 					rdp->realm_name, (char **) NULL,
314*7c478bd9Sstevel@tonic-gate 					&rdp->realm_mprinc))) {
315*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
316*7c478bd9Sstevel@tonic-gate 		gettext("while setting up master key name %s for realm %s"),
317*7c478bd9Sstevel@tonic-gate 		rdp->realm_mpname, realm);
318*7c478bd9Sstevel@tonic-gate 	goto whoops;
319*7c478bd9Sstevel@tonic-gate     }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate     /*
322*7c478bd9Sstevel@tonic-gate      * Get the master key.
323*7c478bd9Sstevel@tonic-gate      */
324*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
325*7c478bd9Sstevel@tonic-gate 				   rdp->realm_mkey.enctype, manual,
326*7c478bd9Sstevel@tonic-gate 				   FALSE, rdp->realm_stash,
327*7c478bd9Sstevel@tonic-gate 				   0, &rdp->realm_mkey))) {
328*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
329*7c478bd9Sstevel@tonic-gate 		gettext("while fetching master key %s for realm %s"),
330*7c478bd9Sstevel@tonic-gate 		rdp->realm_mpname, realm);
331*7c478bd9Sstevel@tonic-gate 	goto whoops;
332*7c478bd9Sstevel@tonic-gate     }
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate     /* Set and open the database. */
335*7c478bd9Sstevel@tonic-gate     if (rdp->realm_dbname &&
336*7c478bd9Sstevel@tonic-gate 	(kret = krb5_db_set_name(rdp->realm_context, rdp->realm_dbname))) {
337*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
338*7c478bd9Sstevel@tonic-gate 		gettext("while setting database name to %s for realm %s"),
339*7c478bd9Sstevel@tonic-gate 		rdp->realm_dbname, realm);
340*7c478bd9Sstevel@tonic-gate 	goto whoops;
341*7c478bd9Sstevel@tonic-gate     }
342*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_init(rdp->realm_context))) {
343*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
344*7c478bd9Sstevel@tonic-gate 		gettext("while initializing database "),
345*7c478bd9Sstevel@tonic-gate 		gettext("for realm %s"), realm);
346*7c478bd9Sstevel@tonic-gate 	goto whoops;
347*7c478bd9Sstevel@tonic-gate     } else
348*7c478bd9Sstevel@tonic-gate 	db_inited = 1;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate     /* Verify the master key */
351*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_verify_master_key(rdp->realm_context,
352*7c478bd9Sstevel@tonic-gate 					  rdp->realm_mprinc,
353*7c478bd9Sstevel@tonic-gate 					  &rdp->realm_mkey))) {
354*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
355*7c478bd9Sstevel@tonic-gate 		gettext("while verifying master key for realm %s"),
356*7c478bd9Sstevel@tonic-gate 		realm);
357*7c478bd9Sstevel@tonic-gate 	goto whoops;
358*7c478bd9Sstevel@tonic-gate     }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate     /* Fetch the master key and get its version number */
361*7c478bd9Sstevel@tonic-gate     num2get = 1;
362*7c478bd9Sstevel@tonic-gate     kret = krb5_db_get_principal(rdp->realm_context, rdp->realm_mprinc,
363*7c478bd9Sstevel@tonic-gate 				 &db_entry, &num2get, &more);
364*7c478bd9Sstevel@tonic-gate     if (!kret) {
365*7c478bd9Sstevel@tonic-gate 	if (num2get != 1)
366*7c478bd9Sstevel@tonic-gate 	    kret = KRB5_KDB_NOMASTERKEY;
367*7c478bd9Sstevel@tonic-gate 	else {
368*7c478bd9Sstevel@tonic-gate 	    if (more) {
369*7c478bd9Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
370*7c478bd9Sstevel@tonic-gate 				       &db_entry,
371*7c478bd9Sstevel@tonic-gate 				       num2get);
372*7c478bd9Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
373*7c478bd9Sstevel@tonic-gate 	    }
374*7c478bd9Sstevel@tonic-gate 	}
375*7c478bd9Sstevel@tonic-gate     }
376*7c478bd9Sstevel@tonic-gate     if (kret) {
377*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
378*7c478bd9Sstevel@tonic-gate 		gettext("while fetching master entry for realm %s"),
379*7c478bd9Sstevel@tonic-gate 		realm);
380*7c478bd9Sstevel@tonic-gate 	goto whoops;
381*7c478bd9Sstevel@tonic-gate     }
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate     /*
384*7c478bd9Sstevel@tonic-gate      * Get the most recent master key.  Search the key list in
385*7c478bd9Sstevel@tonic-gate      * the order specified by the key/salt list.
386*7c478bd9Sstevel@tonic-gate      */
387*7c478bd9Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
388*7c478bd9Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
389*7c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
390*7c478bd9Sstevel@tonic-gate 					   &db_entry,
391*7c478bd9Sstevel@tonic-gate 					   kslist[i].ks_enctype,
392*7c478bd9Sstevel@tonic-gate 					   -1,
393*7c478bd9Sstevel@tonic-gate 					   -1,
394*7c478bd9Sstevel@tonic-gate 					   &kdata)))
395*7c478bd9Sstevel@tonic-gate 	    break;
396*7c478bd9Sstevel@tonic-gate     }
397*7c478bd9Sstevel@tonic-gate     if (!kdata) {
398*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
399*7c478bd9Sstevel@tonic-gate 		gettext("while finding master key for realm %s"),
400*7c478bd9Sstevel@tonic-gate 		realm);
401*7c478bd9Sstevel@tonic-gate 	goto whoops;
402*7c478bd9Sstevel@tonic-gate     }
403*7c478bd9Sstevel@tonic-gate     rdp->realm_mkvno = kdata->key_data_kvno;
404*7c478bd9Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context, &db_entry, num2get);
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) {
407*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
408*7c478bd9Sstevel@tonic-gate 		gettext("while processing master key for realm %s"),
409*7c478bd9Sstevel@tonic-gate 		realm);
410*7c478bd9Sstevel@tonic-gate 	goto whoops;
411*7c478bd9Sstevel@tonic-gate     }
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate     /* Set up the keytab */
414*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_ktkdb_resolve(rdp->realm_context,
415*7c478bd9Sstevel@tonic-gate 				   NULL,
416*7c478bd9Sstevel@tonic-gate 				   &rdp->realm_keytab))) {
417*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
418*7c478bd9Sstevel@tonic-gate 		gettext("while resolving kdb keytab for realm %s"),
419*7c478bd9Sstevel@tonic-gate 		realm);
420*7c478bd9Sstevel@tonic-gate 	goto whoops;
421*7c478bd9Sstevel@tonic-gate     }
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate     /* Preformat the TGS name */
424*7c478bd9Sstevel@tonic-gate     if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc,
425*7c478bd9Sstevel@tonic-gate 				     strlen(realm), realm, KRB5_TGS_NAME,
426*7c478bd9Sstevel@tonic-gate 				     realm, (char *) NULL))) {
427*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
428*7c478bd9Sstevel@tonic-gate 		gettext("while building TGS name for realm %s"),
429*7c478bd9Sstevel@tonic-gate 		realm);
430*7c478bd9Sstevel@tonic-gate 	goto whoops;
431*7c478bd9Sstevel@tonic-gate     }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate     /* Get the TGS database entry */
434*7c478bd9Sstevel@tonic-gate     num2get = 1;
435*7c478bd9Sstevel@tonic-gate     if (!(kret = krb5_db_get_principal(rdp->realm_context,
436*7c478bd9Sstevel@tonic-gate 				       rdp->realm_tgsprinc,
437*7c478bd9Sstevel@tonic-gate 				       &db_entry,
438*7c478bd9Sstevel@tonic-gate 				       &num2get,
439*7c478bd9Sstevel@tonic-gate 				       &more))) {
440*7c478bd9Sstevel@tonic-gate 	if (num2get != 1)
441*7c478bd9Sstevel@tonic-gate 	    kret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
442*7c478bd9Sstevel@tonic-gate 	else {
443*7c478bd9Sstevel@tonic-gate 	    if (more) {
444*7c478bd9Sstevel@tonic-gate 		krb5_db_free_principal(rdp->realm_context,
445*7c478bd9Sstevel@tonic-gate 				       &db_entry,
446*7c478bd9Sstevel@tonic-gate 				       num2get);
447*7c478bd9Sstevel@tonic-gate 		kret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
448*7c478bd9Sstevel@tonic-gate 	    }
449*7c478bd9Sstevel@tonic-gate 	}
450*7c478bd9Sstevel@tonic-gate     }
451*7c478bd9Sstevel@tonic-gate     if (kret) {
452*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
453*7c478bd9Sstevel@tonic-gate 		gettext("while fetching TGS entry for realm %s"),
454*7c478bd9Sstevel@tonic-gate 		realm);
455*7c478bd9Sstevel@tonic-gate 	goto whoops;
456*7c478bd9Sstevel@tonic-gate     }
457*7c478bd9Sstevel@tonic-gate     /*
458*7c478bd9Sstevel@tonic-gate      * Get the most recent TGS key.  Search the key list in
459*7c478bd9Sstevel@tonic-gate      * the order specified by the key/salt list.
460*7c478bd9Sstevel@tonic-gate      */
461*7c478bd9Sstevel@tonic-gate     kdata = (krb5_key_data *) NULL;
462*7c478bd9Sstevel@tonic-gate     for (i=0; i<nkslist; i++) {
463*7c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_dbe_find_enctype(rdp->realm_context,
464*7c478bd9Sstevel@tonic-gate 					   &db_entry,
465*7c478bd9Sstevel@tonic-gate 					   kslist[i].ks_enctype,
466*7c478bd9Sstevel@tonic-gate 					   -1,
467*7c478bd9Sstevel@tonic-gate 					   -1,
468*7c478bd9Sstevel@tonic-gate 					   &kdata)))
469*7c478bd9Sstevel@tonic-gate 	    break;
470*7c478bd9Sstevel@tonic-gate     }
471*7c478bd9Sstevel@tonic-gate     if (!kdata) {
472*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
473*7c478bd9Sstevel@tonic-gate 		gettext("while finding TGS key for realm %s"),
474*7c478bd9Sstevel@tonic-gate 		realm);
475*7c478bd9Sstevel@tonic-gate 	goto whoops;
476*7c478bd9Sstevel@tonic-gate     }
477*7c478bd9Sstevel@tonic-gate     if (!(kret = krb5_dbekd_decrypt_key_data(rdp->realm_context,
478*7c478bd9Sstevel@tonic-gate 					     &rdp->realm_mkey,
479*7c478bd9Sstevel@tonic-gate 					     kdata,
480*7c478bd9Sstevel@tonic-gate 					     &rdp->realm_tgskey, NULL))){
481*7c478bd9Sstevel@tonic-gate 	rdp->realm_tgskvno = kdata->key_data_kvno;
482*7c478bd9Sstevel@tonic-gate     }
483*7c478bd9Sstevel@tonic-gate     krb5_db_free_principal(rdp->realm_context,
484*7c478bd9Sstevel@tonic-gate 			   &db_entry,
485*7c478bd9Sstevel@tonic-gate 			   num2get);
486*7c478bd9Sstevel@tonic-gate     if (kret) {
487*7c478bd9Sstevel@tonic-gate 	com_err(progname, kret,
488*7c478bd9Sstevel@tonic-gate 		gettext("while decrypting TGS key for realm %s"),
489*7c478bd9Sstevel@tonic-gate 		realm);
490*7c478bd9Sstevel@tonic-gate 	goto whoops;
491*7c478bd9Sstevel@tonic-gate     }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate     if (!rkey_init_done) {
494*7c478bd9Sstevel@tonic-gate 	krb5_timestamp now;
495*7c478bd9Sstevel@tonic-gate 	krb5_data seed;
496*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
497*7c478bd9Sstevel@tonic-gate 	krb5_keyblock temp_key;
498*7c478bd9Sstevel@tonic-gate #endif
499*7c478bd9Sstevel@tonic-gate 	/*
500*7c478bd9Sstevel@tonic-gate 	 * If all that worked, then initialize the random key
501*7c478bd9Sstevel@tonic-gate 	 * generators.
502*7c478bd9Sstevel@tonic-gate 	 */
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	if ((kret = krb5_timeofday(rdp->realm_context, &now)))
505*7c478bd9Sstevel@tonic-gate 	    goto whoops;
506*7c478bd9Sstevel@tonic-gate 	seed.length = sizeof(now);
507*7c478bd9Sstevel@tonic-gate 	seed.data = (char *) &now;
508*7c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
509*7c478bd9Sstevel@tonic-gate 	    goto whoops;
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	seed.length = rdp->realm_mkey.length;
512*7c478bd9Sstevel@tonic-gate 	seed.data = (char *)rdp->realm_mkey.contents;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_random_seed(rdp->realm_context, &seed)))
515*7c478bd9Sstevel@tonic-gate 	    goto whoops;
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
518*7c478bd9Sstevel@tonic-gate 	if ((kret = krb5_c_make_random_key(rdp->realm_context,
519*7c478bd9Sstevel@tonic-gate 					   ENCTYPE_DES_CBC_CRC, &temp_key))) {
520*7c478bd9Sstevel@tonic-gate 	    com_err(progname, kret,
521*7c478bd9Sstevel@tonic-gate 		    "while initializing V4 random key generator");
522*7c478bd9Sstevel@tonic-gate 	    goto whoops;
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	(void) des_init_random_number_generator(temp_key.contents);
526*7c478bd9Sstevel@tonic-gate 	krb5_free_keyblock_contents(rdp->realm_context, &temp_key);
527*7c478bd9Sstevel@tonic-gate #endif
528*7c478bd9Sstevel@tonic-gate 	rkey_init_done = 1;
529*7c478bd9Sstevel@tonic-gate     }
530*7c478bd9Sstevel@tonic-gate  whoops:
531*7c478bd9Sstevel@tonic-gate     /*
532*7c478bd9Sstevel@tonic-gate      * If we choked, then clean up any dirt we may have dropped on the floor.
533*7c478bd9Sstevel@tonic-gate      */
534*7c478bd9Sstevel@tonic-gate     if (kret) {
535*7c478bd9Sstevel@tonic-gate 	finish_realm(rdp);
536*7c478bd9Sstevel@tonic-gate     }
537*7c478bd9Sstevel@tonic-gate     return(kret);
538*7c478bd9Sstevel@tonic-gate }
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate krb5_sigtype
541*7c478bd9Sstevel@tonic-gate request_exit(signo)
542*7c478bd9Sstevel@tonic-gate     int signo;
543*7c478bd9Sstevel@tonic-gate {
544*7c478bd9Sstevel@tonic-gate     signal_requests_exit = 1;
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
547*7c478bd9Sstevel@tonic-gate     return;
548*7c478bd9Sstevel@tonic-gate #else
549*7c478bd9Sstevel@tonic-gate     return(0);
550*7c478bd9Sstevel@tonic-gate #endif
551*7c478bd9Sstevel@tonic-gate }
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate krb5_sigtype
554*7c478bd9Sstevel@tonic-gate request_hup(signo)
555*7c478bd9Sstevel@tonic-gate     int signo;
556*7c478bd9Sstevel@tonic-gate {
557*7c478bd9Sstevel@tonic-gate     signal_requests_hup = 1;
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGTYPE
560*7c478bd9Sstevel@tonic-gate     return;
561*7c478bd9Sstevel@tonic-gate #else
562*7c478bd9Sstevel@tonic-gate     return(0);
563*7c478bd9Sstevel@tonic-gate #endif
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate void
567*7c478bd9Sstevel@tonic-gate setup_signal_handlers()
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGNALS
570*7c478bd9Sstevel@tonic-gate     (void) sigemptyset(&s_action.sa_mask);
571*7c478bd9Sstevel@tonic-gate     s_action.sa_flags = 0;
572*7c478bd9Sstevel@tonic-gate     s_action.sa_handler = request_exit;
573*7c478bd9Sstevel@tonic-gate     (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
574*7c478bd9Sstevel@tonic-gate     (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
575*7c478bd9Sstevel@tonic-gate     s_action.sa_handler = request_hup;
576*7c478bd9Sstevel@tonic-gate     (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL);
577*7c478bd9Sstevel@tonic-gate #else  /* POSIX_SIGNALS */
578*7c478bd9Sstevel@tonic-gate     signal(SIGINT, request_exit);
579*7c478bd9Sstevel@tonic-gate     signal(SIGTERM, request_exit);
580*7c478bd9Sstevel@tonic-gate     signal(SIGHUP, request_hup);
581*7c478bd9Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate     return;
584*7c478bd9Sstevel@tonic-gate }
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate krb5_error_code
587*7c478bd9Sstevel@tonic-gate setup_sam()
588*7c478bd9Sstevel@tonic-gate {
589*7c478bd9Sstevel@tonic-gate     return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key);
590*7c478bd9Sstevel@tonic-gate }
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate void
593*7c478bd9Sstevel@tonic-gate usage(name)
594*7c478bd9Sstevel@tonic-gate char *name;
595*7c478bd9Sstevel@tonic-gate {
596*7c478bd9Sstevel@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);
597*7c478bd9Sstevel@tonic-gate     return;
598*7c478bd9Sstevel@tonic-gate }
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate void
601*7c478bd9Sstevel@tonic-gate initialize_realms(kcontext, argc, argv)
602*7c478bd9Sstevel@tonic-gate     krb5_context 	kcontext;
603*7c478bd9Sstevel@tonic-gate     int			argc;
604*7c478bd9Sstevel@tonic-gate     char		**argv;
605*7c478bd9Sstevel@tonic-gate {
606*7c478bd9Sstevel@tonic-gate     int 		c;
607*7c478bd9Sstevel@tonic-gate     char		*db_name = (char *) NULL;
608*7c478bd9Sstevel@tonic-gate     char		*mkey_name = (char *) NULL;
609*7c478bd9Sstevel@tonic-gate     char		*rcname = KDCRCACHE;
610*7c478bd9Sstevel@tonic-gate     char		*lrealm;
611*7c478bd9Sstevel@tonic-gate     krb5_error_code	retval;
612*7c478bd9Sstevel@tonic-gate     krb5_enctype	menctype = ENCTYPE_UNKNOWN;
613*7c478bd9Sstevel@tonic-gate     kdc_realm_t		*rdatap;
614*7c478bd9Sstevel@tonic-gate     krb5_boolean	manual = FALSE;
615*7c478bd9Sstevel@tonic-gate     char		*default_udp_ports = 0;
616*7c478bd9Sstevel@tonic-gate     char		*default_tcp_ports = 0;
617*7c478bd9Sstevel@tonic-gate     krb5_pointer	aprof;
618*7c478bd9Sstevel@tonic-gate     const char		*hierarchy[3];
619*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
620*7c478bd9Sstevel@tonic-gate     char                *v4mode = 0;
621*7c478bd9Sstevel@tonic-gate #endif
622*7c478bd9Sstevel@tonic-gate     extern char *optarg;
623*7c478bd9Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
624*7c478bd9Sstevel@tonic-gate     extern struct krb5_keytypes krb5_enctypes_list[];
625*7c478bd9Sstevel@tonic-gate     extern int krb5_enctypes_length;
626*7c478bd9Sstevel@tonic-gate #endif
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate     if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) {
629*7c478bd9Sstevel@tonic-gate 	hierarchy[0] = "kdcdefaults";
630*7c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_ports";
631*7c478bd9Sstevel@tonic-gate 	hierarchy[2] = (char *) NULL;
632*7c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports))
633*7c478bd9Sstevel@tonic-gate 	    default_udp_ports = 0;
634*7c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_tcp_ports";
635*7c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports))
636*7c478bd9Sstevel@tonic-gate 	    default_tcp_ports = 0;
637*7c478bd9Sstevel@tonic-gate 	hierarchy[1] = "kdc_max_tcp_connections";
638*7c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_int32(aprof, hierarchy, TRUE,
639*7c478bd9Sstevel@tonic-gate 		&max_tcp_data_connections)) {
640*7c478bd9Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
641*7c478bd9Sstevel@tonic-gate 	} else if (max_tcp_data_connections < MIN_KDC_TCP_CONNECTIONS) {
642*7c478bd9Sstevel@tonic-gate 	    max_tcp_data_connections = DEFAULT_KDC_TCP_CONNECTIONS;
643*7c478bd9Sstevel@tonic-gate 	}
644*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
645*7c478bd9Sstevel@tonic-gate 	hierarchy[1] = "v4_mode";
646*7c478bd9Sstevel@tonic-gate 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
647*7c478bd9Sstevel@tonic-gate 	    v4mode = 0;
648*7c478bd9Sstevel@tonic-gate #endif
649*7c478bd9Sstevel@tonic-gate 	/* aprof_init can return 0 with aprof == NULL */
650*7c478bd9Sstevel@tonic-gate 	if (aprof)
651*7c478bd9Sstevel@tonic-gate 	     krb5_aprof_finish(aprof);
652*7c478bd9Sstevel@tonic-gate     }
653*7c478bd9Sstevel@tonic-gate     if (default_udp_ports == 0)
654*7c478bd9Sstevel@tonic-gate 	default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST);
655*7c478bd9Sstevel@tonic-gate     if (default_tcp_ports == 0)
656*7c478bd9Sstevel@tonic-gate 	default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST);
657*7c478bd9Sstevel@tonic-gate     /*
658*7c478bd9Sstevel@tonic-gate      * Loop through the option list.  Each time we encounter a realm name,
659*7c478bd9Sstevel@tonic-gate      * use the previously scanned options to fill in for defaults.
660*7c478bd9Sstevel@tonic-gate      */
661*7c478bd9Sstevel@tonic-gate     while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:n")) != -1) { /* SUNW */
662*7c478bd9Sstevel@tonic-gate 	switch(c) {
663*7c478bd9Sstevel@tonic-gate 	case 'r':			/* realm name for db */
664*7c478bd9Sstevel@tonic-gate 	    if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
665*7c478bd9Sstevel@tonic-gate 		if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
666*7c478bd9Sstevel@tonic-gate 		    if ((retval = init_realm(argv[0], rdatap, optarg, db_name,
667*7c478bd9Sstevel@tonic-gate 					     mkey_name, menctype,
668*7c478bd9Sstevel@tonic-gate 					     default_udp_ports,
669*7c478bd9Sstevel@tonic-gate 					     default_tcp_ports, manual))) {
670*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,gettext("%s: cannot initialize realm %s\n"),
671*7c478bd9Sstevel@tonic-gate 				argv[0], optarg);
672*7c478bd9Sstevel@tonic-gate 			exit(1);
673*7c478bd9Sstevel@tonic-gate 		    }
674*7c478bd9Sstevel@tonic-gate 		    kdc_realmlist[kdc_numrealms] = rdatap;
675*7c478bd9Sstevel@tonic-gate 		    kdc_numrealms++;
676*7c478bd9Sstevel@tonic-gate 		}
677*7c478bd9Sstevel@tonic-gate 	    }
678*7c478bd9Sstevel@tonic-gate 	    break;
679*7c478bd9Sstevel@tonic-gate 	case 'd':			/* pathname for db */
680*7c478bd9Sstevel@tonic-gate 	    db_name = optarg;
681*7c478bd9Sstevel@tonic-gate 	    break;
682*7c478bd9Sstevel@tonic-gate 	case 'm':			/* manual type-in of master key */
683*7c478bd9Sstevel@tonic-gate 	    manual = TRUE;
684*7c478bd9Sstevel@tonic-gate 	    if (menctype == ENCTYPE_UNKNOWN)
685*7c478bd9Sstevel@tonic-gate 		menctype = ENCTYPE_DES_CBC_CRC;
686*7c478bd9Sstevel@tonic-gate 	    break;
687*7c478bd9Sstevel@tonic-gate 	case 'M':			/* master key name in DB */
688*7c478bd9Sstevel@tonic-gate 	    mkey_name = optarg;
689*7c478bd9Sstevel@tonic-gate 	    break;
690*7c478bd9Sstevel@tonic-gate 	case 'n':
691*7c478bd9Sstevel@tonic-gate 	    nofork++;			/* don't detach from terminal */
692*7c478bd9Sstevel@tonic-gate 	    break;
693*7c478bd9Sstevel@tonic-gate 	case 'k':			/* enctype for master key */
694*7c478bd9Sstevel@tonic-gate 	    if (krb5_string_to_enctype(optarg, &menctype))
695*7c478bd9Sstevel@tonic-gate 		com_err(argv[0], 0,
696*7c478bd9Sstevel@tonic-gate 		gettext("invalid enctype %s"), optarg);
697*7c478bd9Sstevel@tonic-gate 	    break;
698*7c478bd9Sstevel@tonic-gate 	case 'R':
699*7c478bd9Sstevel@tonic-gate 	    rcname = optarg;
700*7c478bd9Sstevel@tonic-gate 	    break;
701*7c478bd9Sstevel@tonic-gate 	case 'p':
702*7c478bd9Sstevel@tonic-gate 	    if (default_udp_ports)
703*7c478bd9Sstevel@tonic-gate 		free(default_udp_ports);
704*7c478bd9Sstevel@tonic-gate 	    default_udp_ports = strdup(optarg);
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	    if (default_tcp_ports)
707*7c478bd9Sstevel@tonic-gate 		free(default_tcp_ports);
708*7c478bd9Sstevel@tonic-gate 	    default_tcp_ports = strdup(optarg);
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	    break;
711*7c478bd9Sstevel@tonic-gate 	case '4':
712*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
713*7c478bd9Sstevel@tonic-gate 	    if (v4mode)
714*7c478bd9Sstevel@tonic-gate 		free(v4mode);
715*7c478bd9Sstevel@tonic-gate 	    v4mode = strdup(optarg);
716*7c478bd9Sstevel@tonic-gate #endif
717*7c478bd9Sstevel@tonic-gate 	    break;
718*7c478bd9Sstevel@tonic-gate 	case '3':
719*7c478bd9Sstevel@tonic-gate #ifdef ATHENA_DES3_KLUDGE
720*7c478bd9Sstevel@tonic-gate 	    if (krb5_enctypes_list[krb5_enctypes_length-1].etype
721*7c478bd9Sstevel@tonic-gate 		!= ENCTYPE_LOCAL_DES3_HMAC_SHA1) {
722*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
723*7c478bd9Sstevel@tonic-gate 			"internal inconsistency in enctypes_list"
724*7c478bd9Sstevel@tonic-gate 			" while disabling\n"
725*7c478bd9Sstevel@tonic-gate 			"des3-marc-hmac-sha1 enctype\n");
726*7c478bd9Sstevel@tonic-gate 		exit(1);
727*7c478bd9Sstevel@tonic-gate 	    }
728*7c478bd9Sstevel@tonic-gate 	    krb5_enctypes_length--;
729*7c478bd9Sstevel@tonic-gate 	    break;
730*7c478bd9Sstevel@tonic-gate #endif
731*7c478bd9Sstevel@tonic-gate 	case '?':
732*7c478bd9Sstevel@tonic-gate 	default:
733*7c478bd9Sstevel@tonic-gate 	    usage(argv[0]);
734*7c478bd9Sstevel@tonic-gate 	    exit(1);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate     }
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
739*7c478bd9Sstevel@tonic-gate     /*
740*7c478bd9Sstevel@tonic-gate      * Setup the v4 mode
741*7c478bd9Sstevel@tonic-gate      */
742*7c478bd9Sstevel@tonic-gate     process_v4_mode(argv[0], v4mode);
743*7c478bd9Sstevel@tonic-gate #endif
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate     /*
746*7c478bd9Sstevel@tonic-gate      * Check to see if we processed any realms.
747*7c478bd9Sstevel@tonic-gate      */
748*7c478bd9Sstevel@tonic-gate     if (kdc_numrealms == 0) {
749*7c478bd9Sstevel@tonic-gate 	/* no realm specified, use default realm */
750*7c478bd9Sstevel@tonic-gate 	if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
751*7c478bd9Sstevel@tonic-gate 	    com_err(argv[0], retval,
752*7c478bd9Sstevel@tonic-gate 		gettext("while attempting to retrieve default realm"));
753*7c478bd9Sstevel@tonic-gate 	    exit(1);
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 	if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
756*7c478bd9Sstevel@tonic-gate 	    if ((retval = init_realm(argv[0], rdatap, lrealm, db_name,
757*7c478bd9Sstevel@tonic-gate 				     mkey_name, menctype, default_udp_ports,
758*7c478bd9Sstevel@tonic-gate 				     default_tcp_ports, manual))) {
759*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
760*7c478bd9Sstevel@tonic-gate 			gettext("%s: cannot initialize realm %s\n"),
761*7c478bd9Sstevel@tonic-gate 			argv[0], lrealm);
762*7c478bd9Sstevel@tonic-gate 		exit(1);
763*7c478bd9Sstevel@tonic-gate 	    }
764*7c478bd9Sstevel@tonic-gate 	    kdc_realmlist[0] = rdatap;
765*7c478bd9Sstevel@tonic-gate 	    kdc_numrealms++;
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate     }
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate #ifdef USE_RCACHE
770*7c478bd9Sstevel@tonic-gate     /*
771*7c478bd9Sstevel@tonic-gate      * Now handle the replay cache.
772*7c478bd9Sstevel@tonic-gate      */
773*7c478bd9Sstevel@tonic-gate     if ((retval = kdc_initialize_rcache(kcontext, rcname))) {
774*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing KDC replay cache"));
775*7c478bd9Sstevel@tonic-gate 	exit(1);
776*7c478bd9Sstevel@tonic-gate     }
777*7c478bd9Sstevel@tonic-gate #endif
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate     /* Ensure that this is set for our first request. */
780*7c478bd9Sstevel@tonic-gate     kdc_active_realm = kdc_realmlist[0];
781*7c478bd9Sstevel@tonic-gate     if (default_udp_ports)
782*7c478bd9Sstevel@tonic-gate 	free(default_udp_ports);
783*7c478bd9Sstevel@tonic-gate     if (default_tcp_ports)
784*7c478bd9Sstevel@tonic-gate 	free(default_tcp_ports);
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate     return;
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate void
790*7c478bd9Sstevel@tonic-gate finish_realms(prog)
791*7c478bd9Sstevel@tonic-gate     char *prog;
792*7c478bd9Sstevel@tonic-gate {
793*7c478bd9Sstevel@tonic-gate     int i;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate     for (i = 0; i < kdc_numrealms; i++) {
796*7c478bd9Sstevel@tonic-gate 	finish_realm(kdc_realmlist[i]);
797*7c478bd9Sstevel@tonic-gate 	kdc_realmlist[i] = 0;
798*7c478bd9Sstevel@tonic-gate     }
799*7c478bd9Sstevel@tonic-gate }
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate /*
802*7c478bd9Sstevel@tonic-gate  outline:
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate  process args & setup
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate  initialize database access (fetch master key, open DB)
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate  initialize network
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate  loop:
811*7c478bd9Sstevel@tonic-gate  	listen for packet
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	determine packet type, dispatch to handling routine
814*7c478bd9Sstevel@tonic-gate 		(AS or TGS (or V4?))
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 	reflect response
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 	exit on signal
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate  clean up secrets, close db
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate  shut down network
823*7c478bd9Sstevel@tonic-gate 
824*7c478bd9Sstevel@tonic-gate  exit
825*7c478bd9Sstevel@tonic-gate  */
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate int main(argc, argv)
828*7c478bd9Sstevel@tonic-gate      int argc;
829*7c478bd9Sstevel@tonic-gate      char *argv[];
830*7c478bd9Sstevel@tonic-gate {
831*7c478bd9Sstevel@tonic-gate     krb5_error_code	retval;
832*7c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
833*7c478bd9Sstevel@tonic-gate     int			*port_list;
834*7c478bd9Sstevel@tonic-gate     int errout = 0;
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
839*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"KRB5KDC_TEST"	/* Use this only if it weren't */
840*7c478bd9Sstevel@tonic-gate #endif
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate     if (strrchr(argv[0], '/'))
845*7c478bd9Sstevel@tonic-gate 	argv[0] = strrchr(argv[0], '/')+1;
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate     if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) *
848*7c478bd9Sstevel@tonic-gate 						  KRB5_KDC_MAX_REALMS))) {
849*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: cannot get memory for realm list\n"), argv[0]);
850*7c478bd9Sstevel@tonic-gate 	exit(1);
851*7c478bd9Sstevel@tonic-gate     }
852*7c478bd9Sstevel@tonic-gate     memset((char *) kdc_realmlist, 0,
853*7c478bd9Sstevel@tonic-gate 	   (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));
854*7c478bd9Sstevel@tonic-gate     port_list = NULL;
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate     /*
857*7c478bd9Sstevel@tonic-gate      * A note about Kerberos contexts: This context, "kcontext", is used
858*7c478bd9Sstevel@tonic-gate      * for the KDC operations, i.e. setup, network connection and error
859*7c478bd9Sstevel@tonic-gate      * reporting.  The per-realm operations use the "realm_context"
860*7c478bd9Sstevel@tonic-gate      * associated with each realm.
861*7c478bd9Sstevel@tonic-gate      */
862*7c478bd9Sstevel@tonic-gate     retval = krb5_init_context(&kcontext);
863*7c478bd9Sstevel@tonic-gate     if (retval) {
864*7c478bd9Sstevel@tonic-gate 	    com_err(argv[0], retval, gettext("while initializing krb5"));
865*7c478bd9Sstevel@tonic-gate 	    exit(1);
866*7c478bd9Sstevel@tonic-gate     }
867*7c478bd9Sstevel@tonic-gate     krb5_klog_init(kcontext, "kdc", argv[0], 1);
868*7c478bd9Sstevel@tonic-gate     /* initialize_kdc5_error_table();  SUNWresync121 XXX */
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate     /*
871*7c478bd9Sstevel@tonic-gate      * Scan through the argument list
872*7c478bd9Sstevel@tonic-gate      */
873*7c478bd9Sstevel@tonic-gate     initialize_realms(kcontext, argc, argv);
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate     setup_signal_handlers();
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate     if (retval = setup_sam()) {
878*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing SAM"));
879*7c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
880*7c478bd9Sstevel@tonic-gate 	return 1;
881*7c478bd9Sstevel@tonic-gate     }
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate     if ((retval = setup_network(argv[0]))) {
884*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while initializing network"));
885*7c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
886*7c478bd9Sstevel@tonic-gate 	return 1;
887*7c478bd9Sstevel@tonic-gate     }
888*7c478bd9Sstevel@tonic-gate     if (!nofork && daemon(0, 0)) {
889*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], errno, gettext("while detaching from tty"));
890*7c478bd9Sstevel@tonic-gate 	finish_realms(argv[0]);
891*7c478bd9Sstevel@tonic-gate 	return 1;
892*7c478bd9Sstevel@tonic-gate     }
893*7c478bd9Sstevel@tonic-gate     if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) {
894*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while logging message"));
895*7c478bd9Sstevel@tonic-gate 	errout++;
896*7c478bd9Sstevel@tonic-gate 	};
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate     if ((retval = listen_and_process(argv[0]))) {
899*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while processing network requests"));
900*7c478bd9Sstevel@tonic-gate 	errout++;
901*7c478bd9Sstevel@tonic-gate     }
902*7c478bd9Sstevel@tonic-gate     if ((retval = closedown_network(argv[0]))) {
903*7c478bd9Sstevel@tonic-gate 	com_err(argv[0], retval, gettext("while shutting down network"));
904*7c478bd9Sstevel@tonic-gate 	errout++;
905*7c478bd9Sstevel@tonic-gate     }
906*7c478bd9Sstevel@tonic-gate     krb5_klog_syslog(LOG_INFO, "shutting down");
907*7c478bd9Sstevel@tonic-gate     krb5_klog_close(kdc_context);
908*7c478bd9Sstevel@tonic-gate     finish_realms(argv[0]);
909*7c478bd9Sstevel@tonic-gate     krb5_free_context(kcontext);
910*7c478bd9Sstevel@tonic-gate     return errout;
911*7c478bd9Sstevel@tonic-gate }
912