xref: /titanic_50/usr/src/cmd/krb5/slave/kpropd.c (revision 7c64d3750da7fda7e450b8f9b0b963905ded6379)
17c478bd9Sstevel@tonic-gate /*
2*7c64d375Smp153739  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
87c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
97c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
107c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
137c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
147c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
157c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
167c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
177c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
187c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
197c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
207c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
217c478bd9Sstevel@tonic-gate  * or implied warranty.
227c478bd9Sstevel@tonic-gate  *
237c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
247c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
257c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * slave/kpropd.c
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
347c478bd9Sstevel@tonic-gate  * All Rights Reserved.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
377c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
387c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
397c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
427c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
437c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
447c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
457c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
467c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
477c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
487c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
497c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
507c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
517c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
527c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
537c478bd9Sstevel@tonic-gate  * or implied warranty.
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * XXX We need to modify the protocol so that an acknowledge is set
577c478bd9Sstevel@tonic-gate  * after each block, instead after the entire series is sent over.
587c478bd9Sstevel@tonic-gate  * The reason for this is so that error packets can get interpreted
597c478bd9Sstevel@tonic-gate  * right away.  If you don't do this, the sender may never get the
607c478bd9Sstevel@tonic-gate  * error packet, because it will die an EPIPE trying to complete the
617c478bd9Sstevel@tonic-gate  * write...
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
6456a424ccSmp153739 
657c478bd9Sstevel@tonic-gate #include <stdio.h>
667c478bd9Sstevel@tonic-gate #include <ctype.h>
677c478bd9Sstevel@tonic-gate #include <sys/file.h>
687c478bd9Sstevel@tonic-gate #include <signal.h>
697c478bd9Sstevel@tonic-gate #include <string.h>
707c478bd9Sstevel@tonic-gate #include <fcntl.h>
717c478bd9Sstevel@tonic-gate #include <sys/types.h>
727c478bd9Sstevel@tonic-gate #include <sys/time.h>
737c478bd9Sstevel@tonic-gate #include <sys/stat.h>
747c478bd9Sstevel@tonic-gate #include <sys/socket.h>
757c478bd9Sstevel@tonic-gate #include <sys/wait.h>
767c478bd9Sstevel@tonic-gate #include <netinet/in.h>
777c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
787c478bd9Sstevel@tonic-gate #include <sys/param.h>
797c478bd9Sstevel@tonic-gate #include <netdb.h>
807c478bd9Sstevel@tonic-gate #include <syslog.h>
817c478bd9Sstevel@tonic-gate #include <libintl.h>
827c478bd9Sstevel@tonic-gate #include <locale.h>
837c478bd9Sstevel@tonic-gate #include <k5-int.h>
847c478bd9Sstevel@tonic-gate #include <socket-utils.h>
857c478bd9Sstevel@tonic-gate #include "com_err.h"
867c478bd9Sstevel@tonic-gate #include <errno.h>
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #include "kprop.h"
897c478bd9Sstevel@tonic-gate #include <iprop_hdr.h>
907c478bd9Sstevel@tonic-gate #include "iprop.h"
917c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
927c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h>
937c478bd9Sstevel@tonic-gate 
94*7c64d375Smp153739 /* Solaris Kerberos */
95*7c64d375Smp153739 #include <libgen.h>
96*7c64d375Smp153739 
977c478bd9Sstevel@tonic-gate #define SYSLOG_CLASS LOG_DAEMON
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate char *poll_time = NULL;
1007c478bd9Sstevel@tonic-gate char *def_realm = NULL;
1017c478bd9Sstevel@tonic-gate boolean_t runonce = B_FALSE;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * This struct simulates the use of _kadm5_server_handle_t
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate typedef struct _kadm5_iprop_handle_t {
1077c478bd9Sstevel@tonic-gate 	krb5_ui_4	magic_number;
1087c478bd9Sstevel@tonic-gate 	krb5_ui_4	struct_version;
1097c478bd9Sstevel@tonic-gate 	krb5_ui_4	api_version;
1107c478bd9Sstevel@tonic-gate 	char 		*cache_name;
1117c478bd9Sstevel@tonic-gate 	int		destroy_cache;
1127c478bd9Sstevel@tonic-gate 	CLIENT		*clnt;
1137c478bd9Sstevel@tonic-gate 	krb5_context	context;
1147c478bd9Sstevel@tonic-gate 	kadm5_config_params params;
1157c478bd9Sstevel@tonic-gate 	struct _kadm5_iprop_handle_t *lhandle;
1167c478bd9Sstevel@tonic-gate } *kadm5_iprop_handle_t;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static char *kprop_version = KPROP_PROT_VERSION;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate char	*progname;
1217c478bd9Sstevel@tonic-gate int     debug = 0;
1227c478bd9Sstevel@tonic-gate char	*srvtab = 0;
1237c478bd9Sstevel@tonic-gate int	standalone = 0;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate krb5_principal	server;		/* This is our server principal name */
1267c478bd9Sstevel@tonic-gate krb5_principal	client;		/* This is who we're talking to */
1277c478bd9Sstevel@tonic-gate krb5_context kpropd_context;
1287c478bd9Sstevel@tonic-gate krb5_auth_context auth_context;
1297c478bd9Sstevel@tonic-gate char	*realm = NULL;		/* Our realm */
1307c478bd9Sstevel@tonic-gate char	*file = KPROPD_DEFAULT_FILE;
1317c478bd9Sstevel@tonic-gate char	*temp_file_name;
1327c478bd9Sstevel@tonic-gate char	*kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
1337c478bd9Sstevel@tonic-gate char	*kerb_database = NULL;
1347c478bd9Sstevel@tonic-gate char	*acl_file_name = KPROPD_ACL_FILE;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate krb5_address	sender_addr;
1377c478bd9Sstevel@tonic-gate krb5_address	receiver_addr;
1387c478bd9Sstevel@tonic-gate short 		port = 0;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate void	PRS
1417c478bd9Sstevel@tonic-gate 	 (int, char**);
1427c478bd9Sstevel@tonic-gate int	do_standalone
1437c478bd9Sstevel@tonic-gate 	 (iprop_role iproprole);
1447c478bd9Sstevel@tonic-gate void	doit
1457c478bd9Sstevel@tonic-gate 	(int);
1467c478bd9Sstevel@tonic-gate krb5_error_code	do_iprop(kdb_log_context *log_ctx);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate void	kerberos_authenticate
1497c478bd9Sstevel@tonic-gate 	(krb5_context,
1507c478bd9Sstevel@tonic-gate 		   int,
1517c478bd9Sstevel@tonic-gate 		   krb5_principal *,
1527c478bd9Sstevel@tonic-gate 		   krb5_enctype *,
1537c478bd9Sstevel@tonic-gate 		   struct sockaddr_storage);
1547c478bd9Sstevel@tonic-gate krb5_boolean authorized_principal
1557c478bd9Sstevel@tonic-gate 	(krb5_context,
1567c478bd9Sstevel@tonic-gate     		   krb5_principal,
1577c478bd9Sstevel@tonic-gate 		   krb5_enctype);
1587c478bd9Sstevel@tonic-gate void	recv_database
1597c478bd9Sstevel@tonic-gate 	(krb5_context,
1607c478bd9Sstevel@tonic-gate 		   int,
1617c478bd9Sstevel@tonic-gate 		   int,
1627c478bd9Sstevel@tonic-gate 		   krb5_data *);
1637c478bd9Sstevel@tonic-gate void	load_database
1647c478bd9Sstevel@tonic-gate 	(krb5_context,
1657c478bd9Sstevel@tonic-gate     		   char *,
1667c478bd9Sstevel@tonic-gate     		   char *);
1677c478bd9Sstevel@tonic-gate void	send_error
1687c478bd9Sstevel@tonic-gate 	(krb5_context,
1697c478bd9Sstevel@tonic-gate     		   int,
1707c478bd9Sstevel@tonic-gate 		   krb5_error_code,
1717c478bd9Sstevel@tonic-gate     		   char	*);
1727c478bd9Sstevel@tonic-gate void	recv_error
1737c478bd9Sstevel@tonic-gate 	(krb5_context,
1747c478bd9Sstevel@tonic-gate     		   krb5_data *);
1757c478bd9Sstevel@tonic-gate int	convert_polltime
1767c478bd9Sstevel@tonic-gate 	(char *);
1777c478bd9Sstevel@tonic-gate unsigned int	backoff_from_master
1787c478bd9Sstevel@tonic-gate 	(int *);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate static void usage()
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1837c478bd9Sstevel@tonic-gate 		gettext("\nUsage: %s\n"), /* progname may be a long pathname */
1847c478bd9Sstevel@tonic-gate 		progname);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1877c478bd9Sstevel@tonic-gate 		gettext("\t[-r realm] [-s srvtab] [-dS] [-f slave_file]\n"));
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1907c478bd9Sstevel@tonic-gate 		gettext("\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n"));
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\t[-P port] [-a acl_file]\n"));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	exit(1);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate int
1987c478bd9Sstevel@tonic-gate main(argc, argv)
1997c478bd9Sstevel@tonic-gate 	int	argc;
2007c478bd9Sstevel@tonic-gate 	char	**argv;
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	krb5_error_code retval;
2037c478bd9Sstevel@tonic-gate 	int ret = 0;
2047c478bd9Sstevel@tonic-gate 	kdb_log_context	*log_ctx;
20554925bf6Swillf 	int iprop_supported;
206*7c64d375Smp153739 	krb5_boolean is_master = FALSE;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	PRS(argc, argv);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	log_ctx = kpropd_context->kdblog_context;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
2137c478bd9Sstevel@tonic-gate 		/*
2147c478bd9Sstevel@tonic-gate 		 * We wanna do iprop !
2157c478bd9Sstevel@tonic-gate 		 */
21654925bf6Swillf 		retval = krb5_db_supports_iprop(kpropd_context,
21754925bf6Swillf 		    &iprop_supported);
21854925bf6Swillf 		if (retval) {
219*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
22054925bf6Swillf 			com_err(progname, retval,
221*7c64d375Smp153739 				gettext("while determining if dbmodule plugin "
222*7c64d375Smp153739 					    "supports iprop"));
22354925bf6Swillf 			exit(1);
22454925bf6Swillf 		}
22554925bf6Swillf 		if (!iprop_supported) {
226*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
227*7c64d375Smp153739 			com_err(progname, 0,
22854925bf6Swillf 				gettext("Current dbmodule plugin does not support "
229*7c64d375Smp153739 				    "iprop"));
230*7c64d375Smp153739 			exit(1);
231*7c64d375Smp153739 		}
232*7c64d375Smp153739 
233*7c64d375Smp153739 		/*
234*7c64d375Smp153739 		 * Solaris Kerberos:
235*7c64d375Smp153739 		 * Ensure that kpropd is only run on a slave
236*7c64d375Smp153739 		 */
237*7c64d375Smp153739 		if (retval = kadm5_is_master(kpropd_context, def_realm,
238*7c64d375Smp153739 		    &is_master)) {
239*7c64d375Smp153739 			com_err(progname, retval,
240*7c64d375Smp153739 			    gettext("while trying to determine whether host is "
241*7c64d375Smp153739 			    "master KDC for realm %s"), def_realm);
242*7c64d375Smp153739 			exit(1);
243*7c64d375Smp153739 		}
244*7c64d375Smp153739 
245*7c64d375Smp153739 		if (is_master == TRUE) {
246*7c64d375Smp153739 			char *master = NULL;
247*7c64d375Smp153739 			kadm5_get_master(kpropd_context, def_realm, &master);
248*7c64d375Smp153739 
249*7c64d375Smp153739 			com_err(progname, 0,
250*7c64d375Smp153739 			    gettext("%s is the master KDC for the realm %s. "
251*7c64d375Smp153739 			    "%s can only be run on a slave KDC"),
252*7c64d375Smp153739 			    master ? master : "unknown", def_realm, progname);
25354925bf6Swillf 			exit(1);
25454925bf6Swillf 		}
25554925bf6Swillf 
2567c478bd9Sstevel@tonic-gate 		retval = do_iprop(log_ctx);
2577c478bd9Sstevel@tonic-gate 		if (retval) {
258*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
2597c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
260*7c64d375Smp153739 			    gettext("while doing iprop"));
2617c478bd9Sstevel@tonic-gate 			exit(1);
2627c478bd9Sstevel@tonic-gate 		}
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	} else {
265*7c64d375Smp153739 
266*7c64d375Smp153739 		/*
267*7c64d375Smp153739 		 * Solaris Kerberos:
268*7c64d375Smp153739 		 * Ensure that the kpropd.acl file exists and contains at least
269*7c64d375Smp153739 		 * 1 entry.
270*7c64d375Smp153739 		 */
271*7c64d375Smp153739 		FILE *tmp_acl_file;
272*7c64d375Smp153739 		int seen_file = 0;
273*7c64d375Smp153739 		char buf[1024];
274*7c64d375Smp153739 
275*7c64d375Smp153739 		tmp_acl_file = fopen(acl_file_name, "r");
276*7c64d375Smp153739 		if (!tmp_acl_file) {
277*7c64d375Smp153739 			com_err(progname, errno,
278*7c64d375Smp153739 			    gettext("while opening acl file %s"),
279*7c64d375Smp153739 			    acl_file_name);
280*7c64d375Smp153739 			exit(1);
281*7c64d375Smp153739 		}
282*7c64d375Smp153739 
283*7c64d375Smp153739 		while (!feof(tmp_acl_file) && !seen_file ) {
284*7c64d375Smp153739 			if (!fgets(buf, sizeof(buf), tmp_acl_file))
285*7c64d375Smp153739 				break;
286*7c64d375Smp153739 
287*7c64d375Smp153739 			if (buf[0] != '#' && !isspace(buf[0]))
288*7c64d375Smp153739 				seen_file = 1;
289*7c64d375Smp153739 		}
290*7c64d375Smp153739 		if (!seen_file) {
291*7c64d375Smp153739 			com_err(progname, 0,
292*7c64d375Smp153739 			    gettext("No entries found in %s. Can't "
293*7c64d375Smp153739 			    "authorize propagation requests"), acl_file_name);
294*7c64d375Smp153739 			exit(1);
295*7c64d375Smp153739 		}
296*7c64d375Smp153739 		fclose(tmp_acl_file);
297*7c64d375Smp153739 
2987c478bd9Sstevel@tonic-gate 		if (standalone)
2997c478bd9Sstevel@tonic-gate 			ret = do_standalone(IPROP_NULL);
3007c478bd9Sstevel@tonic-gate 		else
3017c478bd9Sstevel@tonic-gate 			doit(0);
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	exit(ret);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate int do_standalone(iprop_role iproprole)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate     struct	linger linger;
3107c478bd9Sstevel@tonic-gate     struct	servent *sp;
3117c478bd9Sstevel@tonic-gate     int	finet, fromlen, s;
3127c478bd9Sstevel@tonic-gate     int	on = 1;
3137c478bd9Sstevel@tonic-gate     int	ret, status = 0;
3147c478bd9Sstevel@tonic-gate     struct	sockaddr_in6 sin6 = { AF_INET6 };
3157c478bd9Sstevel@tonic-gate     int sin6_size = sizeof (sin6);
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate     /* listen for either ipv4 or ipv6 */
3187c478bd9Sstevel@tonic-gate     finet = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
3197c478bd9Sstevel@tonic-gate     if (finet < 0 ) {
3207c478bd9Sstevel@tonic-gate 	com_err(progname, errno, gettext("while obtaining socket"));
3217c478bd9Sstevel@tonic-gate 	exit(1);
3227c478bd9Sstevel@tonic-gate     }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate     if(!port) {
3257c478bd9Sstevel@tonic-gate 	sp = getservbyname(KPROP_SERVICE, "tcp");
3267c478bd9Sstevel@tonic-gate 	if (sp == NULL) {
3277c478bd9Sstevel@tonic-gate 	    com_err(progname, 0, gettext("%s/tcp: unknown service"),
3287c478bd9Sstevel@tonic-gate 		    KPROP_SERVICE);
3297c478bd9Sstevel@tonic-gate 	    exit(1);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 	sin6.sin6_port = sp->s_port;
3327c478bd9Sstevel@tonic-gate     } else
3337c478bd9Sstevel@tonic-gate 	sin6.sin6_port = port;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate     /*
3367c478bd9Sstevel@tonic-gate      * We need to close the socket immediately if iprop is enabled,
3377c478bd9Sstevel@tonic-gate      * since back-to-back full resyncs are possible, so we do not
3387c478bd9Sstevel@tonic-gate      * linger around for too long
3397c478bd9Sstevel@tonic-gate      */
3407c478bd9Sstevel@tonic-gate     if (iproprole == IPROP_SLAVE) {
3417c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3427c478bd9Sstevel@tonic-gate 			(char *)&on, sizeof(on)) < 0)
3437c478bd9Sstevel@tonic-gate 		    com_err(progname, errno,
344*7c64d375Smp153739 			    gettext("while setting socket option (SO_REUSEADDR)"));
3457c478bd9Sstevel@tonic-gate 	    linger.l_onoff = 1;
3467c478bd9Sstevel@tonic-gate 	    linger.l_linger = 2;
3477c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_LINGER,
3487c478bd9Sstevel@tonic-gate 			(void *)&linger, sizeof(linger)) < 0)
3497c478bd9Sstevel@tonic-gate 		    com_err(progname, errno,
350*7c64d375Smp153739 			    gettext("while setting socket option (SO_LINGER)"));
3517c478bd9Sstevel@tonic-gate     }
3527c478bd9Sstevel@tonic-gate     if ((ret = bind(finet, (struct sockaddr *)&sin6, sizeof(sin6))) < 0) {
3537c478bd9Sstevel@tonic-gate 	if (debug) {
3547c478bd9Sstevel@tonic-gate 	    on = 1;
3557c478bd9Sstevel@tonic-gate 	    fprintf(stderr,
3567c478bd9Sstevel@tonic-gate 		    gettext("%s: attempting to rebind socket "
3577c478bd9Sstevel@tonic-gate 		    "with SO_REUSEADDR\n"), progname);
3587c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3597c478bd9Sstevel@tonic-gate 			(char *)&on, sizeof(on)) < 0) {
3607c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
361*7c64d375Smp153739 			gettext("while setting socket option (SO_REUSEADDR)"));
3627c478bd9Sstevel@tonic-gate 	    }
3637c478bd9Sstevel@tonic-gate 	    ret = bind(finet, (struct sockaddr *) &sin6, sizeof(sin6));
3647c478bd9Sstevel@tonic-gate 	    }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	    if (ret < 0) {
367*7c64d375Smp153739 	/*
368*7c64d375Smp153739 	 * Solaris Kerberos:
369*7c64d375Smp153739 	 * com_err will print the err msg associated with errno
370*7c64d375Smp153739 	 */
371*7c64d375Smp153739 #if 0
3727c478bd9Sstevel@tonic-gate 		perror(gettext("bind"));
373*7c64d375Smp153739 #endif
3747c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
3757c478bd9Sstevel@tonic-gate 		    gettext("while binding listener socket"));
3767c478bd9Sstevel@tonic-gate 		exit(1);
3777c478bd9Sstevel@tonic-gate 	    }
3787c478bd9Sstevel@tonic-gate 	}
379*7c64d375Smp153739 	if (!debug && (iproprole != IPROP_SLAVE)) {
380*7c64d375Smp153739 	/* Solaris Kerberos: Indicate where further messages will be sent */
381*7c64d375Smp153739 		fprintf(stderr,
382*7c64d375Smp153739 		    gettext("%s: Logging to SYSLOG with LOG_DAEMON facility\n"),
383*7c64d375Smp153739 		    progname);
384*7c64d375Smp153739 		if (daemon(1, 0)) {
385*7c64d375Smp153739 			com_err(progname, errno, gettext("while daemonizing"));
386*7c64d375Smp153739 			exit(1);
387*7c64d375Smp153739 		}
388*7c64d375Smp153739 		rem_default_com_err_hook();
389*7c64d375Smp153739 	}
390*7c64d375Smp153739 
3917c478bd9Sstevel@tonic-gate #ifdef PID_FILE
3927c478bd9Sstevel@tonic-gate 	if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
3937c478bd9Sstevel@tonic-gate 		fprintf(pidfile, gettext("%d\n"), getpid());
3947c478bd9Sstevel@tonic-gate 		fclose(pidfile);
3957c478bd9Sstevel@tonic-gate 	} else
3967c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
3977c478bd9Sstevel@tonic-gate 		gettext("while opening pid file %s for writing"),
3987c478bd9Sstevel@tonic-gate 		PID_FILE);
3997c478bd9Sstevel@tonic-gate #endif
4007c478bd9Sstevel@tonic-gate 	if (listen(finet, 5) < 0) {
401*7c64d375Smp153739 		/* Solaris Kerberos: Keep error messages consistent */
402*7c64d375Smp153739 		com_err(progname, errno, gettext("while listening on socket"));
4037c478bd9Sstevel@tonic-gate 		exit(1);
4047c478bd9Sstevel@tonic-gate 	}
4057c478bd9Sstevel@tonic-gate 	while (1) {
4067c478bd9Sstevel@tonic-gate 		int child_pid;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 		s = accept(finet, (struct sockaddr *) &sin6, &sin6_size);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		if (s < 0) {
411*7c64d375Smp153739 			if (errno != EINTR) {
412*7c64d375Smp153739 				/* Solaris Kerberos: Keep error messages consistent */
4137c478bd9Sstevel@tonic-gate 				com_err(progname, errno,
414*7c64d375Smp153739 		    gettext("while accepting connection"));
415*7c64d375Smp153739 			}
4167c478bd9Sstevel@tonic-gate 			continue;
4177c478bd9Sstevel@tonic-gate 		}
4187c478bd9Sstevel@tonic-gate 		if (debug && (iproprole != IPROP_SLAVE))
4197c478bd9Sstevel@tonic-gate 			child_pid = 0;
4207c478bd9Sstevel@tonic-gate 		else
4217c478bd9Sstevel@tonic-gate 			child_pid = fork();
4227c478bd9Sstevel@tonic-gate 		switch (child_pid) {
4237c478bd9Sstevel@tonic-gate 		case -1:
4247c478bd9Sstevel@tonic-gate 			com_err(progname, errno, gettext("while forking"));
4257c478bd9Sstevel@tonic-gate 			exit(1);
4267c478bd9Sstevel@tonic-gate 	    /*NOTREACHED*/
4277c478bd9Sstevel@tonic-gate 		case 0:
4287c478bd9Sstevel@tonic-gate 	    /* child */
4297c478bd9Sstevel@tonic-gate 			(void) close(finet);
43056a424ccSmp153739 
4317c478bd9Sstevel@tonic-gate 			doit(s);
4327c478bd9Sstevel@tonic-gate 			close(s);
4337c478bd9Sstevel@tonic-gate 			_exit(0);
4347c478bd9Sstevel@tonic-gate 	    /*NOTREACHED*/
4357c478bd9Sstevel@tonic-gate 		default:
4367c478bd9Sstevel@tonic-gate 	    /* parent */
4377c478bd9Sstevel@tonic-gate 	    if (wait(&status) < 0) {
4387c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
4397c478bd9Sstevel@tonic-gate 		    gettext("while waiting to receive database"));
4407c478bd9Sstevel@tonic-gate 		exit(1);
4417c478bd9Sstevel@tonic-gate 	    }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	    close(s);
4447c478bd9Sstevel@tonic-gate 	    if (iproprole == IPROP_SLAVE)
4457c478bd9Sstevel@tonic-gate 		close(finet);
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	    if ((ret = WEXITSTATUS(status)) != 0)
4487c478bd9Sstevel@tonic-gate 		return (ret);
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	if (iproprole == IPROP_SLAVE)
4527c478bd9Sstevel@tonic-gate 	    break;
4537c478bd9Sstevel@tonic-gate     }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate     return (0);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate void doit(fd)
4597c478bd9Sstevel@tonic-gate 	int	fd;
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate 	struct sockaddr_storage from;
4627c478bd9Sstevel@tonic-gate 	socklen_t fromlen;
4637c478bd9Sstevel@tonic-gate 	int on = 1;
4647c478bd9Sstevel@tonic-gate 	struct hostent	*hp;
4657c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
4667c478bd9Sstevel@tonic-gate 	krb5_data confmsg;
4677c478bd9Sstevel@tonic-gate 	int lock_fd;
46856a424ccSmp153739 	mode_t omask;
4697c478bd9Sstevel@tonic-gate 	krb5_enctype etype;
47056a424ccSmp153739 	int database_fd;
4717c478bd9Sstevel@tonic-gate 	char ntop[NI_MAXHOST] = "";
4727c478bd9Sstevel@tonic-gate 	krb5_context doit_context;
4737c478bd9Sstevel@tonic-gate 	kdb_log_context *log_ctx;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	retval = krb5_init_context(&doit_context);
4767c478bd9Sstevel@tonic-gate 	if (retval) {
4777c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while initializing krb5"));
4787c478bd9Sstevel@tonic-gate 		exit(1);
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 	log_ctx = kpropd_context->kdblog_context;
4817c478bd9Sstevel@tonic-gate 	if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE))
4827c478bd9Sstevel@tonic-gate 		ulog_set_role(doit_context, IPROP_SLAVE);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	fromlen = (socklen_t)sizeof (from);
4857c478bd9Sstevel@tonic-gate 	if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) {
4867c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: ", progname);
4877c478bd9Sstevel@tonic-gate 		perror(gettext("getpeername"));
4887c478bd9Sstevel@tonic-gate 		exit(1);
4897c478bd9Sstevel@tonic-gate 	}
4907c478bd9Sstevel@tonic-gate 	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (caddr_t) &on,
4917c478bd9Sstevel@tonic-gate 		       sizeof (on)) < 0) {
4927c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
4937c478bd9Sstevel@tonic-gate 		gettext("while attempting setsockopt (SO_KEEPALIVE)"));
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
4977c478bd9Sstevel@tonic-gate 		NULL, 0, NI_NUMERICHOST) != 0) {
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 		/* getnameifo failed so use inet_ntop() to get printable addresses */
5007c478bd9Sstevel@tonic-gate 		if (from.ss_family == AF_INET) {
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET,
5037c478bd9Sstevel@tonic-gate 			    (const void *)&ss2sin(&from)->sin_addr,
5047c478bd9Sstevel@tonic-gate 			    ntop, sizeof(ntop));
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 		} else if (from.ss_family == AF_INET6 &&
5077c478bd9Sstevel@tonic-gate 			! IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 			ipaddr_t v4addr;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET6,
5127c478bd9Sstevel@tonic-gate 				(const void *)&ss2sin6(&from)->sin6_addr, ntop,
5137c478bd9Sstevel@tonic-gate 				sizeof(ntop));
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 		/* ipv4 mapped ipv6 addrs handled later */
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (from.ss_family == AF_INET || from.ss_family == AF_INET6) {
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		if (from.ss_family == AF_INET6 &&
5217c478bd9Sstevel@tonic-gate 			IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 			ipaddr_t v4addr;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 			/* coerce ipv4 mapped ipv6 addr to normal ipv4 addr */
5267c478bd9Sstevel@tonic-gate 			IN6_V4MAPPED_TO_IPADDR(&(ss2sin6(&from)->sin6_addr),
5277c478bd9Sstevel@tonic-gate 				v4addr);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET, (const void *) &v4addr,
5307c478bd9Sstevel@tonic-gate 				ntop, sizeof(ntop));
5317c478bd9Sstevel@tonic-gate 		}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO, gettext("Connection from %s"), ntop);
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		if (debug)
5367c478bd9Sstevel@tonic-gate 			printf("Connection from %s\n", ntop);
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	} else {
5397c478bd9Sstevel@tonic-gate 		/* address family isn't either AF_INET || AF_INET6 */
5407c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO,
5417c478bd9Sstevel@tonic-gate 		    gettext("Connection from unknown address family:%d"),
5427c478bd9Sstevel@tonic-gate 		    from.ss_family);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		if (debug) {
5457c478bd9Sstevel@tonic-gate 			printf(gettext("Connection from unknown address family:%d"),
5467c478bd9Sstevel@tonic-gate 			    from.ss_family);
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * Now do the authentication
5527c478bd9Sstevel@tonic-gate 	 */
5537c478bd9Sstevel@tonic-gate 	kerberos_authenticate(doit_context, fd, &client, &etype, from);
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if (!authorized_principal(doit_context, client, etype)) {
5567c478bd9Sstevel@tonic-gate 		char	*name;
5577c478bd9Sstevel@tonic-gate 
55856a424ccSmp153739 		retval = krb5_unparse_name(doit_context, client, &name);
55956a424ccSmp153739 		if (retval) {
560*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
5617c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
562*7c64d375Smp153739 		    gettext("while unparsing client name"));
5637c478bd9Sstevel@tonic-gate 			exit(1);
5647c478bd9Sstevel@tonic-gate 		}
5657c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
5667c478bd9Sstevel@tonic-gate 		gettext("Rejected connection from unauthorized principal %s"),
5677c478bd9Sstevel@tonic-gate 		       name);
5687c478bd9Sstevel@tonic-gate 		free(name);
5697c478bd9Sstevel@tonic-gate 		exit(1);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 	omask = umask(077);
5727c478bd9Sstevel@tonic-gate 	lock_fd = open(temp_file_name, O_RDWR|O_CREAT, 0600);
5737c478bd9Sstevel@tonic-gate 	(void) umask(omask);
5747c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd,
5757c478bd9Sstevel@tonic-gate 				KRB5_LOCKMODE_EXCLUSIVE|KRB5_LOCKMODE_DONTBLOCK);
5767c478bd9Sstevel@tonic-gate 	if (retval) {
5777c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
5787c478bd9Sstevel@tonic-gate 			gettext("while trying to lock '%s'"),
5797c478bd9Sstevel@tonic-gate 		    temp_file_name);
5807c478bd9Sstevel@tonic-gate 	    exit(1);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 	if ((database_fd = open(temp_file_name,
5837c478bd9Sstevel@tonic-gate 				O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
5847c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
5857c478bd9Sstevel@tonic-gate 			gettext("while opening database file, '%s'"),
5867c478bd9Sstevel@tonic-gate 			temp_file_name);
5877c478bd9Sstevel@tonic-gate 		exit(1);
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 	recv_database(doit_context, fd, database_fd, &confmsg);
5907c478bd9Sstevel@tonic-gate 	if (rename(temp_file_name, file)) {
591*7c64d375Smp153739 		/* Solaris Kerberos: Keep error messages consistent */
5927c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
593*7c64d375Smp153739 			gettext("while renaming %s to %s"),
5947c478bd9Sstevel@tonic-gate 			temp_file_name, file);
5957c478bd9Sstevel@tonic-gate 		exit(1);
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_SHARED);
5987c478bd9Sstevel@tonic-gate 	if (retval) {
5997c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
6007c478bd9Sstevel@tonic-gate 			gettext("while downgrading lock on '%s'"),
6017c478bd9Sstevel@tonic-gate 		    temp_file_name);
6027c478bd9Sstevel@tonic-gate 	    exit(1);
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 	load_database(doit_context, kdb5_util, file);
6057c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_UNLOCK);
6067c478bd9Sstevel@tonic-gate 	if (retval) {
6077c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
6087c478bd9Sstevel@tonic-gate 		gettext("while unlocking '%s'"), temp_file_name);
6097c478bd9Sstevel@tonic-gate 	    exit(1);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 	(void)close(lock_fd);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	/*
6147c478bd9Sstevel@tonic-gate 	 * Send the acknowledgement message generated in
6157c478bd9Sstevel@tonic-gate 	 * recv_database, then close the socket.
6167c478bd9Sstevel@tonic-gate 	 */
61756a424ccSmp153739 	retval = krb5_write_message(doit_context, (void *) &fd, &confmsg);
61856a424ccSmp153739 	if (retval) {
6197c478bd9Sstevel@tonic-gate 		krb5_free_data_contents(doit_context, &confmsg);
6207c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
6217c478bd9Sstevel@tonic-gate 			gettext("while sending # of received bytes"));
6227c478bd9Sstevel@tonic-gate 		exit(1);
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate 	krb5_free_data_contents(doit_context, &confmsg);
6257c478bd9Sstevel@tonic-gate 	if (close(fd) < 0) {
6267c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
6277c478bd9Sstevel@tonic-gate 			gettext("while trying to close database file"));
6287c478bd9Sstevel@tonic-gate 		exit(1);
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	exit(0);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate /*
6367c478bd9Sstevel@tonic-gate  * Routine to handle incremental update transfer(s) from master KDC
6377c478bd9Sstevel@tonic-gate  */
6387c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx) {
6397c478bd9Sstevel@tonic-gate 	CLIENT *cl;
6407c478bd9Sstevel@tonic-gate 	kadm5_ret_t retval;
6417c478bd9Sstevel@tonic-gate 	kadm5_config_params params;
6427c478bd9Sstevel@tonic-gate 	krb5_ccache cc;
6437c478bd9Sstevel@tonic-gate 	krb5_principal iprop_svc_principal;
6447c478bd9Sstevel@tonic-gate 	void *server_handle = NULL;
6457c478bd9Sstevel@tonic-gate 	char *iprop_svc_princstr = NULL;
6467c478bd9Sstevel@tonic-gate 	char *master_svc_princstr = NULL;
6477c478bd9Sstevel@tonic-gate 	char *admin_server = NULL;
6487c478bd9Sstevel@tonic-gate 	char *keytab_name = NULL;
6497c478bd9Sstevel@tonic-gate 	unsigned int pollin, backoff_time;
6507c478bd9Sstevel@tonic-gate 	int backoff_cnt = 0;
6517c478bd9Sstevel@tonic-gate 	int reinit_cnt = 0;
6527c478bd9Sstevel@tonic-gate 	int ret;
6537c478bd9Sstevel@tonic-gate 	boolean_t frdone = B_FALSE;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	kdb_incr_result_t *incr_ret;
6567c478bd9Sstevel@tonic-gate 	static kdb_last_t mylast;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	kdb_fullresync_result_t *full_ret;
6597c478bd9Sstevel@tonic-gate 	char *full_resync_arg = NULL;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	kadm5_iprop_handle_t handle;
6627c478bd9Sstevel@tonic-gate 	kdb_hlog_t *ulog;
6637c478bd9Sstevel@tonic-gate 
664*7c64d375Smp153739 	krb5_keytab kt;
665*7c64d375Smp153739 	krb5_keytab_entry entry;
666*7c64d375Smp153739 	char kt_name[MAX_KEYTAB_NAME_LEN];
667*7c64d375Smp153739 
668*7c64d375Smp153739 	/*
669*7c64d375Smp153739 	 * Solaris Kerberos:
670*7c64d375Smp153739 	 * Delay daemonizing until some basic configuration checks have been
671*7c64d375Smp153739 	 * performed
672*7c64d375Smp153739 	 */
673*7c64d375Smp153739 #if 0
6747c478bd9Sstevel@tonic-gate 	if (!debug)
6757c478bd9Sstevel@tonic-gate 		daemon(0, 0);
676*7c64d375Smp153739 #endif
6777c478bd9Sstevel@tonic-gate 	pollin = (unsigned int)0;
6787c478bd9Sstevel@tonic-gate 	(void) memset((char *)&params, 0, sizeof (params));
6797c478bd9Sstevel@tonic-gate 	ulog = log_ctx->ulog;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	params.mask |= KADM5_CONFIG_REALM;
6827c478bd9Sstevel@tonic-gate 	params.realm = def_realm;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	if (master_svc_princstr == NULL) {
6857c478bd9Sstevel@tonic-gate 		if (retval = kadm5_get_kiprop_host_srv_name(kpropd_context,
6867c478bd9Sstevel@tonic-gate 					def_realm, &master_svc_princstr)) {
687*7c64d375Smp153739 			/* Solaris Kerberos: keep error messages consistent */
6887c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
689*7c64d375Smp153739 				gettext("while getting kiprop host based "
690*7c64d375Smp153739 					"service name for realm %s"), def_realm);
6917c478bd9Sstevel@tonic-gate 			exit(1);
6927c478bd9Sstevel@tonic-gate 		}
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/*
6967c478bd9Sstevel@tonic-gate 	 * Set cc to the default credentials cache
6977c478bd9Sstevel@tonic-gate 	 */
6987c478bd9Sstevel@tonic-gate 	if (retval = krb5_cc_default(kpropd_context, &cc)) {
6997c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
7007c478bd9Sstevel@tonic-gate 			gettext("while opening default "
7017c478bd9Sstevel@tonic-gate 				"credentials cache"));
7027c478bd9Sstevel@tonic-gate 		exit(1);
7037c478bd9Sstevel@tonic-gate 	}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME,
7067c478bd9Sstevel@tonic-gate 				KRB5_NT_SRV_HST, &iprop_svc_principal);
7077c478bd9Sstevel@tonic-gate 	if (retval) {
7087c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while trying to construct "
7097c478bd9Sstevel@tonic-gate 						"host service principal"));
7107c478bd9Sstevel@tonic-gate 		exit(1);
7117c478bd9Sstevel@tonic-gate 	}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	if (retval = krb5_unparse_name(kpropd_context, iprop_svc_principal,
7147c478bd9Sstevel@tonic-gate 				&iprop_svc_princstr)) {
7157c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
7167c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing "
7177c478bd9Sstevel@tonic-gate 				"principal name"));
7187c478bd9Sstevel@tonic-gate 		krb5_free_principal(kpropd_context, iprop_svc_principal);
7197c478bd9Sstevel@tonic-gate 		exit(1);
7207c478bd9Sstevel@tonic-gate 	}
721*7c64d375Smp153739 
722*7c64d375Smp153739 	/*
723*7c64d375Smp153739 	 * Solaris Kerberos:
724*7c64d375Smp153739 	 * Check to see if kiprop/<fqdn>@REALM is in the keytab
725*7c64d375Smp153739 	 */
726*7c64d375Smp153739 	kt_name[0] = '\0';
727*7c64d375Smp153739 	if (retval = krb5_kt_default_name(kpropd_context, kt_name,
728*7c64d375Smp153739 	    MAX_KEYTAB_NAME_LEN)){
729*7c64d375Smp153739 		com_err(progname, retval, gettext ("while resolving the "
730*7c64d375Smp153739 		    "name of the default keytab"));
731*7c64d375Smp153739 	}
732*7c64d375Smp153739 
733*7c64d375Smp153739 	if (retval = krb5_kt_default(kpropd_context, &kt)) {
734*7c64d375Smp153739 		com_err(progname, retval, gettext ("while resolving default "
735*7c64d375Smp153739 		    "keytab"));
7367c478bd9Sstevel@tonic-gate 		krb5_free_principal(kpropd_context, iprop_svc_principal);
737*7c64d375Smp153739 		exit(1);
738*7c64d375Smp153739 	}
739*7c64d375Smp153739 
740*7c64d375Smp153739 	if (retval = krb5_kt_get_entry(kpropd_context, kt, iprop_svc_principal,
741*7c64d375Smp153739 	    0, 0, &entry)) {
742*7c64d375Smp153739 		com_err(progname, retval, gettext("while retrieving entry %s "
743*7c64d375Smp153739 		    "from %s"), iprop_svc_princstr,
744*7c64d375Smp153739 		    kt_name[0] ? kt_name : "default keytab");
745*7c64d375Smp153739 		krb5_kt_close(kpropd_context,kt);
746*7c64d375Smp153739 		krb5_free_principal(kpropd_context, iprop_svc_principal);
747*7c64d375Smp153739 		exit(1);
748*7c64d375Smp153739 	}
749*7c64d375Smp153739 
750*7c64d375Smp153739 	krb5_kt_close(kpropd_context,kt);
751*7c64d375Smp153739 	krb5_free_principal(kpropd_context, iprop_svc_principal);
752*7c64d375Smp153739 
753*7c64d375Smp153739 	if (!debug) {
754*7c64d375Smp153739 	/* Solaris Kerberos: Indicate where further messages will be sent */
755*7c64d375Smp153739 		fprintf(stderr, gettext("%s: Logging to SYSLOG\n"), progname);
756*7c64d375Smp153739 		if (daemon(0, 0)) {
757*7c64d375Smp153739 			com_err(progname, errno, gettext("while daemonizing"));
758*7c64d375Smp153739 			exit(1);
759*7c64d375Smp153739 		}
760*7c64d375Smp153739 		rem_default_com_err_hook();
761*7c64d375Smp153739 	}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate reinit:
7647c478bd9Sstevel@tonic-gate 	/*
7657c478bd9Sstevel@tonic-gate 	 * Authentication, initialize rpcsec_gss handle etc.
7667c478bd9Sstevel@tonic-gate 	 */
7677c478bd9Sstevel@tonic-gate 	retval = kadm5_init_with_skey(iprop_svc_princstr, keytab_name,
7687c478bd9Sstevel@tonic-gate 				    master_svc_princstr,
7697c478bd9Sstevel@tonic-gate 				    &params,
7707c478bd9Sstevel@tonic-gate 				    KADM5_STRUCT_VERSION,
7717c478bd9Sstevel@tonic-gate 				    KADM5_API_VERSION_2,
77254925bf6Swillf 				    NULL,
7737c478bd9Sstevel@tonic-gate  				    &server_handle);
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	if (retval) {
7767c478bd9Sstevel@tonic-gate 		if (retval == KADM5_RPC_ERROR) {
7777c478bd9Sstevel@tonic-gate 			reinit_cnt++;
7787c478bd9Sstevel@tonic-gate 			if (server_handle)
7797c478bd9Sstevel@tonic-gate 				kadm5_destroy((void *) server_handle);
7807c478bd9Sstevel@tonic-gate 			server_handle = (void *)NULL;
7817c478bd9Sstevel@tonic-gate 			handle = (kadm5_iprop_handle_t)NULL;
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 			com_err(progname, retval, gettext(
7847c478bd9Sstevel@tonic-gate 					"while attempting to connect"
7857c478bd9Sstevel@tonic-gate 					" to master KDC ... retrying"));
7867c478bd9Sstevel@tonic-gate 			backoff_time = backoff_from_master(&reinit_cnt);
7877c478bd9Sstevel@tonic-gate 			(void) sleep(backoff_time);
7887c478bd9Sstevel@tonic-gate 			goto reinit;
7897c478bd9Sstevel@tonic-gate 		} else {
790*7c64d375Smp153739 			/* Solaris Kerberos: Be more verbose */
7917c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
792*7c64d375Smp153739                                 gettext("while initializing %s interface for "
793*7c64d375Smp153739 				    "%s"), progname, iprop_svc_princstr);
7947c478bd9Sstevel@tonic-gate 			if (retval == KADM5_BAD_CLIENT_PARAMS ||
7957c478bd9Sstevel@tonic-gate 			    retval == KADM5_BAD_SERVER_PARAMS)
7967c478bd9Sstevel@tonic-gate 				usage();
7977c478bd9Sstevel@tonic-gate 			exit(1);
7987c478bd9Sstevel@tonic-gate                 }
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	/*
8027c478bd9Sstevel@tonic-gate 	 * Reset re-initialization count to zero now.
8037c478bd9Sstevel@tonic-gate 	 */
8047c478bd9Sstevel@tonic-gate 	reinit_cnt = backoff_time = 0;
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	/*
8077c478bd9Sstevel@tonic-gate 	 * Reset the handle to the correct type for the RPC call
8087c478bd9Sstevel@tonic-gate 	 */
8097c478bd9Sstevel@tonic-gate 	handle = server_handle;
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	/*
8127c478bd9Sstevel@tonic-gate 	 * If we have reached this far, we have succesfully established
8137c478bd9Sstevel@tonic-gate 	 * a RPCSEC_GSS connection; we now start polling for updates
8147c478bd9Sstevel@tonic-gate 	 */
8157c478bd9Sstevel@tonic-gate 	if (poll_time == NULL) {
8167c478bd9Sstevel@tonic-gate 		if ((poll_time = (char *)strdup("2m")) == NULL) {
817*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
8187c478bd9Sstevel@tonic-gate 			com_err(progname, ENOMEM,
819*7c64d375Smp153739 				gettext("while allocating poll_time"));
8207c478bd9Sstevel@tonic-gate 			exit(1);
8217c478bd9Sstevel@tonic-gate 		}
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	if (pollin == (unsigned int)0)
8257c478bd9Sstevel@tonic-gate 		pollin = convert_polltime(poll_time);
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	for (;;) {
8287c478bd9Sstevel@tonic-gate 		incr_ret = NULL;
8297c478bd9Sstevel@tonic-gate 		full_ret = NULL;
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 		/*
8327c478bd9Sstevel@tonic-gate 		 * Get the most recent ulog entry sno + ts, which
8337c478bd9Sstevel@tonic-gate 		 * we package in the request to the master KDC
8347c478bd9Sstevel@tonic-gate 		 */
8357c478bd9Sstevel@tonic-gate 		mylast.last_sno = ulog->kdb_last_sno;
8367c478bd9Sstevel@tonic-gate 		mylast.last_time = ulog->kdb_last_time;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		/*
8397c478bd9Sstevel@tonic-gate 		 * Loop continuously on an iprop_get_updates_1(),
8407c478bd9Sstevel@tonic-gate 		 * so that we can keep probing the master for updates
8417c478bd9Sstevel@tonic-gate 		 * or (if needed) do a full resync of the krb5 db.
8427c478bd9Sstevel@tonic-gate 		 */
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 		incr_ret = iprop_get_updates_1(&mylast, handle->clnt);
8457c478bd9Sstevel@tonic-gate 		if (incr_ret == (kdb_incr_result_t *)NULL) {
8467c478bd9Sstevel@tonic-gate 			clnt_perror(handle->clnt,
8477c478bd9Sstevel@tonic-gate 				    "iprop_get_updates call failed");
8487c478bd9Sstevel@tonic-gate 			if (server_handle)
8497c478bd9Sstevel@tonic-gate 				kadm5_destroy((void *)server_handle);
8507c478bd9Sstevel@tonic-gate 			server_handle = (void *)NULL;
8517c478bd9Sstevel@tonic-gate 			handle = (kadm5_iprop_handle_t)NULL;
8527c478bd9Sstevel@tonic-gate 			goto reinit;
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		switch (incr_ret->ret) {
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		case UPDATE_FULL_RESYNC_NEEDED:
8587c478bd9Sstevel@tonic-gate 			/*
8597c478bd9Sstevel@tonic-gate 			 * We dont do a full resync again, if the last
8607c478bd9Sstevel@tonic-gate 			 * X'fer was a resync and if the master sno is
8617c478bd9Sstevel@tonic-gate 			 * still "0", i.e. no updates so far.
8627c478bd9Sstevel@tonic-gate 			 */
8637c478bd9Sstevel@tonic-gate 			if ((frdone == B_TRUE) && (incr_ret->lastentry.last_sno
8647c478bd9Sstevel@tonic-gate 						== 0)) {
8657c478bd9Sstevel@tonic-gate 				break;
8667c478bd9Sstevel@tonic-gate 			} else {
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 				full_ret = iprop_full_resync_1((void *)
8697c478bd9Sstevel@tonic-gate 						&full_resync_arg, handle->clnt);
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 				if (full_ret == (kdb_fullresync_result_t *)
8727c478bd9Sstevel@tonic-gate 							NULL) {
8737c478bd9Sstevel@tonic-gate 					clnt_perror(handle->clnt,
8747c478bd9Sstevel@tonic-gate 					    "iprop_full_resync call failed");
8757c478bd9Sstevel@tonic-gate 					if (server_handle)
8767c478bd9Sstevel@tonic-gate 						kadm5_destroy((void *)
8777c478bd9Sstevel@tonic-gate 							server_handle);
8787c478bd9Sstevel@tonic-gate 					server_handle = (void *)NULL;
8797c478bd9Sstevel@tonic-gate 					handle = (kadm5_iprop_handle_t)NULL;
8807c478bd9Sstevel@tonic-gate 					goto reinit;
8817c478bd9Sstevel@tonic-gate 				}
8827c478bd9Sstevel@tonic-gate 			}
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 			switch (full_ret->ret) {
8857c478bd9Sstevel@tonic-gate 			case UPDATE_OK:
8867c478bd9Sstevel@tonic-gate 				backoff_cnt = 0;
8877c478bd9Sstevel@tonic-gate 				/*
8887c478bd9Sstevel@tonic-gate 				 * We now listen on the kprop port for
8897c478bd9Sstevel@tonic-gate 				 * the full dump
8907c478bd9Sstevel@tonic-gate 				 */
8917c478bd9Sstevel@tonic-gate 				ret = do_standalone(log_ctx->iproprole);
8927c478bd9Sstevel@tonic-gate 				if (ret)
8937c478bd9Sstevel@tonic-gate 					syslog(LOG_WARNING,
8947c478bd9Sstevel@tonic-gate 					    gettext("kpropd: Full resync, "
8957c478bd9Sstevel@tonic-gate 					    "invalid return."));
8967c478bd9Sstevel@tonic-gate 				if (debug)
8977c478bd9Sstevel@tonic-gate 					if (ret)
8987c478bd9Sstevel@tonic-gate 						fprintf(stderr,
8997c478bd9Sstevel@tonic-gate 						    gettext("Full resync "
9007c478bd9Sstevel@tonic-gate 						    "was unsuccessful\n"));
9017c478bd9Sstevel@tonic-gate 					else
9027c478bd9Sstevel@tonic-gate 						fprintf(stderr,
9037c478bd9Sstevel@tonic-gate 						    gettext("Full resync "
9047c478bd9Sstevel@tonic-gate 						    "was successful\n"));
9057c478bd9Sstevel@tonic-gate 				frdone = B_TRUE;
9067c478bd9Sstevel@tonic-gate 				break;
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 			case UPDATE_BUSY:
9097c478bd9Sstevel@tonic-gate 				/*
9107c478bd9Sstevel@tonic-gate 				 * Exponential backoff
9117c478bd9Sstevel@tonic-gate 				 */
9127c478bd9Sstevel@tonic-gate 				backoff_cnt++;
9137c478bd9Sstevel@tonic-gate 				break;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 			case UPDATE_FULL_RESYNC_NEEDED:
9167c478bd9Sstevel@tonic-gate 			case UPDATE_NIL:
9177c478bd9Sstevel@tonic-gate 			default:
9187c478bd9Sstevel@tonic-gate 				backoff_cnt = 0;
9197c478bd9Sstevel@tonic-gate 				frdone = B_FALSE;
9207c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext("kpropd: Full resync,"
9217c478bd9Sstevel@tonic-gate 					" invalid return from master KDC."));
9227c478bd9Sstevel@tonic-gate 				break;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 			case UPDATE_PERM_DENIED:
9257c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext("kpropd: Full resync,"
9267c478bd9Sstevel@tonic-gate 					" permission denied."));
9277c478bd9Sstevel@tonic-gate 				goto error;
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 			case UPDATE_ERROR:
9307c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext("kpropd: Full resync,"
9317c478bd9Sstevel@tonic-gate 					" error returned from master KDC."));
9327c478bd9Sstevel@tonic-gate 				goto error;
9337c478bd9Sstevel@tonic-gate 			}
9347c478bd9Sstevel@tonic-gate 			break;
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 		case UPDATE_OK:
9377c478bd9Sstevel@tonic-gate 			backoff_cnt = 0;
9387c478bd9Sstevel@tonic-gate 			frdone = B_FALSE;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 			/*
9417c478bd9Sstevel@tonic-gate 			 * ulog_replay() will convert the ulog updates to db
9427c478bd9Sstevel@tonic-gate 			 * entries using the kdb conv api and will commit
9437c478bd9Sstevel@tonic-gate 			 * the entries to the slave kdc database
9447c478bd9Sstevel@tonic-gate 			 */
9457c478bd9Sstevel@tonic-gate 			retval = ulog_replay(kpropd_context, incr_ret);
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 			if (retval) {
9487c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext("kpropd: ulog_replay"
9497c478bd9Sstevel@tonic-gate 					" failed, updates not registered."));
9507c478bd9Sstevel@tonic-gate 				break;
9517c478bd9Sstevel@tonic-gate 			}
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 			if (debug)
9547c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("Update transfer "
9557c478bd9Sstevel@tonic-gate 					"from master was OK\n"));
9567c478bd9Sstevel@tonic-gate 			break;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 		case UPDATE_PERM_DENIED:
9597c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("kpropd: get_updates,"
9607c478bd9Sstevel@tonic-gate 						" permission denied."));
9617c478bd9Sstevel@tonic-gate 			goto error;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 		case UPDATE_ERROR:
9647c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("kpropd: get_updates, error "
9657c478bd9Sstevel@tonic-gate 						"returned from master KDC."));
9667c478bd9Sstevel@tonic-gate 			goto error;
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 		case UPDATE_BUSY:
9697c478bd9Sstevel@tonic-gate 			/*
9707c478bd9Sstevel@tonic-gate 			 * Exponential backoff
9717c478bd9Sstevel@tonic-gate 			 */
9727c478bd9Sstevel@tonic-gate 			backoff_cnt++;
9737c478bd9Sstevel@tonic-gate 			break;
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		case UPDATE_NIL:
9767c478bd9Sstevel@tonic-gate 			/*
9777c478bd9Sstevel@tonic-gate 			 * Master-slave are in sync
9787c478bd9Sstevel@tonic-gate 			 */
9797c478bd9Sstevel@tonic-gate 			if (debug)
9807c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("Master, slave KDC's "
9817c478bd9Sstevel@tonic-gate 					"are in-sync, no updates\n"));
9827c478bd9Sstevel@tonic-gate 			backoff_cnt = 0;
9837c478bd9Sstevel@tonic-gate 			frdone = B_FALSE;
9847c478bd9Sstevel@tonic-gate 			break;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 		default:
9877c478bd9Sstevel@tonic-gate 			backoff_cnt = 0;
9887c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("kpropd: get_updates,"
9897c478bd9Sstevel@tonic-gate 					" invalid return from master KDC."));
9907c478bd9Sstevel@tonic-gate 			break;
9917c478bd9Sstevel@tonic-gate 		}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 		if (runonce == B_TRUE)
9947c478bd9Sstevel@tonic-gate 			goto done;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 		/*
9977c478bd9Sstevel@tonic-gate 		 * Sleep for the specified poll interval (Default is 2 mts),
9987c478bd9Sstevel@tonic-gate 		 * or do a binary exponential backoff if we get an
9997c478bd9Sstevel@tonic-gate 		 * UPDATE_BUSY signal
10007c478bd9Sstevel@tonic-gate 		 */
10017c478bd9Sstevel@tonic-gate 		if (backoff_cnt > 0) {
10027c478bd9Sstevel@tonic-gate 			backoff_time = backoff_from_master(&backoff_cnt);
10037c478bd9Sstevel@tonic-gate 			if (debug)
10047c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("Busy signal received "
10057c478bd9Sstevel@tonic-gate 					"from master, backoff for %d secs\n"),
10067c478bd9Sstevel@tonic-gate 					backoff_time);
10077c478bd9Sstevel@tonic-gate 			(void) sleep(backoff_time);
10087c478bd9Sstevel@tonic-gate 		}
10097c478bd9Sstevel@tonic-gate 		else
10107c478bd9Sstevel@tonic-gate 			(void) sleep(pollin);
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	}
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate error:
10167c478bd9Sstevel@tonic-gate 	if (debug)
10177c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("ERROR returned by master, bailing\n"));
10187c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("kpropd: ERROR returned by master KDC,"
10197c478bd9Sstevel@tonic-gate 			" bailing.\n"));
10207c478bd9Sstevel@tonic-gate done:
10217c478bd9Sstevel@tonic-gate 	if (poll_time)
10227c478bd9Sstevel@tonic-gate 		free(poll_time);
10237c478bd9Sstevel@tonic-gate 	if(iprop_svc_princstr)
10247c478bd9Sstevel@tonic-gate 		free(iprop_svc_princstr);
10257c478bd9Sstevel@tonic-gate 	if (master_svc_princstr)
10267c478bd9Sstevel@tonic-gate 		free(master_svc_princstr);
10277c478bd9Sstevel@tonic-gate 	if (retval = krb5_cc_close(kpropd_context, cc)) {
10287c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
10297c478bd9Sstevel@tonic-gate 			gettext("while closing default ccache"));
10307c478bd9Sstevel@tonic-gate 		exit(1);
10317c478bd9Sstevel@tonic-gate 	}
10327c478bd9Sstevel@tonic-gate 	if (def_realm)
10337c478bd9Sstevel@tonic-gate 		free(def_realm);
10347c478bd9Sstevel@tonic-gate 	if (server_handle)
10357c478bd9Sstevel@tonic-gate 		kadm5_destroy((void *)server_handle);
10367c478bd9Sstevel@tonic-gate 	if (kpropd_context)
10377c478bd9Sstevel@tonic-gate 		krb5_free_context(kpropd_context);
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	if (runonce == B_TRUE)
10407c478bd9Sstevel@tonic-gate 		return (0);
10417c478bd9Sstevel@tonic-gate 	else
10427c478bd9Sstevel@tonic-gate 		exit(1);
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate /*
10477c478bd9Sstevel@tonic-gate  * Do exponential backoff, since master KDC is BUSY or down
10487c478bd9Sstevel@tonic-gate  */
10497c478bd9Sstevel@tonic-gate unsigned int backoff_from_master(int *cnt) {
10507c478bd9Sstevel@tonic-gate 	unsigned int btime;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	btime = (unsigned int)(2<<(*cnt));
10537c478bd9Sstevel@tonic-gate 	if (btime > MAX_BACKOFF) {
10547c478bd9Sstevel@tonic-gate 		btime = MAX_BACKOFF;
10557c478bd9Sstevel@tonic-gate 		*cnt--;
10567c478bd9Sstevel@tonic-gate 	}
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	return (btime);
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate /*
10637c478bd9Sstevel@tonic-gate  * Routine to convert the `pollstr' string to seconds
10647c478bd9Sstevel@tonic-gate  */
10657c478bd9Sstevel@tonic-gate int convert_polltime(char *pollstr) {
10667c478bd9Sstevel@tonic-gate 	char *tokenptr = NULL;
10677c478bd9Sstevel@tonic-gate 	int len, polltime;
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	len = polltime = 0;
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 	if ((len = strcspn(pollstr, "s")) < strlen(pollstr)) {
10727c478bd9Sstevel@tonic-gate 		tokenptr = malloc((len + 1) * sizeof(char));
10737c478bd9Sstevel@tonic-gate 		(void) strlcpy(tokenptr, pollstr, len + 1);
10747c478bd9Sstevel@tonic-gate 		polltime = atoi(tokenptr);
10757c478bd9Sstevel@tonic-gate 	}
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	if ((len = strcspn(pollstr, "m")) < strlen(pollstr)) {
10787c478bd9Sstevel@tonic-gate 		tokenptr = malloc((len + 1) * sizeof(char));
10797c478bd9Sstevel@tonic-gate 		(void) strlcpy(tokenptr, pollstr, len + 1);
10807c478bd9Sstevel@tonic-gate 		polltime = atoi(tokenptr) * 60;
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	if ((len = strcspn(pollstr, "h")) < strlen(pollstr)) {
10847c478bd9Sstevel@tonic-gate 		tokenptr = malloc((len + 1) * sizeof(char));
10857c478bd9Sstevel@tonic-gate 		(void) strlcpy(tokenptr, pollstr, len + 1);
10867c478bd9Sstevel@tonic-gate 		polltime = atoi(tokenptr) * 3600;
10877c478bd9Sstevel@tonic-gate 	}
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	if (tokenptr != NULL)
10907c478bd9Sstevel@tonic-gate 		free(tokenptr);
10917c478bd9Sstevel@tonic-gate 	/*
10927c478bd9Sstevel@tonic-gate 	 * If we have a bogus pollstr value, set polltime to the
10937c478bd9Sstevel@tonic-gate 	 * default of 2 mts (120 seconds).
10947c478bd9Sstevel@tonic-gate 	 */
10957c478bd9Sstevel@tonic-gate 	if (polltime == 0)
10967c478bd9Sstevel@tonic-gate 		polltime = 120;
10977c478bd9Sstevel@tonic-gate 	return (polltime);
10987c478bd9Sstevel@tonic-gate }
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate static void
11017c478bd9Sstevel@tonic-gate kpropd_com_err_proc(whoami, code, fmt, args)
11027c478bd9Sstevel@tonic-gate 	const char	*whoami;
11037c478bd9Sstevel@tonic-gate 	long		code;
11047c478bd9Sstevel@tonic-gate 	const char	*fmt;
11057c478bd9Sstevel@tonic-gate 	va_list		args;
11067c478bd9Sstevel@tonic-gate {
11077c478bd9Sstevel@tonic-gate 	char	error_buf[8096];
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	error_buf[0] = '\0';
11107c478bd9Sstevel@tonic-gate 	if (fmt)
11117c478bd9Sstevel@tonic-gate 		vsprintf(error_buf, fmt, args);
11127c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "%s%s%s%s%s", whoami ? whoami : "", whoami ? ": " : "",
11137c478bd9Sstevel@tonic-gate 	       code ? error_message(code) : "", code ? " " : "", error_buf);
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate void PRS(argc,argv)
11177c478bd9Sstevel@tonic-gate 	int	argc;
11187c478bd9Sstevel@tonic-gate 	char	**argv;
11197c478bd9Sstevel@tonic-gate {
11207c478bd9Sstevel@tonic-gate 	register char	*word, ch;
11217c478bd9Sstevel@tonic-gate 	char	*cp;
11227c478bd9Sstevel@tonic-gate 	int c;
11237c478bd9Sstevel@tonic-gate 	struct hostent *hp;
11247c478bd9Sstevel@tonic-gate 	char	my_host_name[MAXHOSTNAMELEN], buf[BUFSIZ];
11257c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
11267c478bd9Sstevel@tonic-gate 	static const char	tmp[] = ".temp";
11277c478bd9Sstevel@tonic-gate 	kadm5_config_params	params;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
11327c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"KPROPD_TEST"	/* Use this only if it weren't */
11337c478bd9Sstevel@tonic-gate #endif
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	(void) memset((char *) &params, 0, sizeof (params));
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	retval = krb5_init_context(&kpropd_context);
11407c478bd9Sstevel@tonic-gate 	if (retval) {
11417c478bd9Sstevel@tonic-gate 		com_err(argv[0], retval,
11427c478bd9Sstevel@tonic-gate 			gettext("while initializing krb5"));
11437c478bd9Sstevel@tonic-gate 		exit(1);
11447c478bd9Sstevel@tonic-gate 	}
1145*7c64d375Smp153739 
1146*7c64d375Smp153739 	/* Solaris Kerberos: Sanitize progname */
1147*7c64d375Smp153739 	progname = basename(argv[0]);
1148*7c64d375Smp153739 
11497c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "dtf:F:p:P:r:s:Sa:")) != EOF){
11507c478bd9Sstevel@tonic-gate 		switch (c) {
11517c478bd9Sstevel@tonic-gate 		case 'd':
11527c478bd9Sstevel@tonic-gate 			debug++;
11537c478bd9Sstevel@tonic-gate 			break;
11547c478bd9Sstevel@tonic-gate 		case 't':
11557c478bd9Sstevel@tonic-gate 			/*
11567c478bd9Sstevel@tonic-gate 			 * Undocumented option - for testing only.
11577c478bd9Sstevel@tonic-gate 			 *
11587c478bd9Sstevel@tonic-gate 			 * Option to run the kpropd server exactly
11597c478bd9Sstevel@tonic-gate 			 * once (this is true only if iprop is enabled).
11607c478bd9Sstevel@tonic-gate 			 */
11617c478bd9Sstevel@tonic-gate 			runonce = B_TRUE;
11627c478bd9Sstevel@tonic-gate 			break;
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 		case 'f':
11657c478bd9Sstevel@tonic-gate 			file = optarg;
11667c478bd9Sstevel@tonic-gate 			if (!file)
11677c478bd9Sstevel@tonic-gate 				usage();
11687c478bd9Sstevel@tonic-gate 			break;
11697c478bd9Sstevel@tonic-gate 		case 'F':
11707c478bd9Sstevel@tonic-gate 			kerb_database = optarg;
11717c478bd9Sstevel@tonic-gate 			if (!kerb_database)
11727c478bd9Sstevel@tonic-gate 				usage();
11737c478bd9Sstevel@tonic-gate 			break;
11747c478bd9Sstevel@tonic-gate 		case 'p':
11757c478bd9Sstevel@tonic-gate 			kdb5_util = optarg;
11767c478bd9Sstevel@tonic-gate 			if (!kdb5_util)
11777c478bd9Sstevel@tonic-gate 				usage();
11787c478bd9Sstevel@tonic-gate 			break;
11797c478bd9Sstevel@tonic-gate 		case 'P':
11807c478bd9Sstevel@tonic-gate 			port = htons(atoi(optarg));
11817c478bd9Sstevel@tonic-gate 			if (!port)
11827c478bd9Sstevel@tonic-gate 				usage();
11837c478bd9Sstevel@tonic-gate 			break;
11847c478bd9Sstevel@tonic-gate 		case 'r':
11857c478bd9Sstevel@tonic-gate 			realm = optarg;
11867c478bd9Sstevel@tonic-gate 			if (!realm)
11877c478bd9Sstevel@tonic-gate 				usage();
11887c478bd9Sstevel@tonic-gate 			params.realm = realm;
11897c478bd9Sstevel@tonic-gate 			params.mask |= KADM5_CONFIG_REALM;
11907c478bd9Sstevel@tonic-gate 			break;
11917c478bd9Sstevel@tonic-gate 		case 's':
11927c478bd9Sstevel@tonic-gate 			srvtab = optarg;
11937c478bd9Sstevel@tonic-gate 			if (!srvtab)
11947c478bd9Sstevel@tonic-gate 				usage();
11957c478bd9Sstevel@tonic-gate 			break;
11967c478bd9Sstevel@tonic-gate 		case 'S':
11977c478bd9Sstevel@tonic-gate 			standalone++;
11987c478bd9Sstevel@tonic-gate 			break;
11997c478bd9Sstevel@tonic-gate 		case 'a':
12007c478bd9Sstevel@tonic-gate 			acl_file_name = optarg;
12017c478bd9Sstevel@tonic-gate 			if (!acl_file_name)
12027c478bd9Sstevel@tonic-gate 				usage();
12037c478bd9Sstevel@tonic-gate 			break;
12047c478bd9Sstevel@tonic-gate 		case '?':
12057c478bd9Sstevel@tonic-gate 				default:
12067c478bd9Sstevel@tonic-gate 					usage();
12077c478bd9Sstevel@tonic-gate 				}
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 			}
12107c478bd9Sstevel@tonic-gate 	/*
12117c478bd9Sstevel@tonic-gate 	 * If not in debug mode, switch com_err reporting to syslog
12127c478bd9Sstevel@tonic-gate 	 */
12137c478bd9Sstevel@tonic-gate 	if (! debug) {
12147c478bd9Sstevel@tonic-gate 	    openlog("kpropd", LOG_PID | LOG_ODELAY, SYSLOG_CLASS);
1215*7c64d375Smp153739 	    /*
1216*7c64d375Smp153739 	     * Solaris Kerberos:
1217*7c64d375Smp153739 	     * Don't replace default logging. Add a new logging channel.
1218*7c64d375Smp153739 	     * Stop logging to stderr when daemonizing
1219*7c64d375Smp153739 	     */
1220*7c64d375Smp153739 	    add_com_err_hook(kpropd_com_err_proc);
12217c478bd9Sstevel@tonic-gate 	}
12227c478bd9Sstevel@tonic-gate 	/*
12237c478bd9Sstevel@tonic-gate 	 * Get my hostname, so we can construct my service name
12247c478bd9Sstevel@tonic-gate 	 */
12257c478bd9Sstevel@tonic-gate 	retval = krb5_sname_to_principal(kpropd_context,
12267c478bd9Sstevel@tonic-gate 					 NULL, KPROP_SERVICE_NAME,
12277c478bd9Sstevel@tonic-gate 					 KRB5_NT_SRV_HST, &server);
12287c478bd9Sstevel@tonic-gate 	if (retval) {
1229*7c64d375Smp153739 		/* Solaris Kerberos: Keep error messages consistent */
12307c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
1231*7c64d375Smp153739 			gettext("while trying to construct my service name"));
12327c478bd9Sstevel@tonic-gate 		exit(1);
12337c478bd9Sstevel@tonic-gate 	}
12347c478bd9Sstevel@tonic-gate 	if (realm) {
123556a424ccSmp153739 	    retval = krb5_set_principal_realm(kpropd_context, server, realm);
123656a424ccSmp153739 	    if (retval) {
123756a424ccSmp153739 	        com_err(progname, errno,
123856a424ccSmp153739 			gettext("while constructing my service realm"));
123956a424ccSmp153739 		exit(1);
124056a424ccSmp153739 	    }
12417c478bd9Sstevel@tonic-gate 	}
12427c478bd9Sstevel@tonic-gate 	/*
12437c478bd9Sstevel@tonic-gate 	 * Construct the name of the temporary file.
12447c478bd9Sstevel@tonic-gate 	 */
12457c478bd9Sstevel@tonic-gate 	if ((temp_file_name = (char *) malloc(strlen(file) +
12467c478bd9Sstevel@tonic-gate 					       strlen(tmp) + 1)) == NULL) {
12477c478bd9Sstevel@tonic-gate 		com_err(progname, ENOMEM,
12487c478bd9Sstevel@tonic-gate 			gettext("while allocating filename for temp file"));
12497c478bd9Sstevel@tonic-gate 		exit(1);
12507c478bd9Sstevel@tonic-gate 	}
12517c478bd9Sstevel@tonic-gate 	strcpy(temp_file_name, file);
12527c478bd9Sstevel@tonic-gate 	strcat(temp_file_name, tmp);
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 	retval = kadm5_get_config_params(kpropd_context, NULL, NULL, &params,
12557c478bd9Sstevel@tonic-gate 	    &params);
12567c478bd9Sstevel@tonic-gate 	if (retval) {
12577c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while initializing"));
12587c478bd9Sstevel@tonic-gate 		exit(1);
12597c478bd9Sstevel@tonic-gate 	}
12607c478bd9Sstevel@tonic-gate 	if (params.iprop_enabled == TRUE) {
12617c478bd9Sstevel@tonic-gate 		ulog_set_role(kpropd_context, IPROP_SLAVE);
12627c478bd9Sstevel@tonic-gate 		poll_time = params.iprop_polltime;
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 		if (ulog_map(kpropd_context, &params, FKPROPD)) {
1265*7c64d375Smp153739 		/* Solaris Kerberos: Keep error messages consistent */
12667c478bd9Sstevel@tonic-gate  			com_err(progname, errno,
1267*7c64d375Smp153739 			    gettext("while mapping log"));
12687c478bd9Sstevel@tonic-gate 			exit(1);
12697c478bd9Sstevel@tonic-gate 		}
12707c478bd9Sstevel@tonic-gate 	}
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 	/*
12737c478bd9Sstevel@tonic-gate 	 * Grab the realm info and check if iprop is enabled.
12747c478bd9Sstevel@tonic-gate 	 */
12757c478bd9Sstevel@tonic-gate 	if (def_realm == NULL) {
12767c478bd9Sstevel@tonic-gate 		retval = krb5_get_default_realm(kpropd_context, &def_realm);
12777c478bd9Sstevel@tonic-gate 		if (retval) {
1278*7c64d375Smp153739 			/* Solaris Kerberos: Keep error messages consistent */
12797c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
1280*7c64d375Smp153739 				gettext("while retrieving default realm"));
12817c478bd9Sstevel@tonic-gate 			exit(1);
12827c478bd9Sstevel@tonic-gate 		}
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate /*
12877c478bd9Sstevel@tonic-gate  * Figure out who's calling on the other end of the connection....
12887c478bd9Sstevel@tonic-gate  */
12897c478bd9Sstevel@tonic-gate void
12907c478bd9Sstevel@tonic-gate kerberos_authenticate(context, fd, clientp, etype, ss)
12917c478bd9Sstevel@tonic-gate     krb5_context 	  context;
12927c478bd9Sstevel@tonic-gate     int		 	  fd;
12937c478bd9Sstevel@tonic-gate     krb5_principal	* clientp;
12947c478bd9Sstevel@tonic-gate     krb5_enctype	* etype;
12957c478bd9Sstevel@tonic-gate     struct sockaddr_storage	  ss;
12967c478bd9Sstevel@tonic-gate {
12977c478bd9Sstevel@tonic-gate     krb5_error_code	  retval;
12987c478bd9Sstevel@tonic-gate     krb5_ticket		* ticket;
12997c478bd9Sstevel@tonic-gate     struct sockaddr_storage	  r_ss;
13007c478bd9Sstevel@tonic-gate     int			  ss_length;
13017c478bd9Sstevel@tonic-gate     krb5_keytab		  keytab = NULL;
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate     /*
13047c478bd9Sstevel@tonic-gate      * Set recv_addr and send_addr
13057c478bd9Sstevel@tonic-gate      */
13067c478bd9Sstevel@tonic-gate     if (cvtkaddr(&ss, &sender_addr) == NULL) {
13077c478bd9Sstevel@tonic-gate 	com_err(progname, errno,
13087c478bd9Sstevel@tonic-gate 		gettext("while converting socket address"));
13097c478bd9Sstevel@tonic-gate 	exit(1);
13107c478bd9Sstevel@tonic-gate     }
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate     ss_length = sizeof (r_ss);
13137c478bd9Sstevel@tonic-gate     if (getsockname(fd, (struct sockaddr *) &r_ss, &ss_length)) {
13147c478bd9Sstevel@tonic-gate 	com_err(progname, errno,
13157c478bd9Sstevel@tonic-gate 		gettext("while getting local socket address"));
13167c478bd9Sstevel@tonic-gate 	exit(1);
13177c478bd9Sstevel@tonic-gate     }
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate     if (cvtkaddr(&r_ss, &receiver_addr) == NULL) {
13207c478bd9Sstevel@tonic-gate 	com_err(progname, errno,
13217c478bd9Sstevel@tonic-gate 		gettext("while converting socket address"));
13227c478bd9Sstevel@tonic-gate 	exit(1);
13237c478bd9Sstevel@tonic-gate     }
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate     if (debug) {
13267c478bd9Sstevel@tonic-gate 	char *name;
132756a424ccSmp153739 
132856a424ccSmp153739 	retval = krb5_unparse_name(context, server, &name);
132956a424ccSmp153739 	if (retval) {
1330*7c64d375Smp153739 	    /* Solaris Kerberos: Keep error messages consistent */
1331*7c64d375Smp153739 	    com_err(progname, retval, gettext("while unparsing server name"));
13327c478bd9Sstevel@tonic-gate 	    exit(1);
13337c478bd9Sstevel@tonic-gate 	}
13347c478bd9Sstevel@tonic-gate 	printf(gettext("krb5_recvauth(%d, %s, %s, ...)\n"), fd, kprop_version,
13357c478bd9Sstevel@tonic-gate 	    name);
13367c478bd9Sstevel@tonic-gate 	free(name);
13377c478bd9Sstevel@tonic-gate     }
13387c478bd9Sstevel@tonic-gate 
133956a424ccSmp153739     retval = krb5_auth_con_init(context, &auth_context);
134056a424ccSmp153739     if (retval) {
13417c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("Error in krb5_auth_con_init: %s"),
13427c478bd9Sstevel@tonic-gate 	       error_message(retval));
13437c478bd9Sstevel@tonic-gate     	exit(1);
13447c478bd9Sstevel@tonic-gate     }
13457c478bd9Sstevel@tonic-gate 
134656a424ccSmp153739     retval = krb5_auth_con_setflags(context, auth_context,
134756a424ccSmp153739 				    KRB5_AUTH_CONTEXT_DO_SEQUENCE);
134856a424ccSmp153739     if (retval) {
13497c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("Error in krb5_auth_con_setflags: %s"),
13507c478bd9Sstevel@tonic-gate 	       error_message(retval));
13517c478bd9Sstevel@tonic-gate 	exit(1);
13527c478bd9Sstevel@tonic-gate     }
13537c478bd9Sstevel@tonic-gate 
135456a424ccSmp153739     retval = krb5_auth_con_setaddrs(context, auth_context, &receiver_addr,
135556a424ccSmp153739 				    &sender_addr);
135656a424ccSmp153739     if (retval) {
13577c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("Error in krb5_auth_con_setaddrs: %s"),
13587c478bd9Sstevel@tonic-gate 	       error_message(retval));
13597c478bd9Sstevel@tonic-gate 	exit(1);
13607c478bd9Sstevel@tonic-gate     }
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate     if (srvtab) {
136356a424ccSmp153739         retval = krb5_kt_resolve(context, srvtab, &keytab);
136456a424ccSmp153739 	if (retval) {
13657c478bd9Sstevel@tonic-gate 	  syslog(LOG_ERR, gettext("Error in krb5_kt_resolve: %s"), error_message(retval));
13667c478bd9Sstevel@tonic-gate 	  exit(1);
13677c478bd9Sstevel@tonic-gate 	}
13687c478bd9Sstevel@tonic-gate     }
13697c478bd9Sstevel@tonic-gate 
137056a424ccSmp153739     retval = krb5_recvauth(context, &auth_context, (void *) &fd,
137156a424ccSmp153739 			   kprop_version, server, 0, keytab, &ticket);
137256a424ccSmp153739     if (retval) {
137356a424ccSmp153739 	syslog(LOG_ERR, gettext("Error in krb5_recvauth: %s"), error_message(retval));
13747c478bd9Sstevel@tonic-gate 	exit(1);
13757c478bd9Sstevel@tonic-gate     }
13767c478bd9Sstevel@tonic-gate 
137756a424ccSmp153739     retval = krb5_copy_principal(context, ticket->enc_part2->client, clientp);
137856a424ccSmp153739     if (retval) {
13797c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("Error in krb5_copy_prinicpal: %s"),
13807c478bd9Sstevel@tonic-gate 	       error_message(retval));
13817c478bd9Sstevel@tonic-gate 	exit(1);
13827c478bd9Sstevel@tonic-gate     }
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate     *etype = ticket->enc_part.enctype;
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate     if (debug) {
13877c478bd9Sstevel@tonic-gate 	char * name;
13887c478bd9Sstevel@tonic-gate 	char etypebuf[100];
13897c478bd9Sstevel@tonic-gate 
139056a424ccSmp153739 	retval = krb5_unparse_name(context, *clientp, &name);
139156a424ccSmp153739 	if (retval) {
1392*7c64d375Smp153739 	    /* Solaris Kerberos: Keep error messages consistent */
13937c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
1394*7c64d375Smp153739 		gettext("while unparsing client name"));
13957c478bd9Sstevel@tonic-gate 	    exit(1);
13967c478bd9Sstevel@tonic-gate 	}
13977c478bd9Sstevel@tonic-gate 
139856a424ccSmp153739 	retval = krb5_enctype_to_string(*etype, etypebuf, sizeof(etypebuf));
139956a424ccSmp153739 	if (retval) {
1400*7c64d375Smp153739 	    /* Solaris Kerberos: Keep error messages consistent */
1401*7c64d375Smp153739 	    com_err(progname, retval, gettext("while unparsing ticket etype"));
14027c478bd9Sstevel@tonic-gate 	    exit(1);
14037c478bd9Sstevel@tonic-gate 	}
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 	printf("authenticated client: %s (etype == %s)\n", name, etypebuf);
14067c478bd9Sstevel@tonic-gate 	free(name);
14077c478bd9Sstevel@tonic-gate     }
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate     krb5_free_ticket(context, ticket);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate krb5_boolean
14137c478bd9Sstevel@tonic-gate authorized_principal(context, p, auth_etype)
14147c478bd9Sstevel@tonic-gate     krb5_context context;
14157c478bd9Sstevel@tonic-gate     krb5_principal p;
14167c478bd9Sstevel@tonic-gate     krb5_enctype auth_etype;
14177c478bd9Sstevel@tonic-gate {
14187c478bd9Sstevel@tonic-gate     char		*name, *ptr;
14197c478bd9Sstevel@tonic-gate     char		buf[1024];
14207c478bd9Sstevel@tonic-gate     krb5_error_code	retval;
14217c478bd9Sstevel@tonic-gate     FILE		*acl_file;
14227c478bd9Sstevel@tonic-gate     int			end;
14237c478bd9Sstevel@tonic-gate     krb5_enctype	acl_etype;
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, p, &name);
14267c478bd9Sstevel@tonic-gate     if (retval)
14277c478bd9Sstevel@tonic-gate 	return FALSE;
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate     acl_file = fopen(acl_file_name, "r");
14307c478bd9Sstevel@tonic-gate     if (!acl_file)
14317c478bd9Sstevel@tonic-gate 	return FALSE;
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate     while (!feof(acl_file)) {
14347c478bd9Sstevel@tonic-gate 	if (!fgets(buf, sizeof(buf), acl_file))
14357c478bd9Sstevel@tonic-gate 	    break;
14367c478bd9Sstevel@tonic-gate 	end = strlen(buf) - 1;
14377c478bd9Sstevel@tonic-gate 	if (buf[end] == '\n')
14387c478bd9Sstevel@tonic-gate 	    buf[end] = '\0';
14397c478bd9Sstevel@tonic-gate 	if (!strncmp(name, buf, strlen(name))) {
14407c478bd9Sstevel@tonic-gate 	    ptr = buf+strlen(name);
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 	    /* if the next character is not whitespace or nul, then
14437c478bd9Sstevel@tonic-gate 	       the match is only partial.  continue on to new lines. */
144456a424ccSmp153739 	    if (*ptr && !isspace((int) *ptr))
14457c478bd9Sstevel@tonic-gate 		continue;
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	    /* otherwise, skip trailing whitespace */
144856a424ccSmp153739 	    for (; *ptr && isspace((int) *ptr); ptr++) ;
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	    /* now, look for an etype string. if there isn't one,
14517c478bd9Sstevel@tonic-gate 	       return true.  if there is an invalid string, continue.
14527c478bd9Sstevel@tonic-gate 	       If there is a valid string, return true only if it
14537c478bd9Sstevel@tonic-gate 	       matches the etype passed in, otherwise continue */
14547c478bd9Sstevel@tonic-gate 
14557c478bd9Sstevel@tonic-gate 	    if ((*ptr) &&
14567c478bd9Sstevel@tonic-gate 		((retval = krb5_string_to_enctype(ptr, &acl_etype)) ||
14577c478bd9Sstevel@tonic-gate 		 (acl_etype != auth_etype)))
14587c478bd9Sstevel@tonic-gate 		continue;
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 	    free(name);
14617c478bd9Sstevel@tonic-gate 	    fclose(acl_file);
14627c478bd9Sstevel@tonic-gate 	    return TRUE;
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate     }
14657c478bd9Sstevel@tonic-gate     free(name);
14667c478bd9Sstevel@tonic-gate     fclose(acl_file);
14677c478bd9Sstevel@tonic-gate     return FALSE;
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate void
14717c478bd9Sstevel@tonic-gate recv_database(context, fd, database_fd, confmsg)
14727c478bd9Sstevel@tonic-gate     krb5_context context;
14737c478bd9Sstevel@tonic-gate     int	fd;
14747c478bd9Sstevel@tonic-gate     int	database_fd;
14757c478bd9Sstevel@tonic-gate     krb5_data *confmsg;
14767c478bd9Sstevel@tonic-gate {
147756a424ccSmp153739 	krb5_ui_4	database_size; /* This must be 4 bytes */
14787c478bd9Sstevel@tonic-gate 	int	received_size, n;
14797c478bd9Sstevel@tonic-gate 	char		buf[1024];
14807c478bd9Sstevel@tonic-gate 	krb5_data	inbuf, outbuf;
14817c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate 	/*
14847c478bd9Sstevel@tonic-gate 	 * Receive and decode size from client
14857c478bd9Sstevel@tonic-gate 	 */
148656a424ccSmp153739 	retval = krb5_read_message(context, (void *) &fd, &inbuf);
148756a424ccSmp153739 	if (retval) {
14887c478bd9Sstevel@tonic-gate 		send_error(context, fd, retval, gettext("while reading database size"));
14897c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
14907c478bd9Sstevel@tonic-gate 			gettext("while reading size of database from client"));
14917c478bd9Sstevel@tonic-gate 		exit(1);
14927c478bd9Sstevel@tonic-gate 	}
14937c478bd9Sstevel@tonic-gate 	if (krb5_is_krb_error(&inbuf))
14947c478bd9Sstevel@tonic-gate 		recv_error(context, &inbuf);
149556a424ccSmp153739 	retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL);
149656a424ccSmp153739 	if (retval) {
149756a424ccSmp153739 		send_error(context, fd, retval, gettext(
149856a424ccSmp153739 			   "while decoding database size"));
14997c478bd9Sstevel@tonic-gate 		krb5_free_data_contents(context, &inbuf);
15007c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
15017c478bd9Sstevel@tonic-gate 			gettext("while decoding database size from client"));
15027c478bd9Sstevel@tonic-gate 		exit(1);
15037c478bd9Sstevel@tonic-gate 	}
15047c478bd9Sstevel@tonic-gate 	memcpy((char *) &database_size, outbuf.data, sizeof(database_size));
15057c478bd9Sstevel@tonic-gate 	krb5_free_data_contents(context, &inbuf);
15067c478bd9Sstevel@tonic-gate 	krb5_free_data_contents(context, &outbuf);
15077c478bd9Sstevel@tonic-gate 	database_size = ntohl(database_size);
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 	/*
15107c478bd9Sstevel@tonic-gate 	 * Initialize the initial vector.
15117c478bd9Sstevel@tonic-gate 	 */
151256a424ccSmp153739 	retval = krb5_auth_con_initivector(context, auth_context);
151356a424ccSmp153739 	if (retval) {
151456a424ccSmp153739 	  send_error(context, fd, retval, gettext(
151556a424ccSmp153739 		     "failed while initializing i_vector"));
15167c478bd9Sstevel@tonic-gate 	  com_err(progname, retval, gettext("while initializing i_vector"));
15177c478bd9Sstevel@tonic-gate 	  exit(1);
15187c478bd9Sstevel@tonic-gate 	}
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate 	/*
15217c478bd9Sstevel@tonic-gate 	 * Now start receiving the database from the net
15227c478bd9Sstevel@tonic-gate 	 */
15237c478bd9Sstevel@tonic-gate 	received_size = 0;
15247c478bd9Sstevel@tonic-gate 	while (received_size < database_size) {
152556a424ccSmp153739 	        retval = krb5_read_message(context, (void *) &fd, &inbuf);
152656a424ccSmp153739 		if (retval) {
15277c478bd9Sstevel@tonic-gate 			snprintf(buf, sizeof (buf),
15287c478bd9Sstevel@tonic-gate 			gettext("while reading database block starting at offset %d"),
15297c478bd9Sstevel@tonic-gate 				received_size);
15307c478bd9Sstevel@tonic-gate 			com_err(progname, retval, buf);
15317c478bd9Sstevel@tonic-gate 			send_error(context, fd, retval, buf);
15327c478bd9Sstevel@tonic-gate 			exit(1);
15337c478bd9Sstevel@tonic-gate 		}
15347c478bd9Sstevel@tonic-gate 		if (krb5_is_krb_error(&inbuf))
15357c478bd9Sstevel@tonic-gate 			recv_error(context, &inbuf);
153656a424ccSmp153739 		retval = krb5_rd_priv(context, auth_context, &inbuf,
153756a424ccSmp153739 				      &outbuf, NULL);
153856a424ccSmp153739 		if (retval) {
15397c478bd9Sstevel@tonic-gate 			snprintf(buf, sizeof (buf),
15407c478bd9Sstevel@tonic-gate 		gettext("while decoding database block starting at offset %d"),
15417c478bd9Sstevel@tonic-gate 				received_size);
15427c478bd9Sstevel@tonic-gate 			com_err(progname, retval, buf);
15437c478bd9Sstevel@tonic-gate 			send_error(context, fd, retval, buf);
15447c478bd9Sstevel@tonic-gate 			krb5_free_data_contents(context, &inbuf);
15457c478bd9Sstevel@tonic-gate 			exit(1);
15467c478bd9Sstevel@tonic-gate 		}
15477c478bd9Sstevel@tonic-gate 		n = write(database_fd, outbuf.data, outbuf.length);
15487c478bd9Sstevel@tonic-gate 		if (n < 0) {
15497c478bd9Sstevel@tonic-gate 			snprintf(buf, sizeof (buf),
15507c478bd9Sstevel@tonic-gate 				gettext(
15517c478bd9Sstevel@tonic-gate "while writing database block starting at offset %d"),
15527c478bd9Sstevel@tonic-gate 				received_size);
15537c478bd9Sstevel@tonic-gate 			send_error(context, fd, errno, buf);
15547c478bd9Sstevel@tonic-gate 		} else if (n != outbuf.length) {
15557c478bd9Sstevel@tonic-gate 			snprintf(buf, sizeof (buf),
15567c478bd9Sstevel@tonic-gate 				gettext(
15577c478bd9Sstevel@tonic-gate "incomplete write while writing database block starting at\n"
15587c478bd9Sstevel@tonic-gate "offset %d (%d written, %d expected)"),
15597c478bd9Sstevel@tonic-gate 				received_size, n, outbuf.length);
15607c478bd9Sstevel@tonic-gate 			send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
15617c478bd9Sstevel@tonic-gate 		}
15627c478bd9Sstevel@tonic-gate 		received_size += outbuf.length;
15637c478bd9Sstevel@tonic-gate 		/* SUNWresync121: our krb5...contents sets length to 0 */
15647c478bd9Sstevel@tonic-gate 		krb5_free_data_contents(context, &inbuf);
15657c478bd9Sstevel@tonic-gate 		krb5_free_data_contents(context, &outbuf);
156656a424ccSmp153739 
15677c478bd9Sstevel@tonic-gate 	}
15687c478bd9Sstevel@tonic-gate 	/*
15697c478bd9Sstevel@tonic-gate 	 * OK, we've seen the entire file.  Did we get too many bytes?
15707c478bd9Sstevel@tonic-gate 	 */
15717c478bd9Sstevel@tonic-gate 	if (received_size > database_size) {
15727c478bd9Sstevel@tonic-gate 		snprintf(buf, sizeof (buf),
15737c478bd9Sstevel@tonic-gate 		gettext("Received %d bytes, expected %d bytes for database file"),
15747c478bd9Sstevel@tonic-gate 			received_size, database_size);
15757c478bd9Sstevel@tonic-gate 		send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
15767c478bd9Sstevel@tonic-gate 	}
15777c478bd9Sstevel@tonic-gate 	/*
15787c478bd9Sstevel@tonic-gate 	 * Create message acknowledging number of bytes received, but
15797c478bd9Sstevel@tonic-gate 	 * don't send it until kdb5_util returns successfully.
15807c478bd9Sstevel@tonic-gate 	 */
15817c478bd9Sstevel@tonic-gate 	database_size = htonl(database_size);
15827c478bd9Sstevel@tonic-gate 	inbuf.data = (char *) &database_size;
15837c478bd9Sstevel@tonic-gate 	inbuf.length = sizeof(database_size);
158456a424ccSmp153739 	retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL);
158556a424ccSmp153739 	if (retval) {
15867c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
15877c478bd9Sstevel@tonic-gate 			gettext("while encoding # of receieved bytes"));
15887c478bd9Sstevel@tonic-gate 		send_error(context, fd, retval,
15897c478bd9Sstevel@tonic-gate 			   gettext("while encoding # of received bytes"));
15907c478bd9Sstevel@tonic-gate 		exit(1);
15917c478bd9Sstevel@tonic-gate 	}
15927c478bd9Sstevel@tonic-gate }
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate void
15967c478bd9Sstevel@tonic-gate send_error(context, fd, err_code, err_text)
15977c478bd9Sstevel@tonic-gate     krb5_context context;
15987c478bd9Sstevel@tonic-gate     int	fd;
15997c478bd9Sstevel@tonic-gate     krb5_error_code	err_code;
16007c478bd9Sstevel@tonic-gate     char	*err_text;
16017c478bd9Sstevel@tonic-gate {
16027c478bd9Sstevel@tonic-gate 	krb5_error	error;
16037c478bd9Sstevel@tonic-gate 	const char	*text;
16047c478bd9Sstevel@tonic-gate 	krb5_data	outbuf;
16057c478bd9Sstevel@tonic-gate 	char		buf[1024];
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 	memset((char *)&error, 0, sizeof(error));
16087c478bd9Sstevel@tonic-gate 	krb5_us_timeofday(context, &error.stime, &error.susec);
16097c478bd9Sstevel@tonic-gate 	error.server = server;
16107c478bd9Sstevel@tonic-gate 	error.client = client;
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 	if (err_text)
16137c478bd9Sstevel@tonic-gate 		text = err_text;
16147c478bd9Sstevel@tonic-gate 	else
16157c478bd9Sstevel@tonic-gate 		text = error_message(err_code);
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	error.error = err_code - ERROR_TABLE_BASE_krb5;
16187c478bd9Sstevel@tonic-gate 	if (error.error > 127) {
16197c478bd9Sstevel@tonic-gate 		error.error = KRB_ERR_GENERIC;
16207c478bd9Sstevel@tonic-gate 		if (err_text) {
16217c478bd9Sstevel@tonic-gate 			sprintf(buf, "%s %s", error_message(err_code),
16227c478bd9Sstevel@tonic-gate 				err_text);
16237c478bd9Sstevel@tonic-gate 			text = buf;
16247c478bd9Sstevel@tonic-gate 		}
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 	error.text.length = strlen(text) + 1;
162756a424ccSmp153739 	error.text.data = malloc(error.text.length);
162856a424ccSmp153739 	if (error.text.data) {
16297c478bd9Sstevel@tonic-gate 		strcpy(error.text.data, text);
16307c478bd9Sstevel@tonic-gate 		if (!krb5_mk_error(context, &error, &outbuf)) {
16317c478bd9Sstevel@tonic-gate 			(void) krb5_write_message(context, (void *)&fd,&outbuf);
16327c478bd9Sstevel@tonic-gate 			krb5_free_data_contents(context, &outbuf);
16337c478bd9Sstevel@tonic-gate 		}
16347c478bd9Sstevel@tonic-gate 		free(error.text.data);
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate }
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate void
16397c478bd9Sstevel@tonic-gate recv_error(context, inbuf)
16407c478bd9Sstevel@tonic-gate     krb5_context context;
16417c478bd9Sstevel@tonic-gate     krb5_data	*inbuf;
16427c478bd9Sstevel@tonic-gate {
16437c478bd9Sstevel@tonic-gate 	krb5_error	*error;
16447c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
16457c478bd9Sstevel@tonic-gate 
164656a424ccSmp153739 	retval = krb5_rd_error(context, inbuf, &error);
164756a424ccSmp153739 	if (retval) {
16487c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
16497c478bd9Sstevel@tonic-gate 			gettext("while decoding error packet from client"));
16507c478bd9Sstevel@tonic-gate 		exit(1);
16517c478bd9Sstevel@tonic-gate 	}
16527c478bd9Sstevel@tonic-gate 	if (error->error == KRB_ERR_GENERIC) {
16537c478bd9Sstevel@tonic-gate 		if (error->text.data)
16547c478bd9Sstevel@tonic-gate 			fprintf(stderr,
16557c478bd9Sstevel@tonic-gate 				gettext("Generic remote error: %s\n"),
16567c478bd9Sstevel@tonic-gate 				error->text.data);
16577c478bd9Sstevel@tonic-gate 	} else if (error->error) {
16587c478bd9Sstevel@tonic-gate 		com_err(progname, error->error + ERROR_TABLE_BASE_krb5,
16597c478bd9Sstevel@tonic-gate 			gettext("signalled from server"));
16607c478bd9Sstevel@tonic-gate 		if (error->text.data)
16617c478bd9Sstevel@tonic-gate 			fprintf(stderr,
16627c478bd9Sstevel@tonic-gate 				gettext("Error text from client: %s\n"),
16637c478bd9Sstevel@tonic-gate 				error->text.data);
16647c478bd9Sstevel@tonic-gate 	}
16657c478bd9Sstevel@tonic-gate 	krb5_free_error(context, error);
16667c478bd9Sstevel@tonic-gate 	exit(1);
16677c478bd9Sstevel@tonic-gate }
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate void
167056a424ccSmp153739 load_database(context, kdb_util, database_file_name)
16717c478bd9Sstevel@tonic-gate     krb5_context context;
167256a424ccSmp153739     char *kdb_util;
16737c478bd9Sstevel@tonic-gate     char *database_file_name;
16747c478bd9Sstevel@tonic-gate {
16757c478bd9Sstevel@tonic-gate 	static char	*edit_av[10];
167656a424ccSmp153739 	int	error_ret, save_stderr = -1;
16777c478bd9Sstevel@tonic-gate 	int	child_pid;
16787c478bd9Sstevel@tonic-gate 	int 	count;
167956a424ccSmp153739 
168056a424ccSmp153739 	/* <sys/param.h> has been included, so BSD will be defined on
168156a424ccSmp153739 	   BSD systems */
168256a424ccSmp153739 #if BSD > 0 && BSD <= 43
168356a424ccSmp153739 #ifndef WEXITSTATUS
168456a424ccSmp153739 #define	WEXITSTATUS(w) (w).w_retcode
168556a424ccSmp153739 #endif
168656a424ccSmp153739 	union wait	waitb;
168756a424ccSmp153739 #else
16887c478bd9Sstevel@tonic-gate 	int	waitb;
168956a424ccSmp153739 #endif
16907c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
16917c478bd9Sstevel@tonic-gate 	kdb_log_context	*log_ctx;
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 	if (debug)
169456a424ccSmp153739 		printf(gettext("calling kdb_util to load database\n"));
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate 	log_ctx = context->kdblog_context;
16977c478bd9Sstevel@tonic-gate 
169856a424ccSmp153739 	edit_av[0] = kdb_util;
16997c478bd9Sstevel@tonic-gate 	count = 1;
17007c478bd9Sstevel@tonic-gate 	if (realm) {
17017c478bd9Sstevel@tonic-gate 		edit_av[count++] = "-r";
17027c478bd9Sstevel@tonic-gate 		edit_av[count++] = realm;
17037c478bd9Sstevel@tonic-gate 	}
17047c478bd9Sstevel@tonic-gate 	edit_av[count++] = "load";
17057c478bd9Sstevel@tonic-gate 	if (kerb_database) {
17067c478bd9Sstevel@tonic-gate 		edit_av[count++] = "-d";
17077c478bd9Sstevel@tonic-gate 		edit_av[count++] = kerb_database;
17087c478bd9Sstevel@tonic-gate 	}
17097c478bd9Sstevel@tonic-gate 
17107c478bd9Sstevel@tonic-gate 	if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
17117c478bd9Sstevel@tonic-gate 		edit_av[count++] = "-i";
17127c478bd9Sstevel@tonic-gate 	}
17137c478bd9Sstevel@tonic-gate 	edit_av[count++] = database_file_name;
17147c478bd9Sstevel@tonic-gate 	edit_av[count++] = NULL;
17157c478bd9Sstevel@tonic-gate 
17167c478bd9Sstevel@tonic-gate 	switch(child_pid = fork()) {
17177c478bd9Sstevel@tonic-gate 	case -1:
17187c478bd9Sstevel@tonic-gate 		com_err(progname, errno, gettext("while trying to fork %s"),
171956a424ccSmp153739 			kdb_util);
17207c478bd9Sstevel@tonic-gate 		exit(1);
17217c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
17227c478bd9Sstevel@tonic-gate 	case 0:
17237c478bd9Sstevel@tonic-gate 		if (!debug) {
17247c478bd9Sstevel@tonic-gate 			save_stderr = dup(2);
17257c478bd9Sstevel@tonic-gate 			close(0);
17267c478bd9Sstevel@tonic-gate 			close(1);
17277c478bd9Sstevel@tonic-gate 			close(2);
17287c478bd9Sstevel@tonic-gate 			open("/dev/null", O_RDWR);
17297c478bd9Sstevel@tonic-gate 			dup(0);
17307c478bd9Sstevel@tonic-gate 			dup(0);
17317c478bd9Sstevel@tonic-gate 		}
17327c478bd9Sstevel@tonic-gate 
173356a424ccSmp153739 		execv(kdb_util, edit_av);
17347c478bd9Sstevel@tonic-gate 		retval = errno;
17357c478bd9Sstevel@tonic-gate 		if (!debug)
17367c478bd9Sstevel@tonic-gate 			dup2(save_stderr, 2);
17377c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while trying to exec %s"),
173856a424ccSmp153739 			kdb_util);
17397c478bd9Sstevel@tonic-gate 		_exit(1);
17407c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
17417c478bd9Sstevel@tonic-gate 	default:
17427c478bd9Sstevel@tonic-gate 		if (debug)
17437c478bd9Sstevel@tonic-gate 		    printf(gettext("Child PID is %d\n"), child_pid);
17447c478bd9Sstevel@tonic-gate 		if (wait(&waitb) < 0) {
17457c478bd9Sstevel@tonic-gate 			com_err(progname, errno, gettext("while waiting for %s"),
174656a424ccSmp153739 				kdb_util);
17477c478bd9Sstevel@tonic-gate 			exit(1);
17487c478bd9Sstevel@tonic-gate 		}
17497c478bd9Sstevel@tonic-gate 	}
17507c478bd9Sstevel@tonic-gate 
175156a424ccSmp153739 	error_ret = WEXITSTATUS(waitb);
175256a424ccSmp153739 	if (error_ret) {
17537c478bd9Sstevel@tonic-gate 		com_err(progname, 0,
175456a424ccSmp153739 		    gettext("%s returned a bad exit status (%d)"),
175556a424ccSmp153739 			kdb_util, error_ret);
17567c478bd9Sstevel@tonic-gate 		exit(1);
17577c478bd9Sstevel@tonic-gate 	}
17587c478bd9Sstevel@tonic-gate 	return;
17597c478bd9Sstevel@tonic-gate }
1760