xref: /illumos-gate/usr/src/cmd/krb5/slave/kpropd.c (revision 83cba5f6)
17c478bd9Sstevel@tonic-gate /*
2f5918cfdS  * Copyright 2009 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 /*
297c478bd9Sstevel@tonic-gate  * slave/kpropd.c
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
327c478bd9Sstevel@tonic-gate  * All Rights Reserved.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
357c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
367c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
377c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
407c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
417c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
427c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
437c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
447c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
457c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
467c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
477c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
487c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
497c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
507c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
517c478bd9Sstevel@tonic-gate  * or implied warranty.
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * XXX We need to modify the protocol so that an acknowledge is set
557c478bd9Sstevel@tonic-gate  * after each block, instead after the entire series is sent over.
567c478bd9Sstevel@tonic-gate  * The reason for this is so that error packets can get interpreted
577c478bd9Sstevel@tonic-gate  * right away.  If you don't do this, the sender may never get the
587c478bd9Sstevel@tonic-gate  * error packet, because it will die an EPIPE trying to complete the
597c478bd9Sstevel@tonic-gate  * write...
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate 
6256a424ccSmp 
637c478bd9Sstevel@tonic-gate #include <stdio.h>
647c478bd9Sstevel@tonic-gate #include <ctype.h>
657c478bd9Sstevel@tonic-gate #include <sys/file.h>
667c478bd9Sstevel@tonic-gate #include <signal.h>
677c478bd9Sstevel@tonic-gate #include <string.h>
687c478bd9Sstevel@tonic-gate #include <fcntl.h>
697c478bd9Sstevel@tonic-gate #include <sys/types.h>
707c478bd9Sstevel@tonic-gate #include <sys/time.h>
717c478bd9Sstevel@tonic-gate #include <sys/stat.h>
727c478bd9Sstevel@tonic-gate #include <sys/socket.h>
737c478bd9Sstevel@tonic-gate #include <sys/wait.h>
747c478bd9Sstevel@tonic-gate #include <netinet/in.h>
757c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
767c478bd9Sstevel@tonic-gate #include <sys/param.h>
777c478bd9Sstevel@tonic-gate #include <netdb.h>
787c478bd9Sstevel@tonic-gate #include <syslog.h>
797c478bd9Sstevel@tonic-gate #include <libintl.h>
807c478bd9Sstevel@tonic-gate #include <locale.h>
817c478bd9Sstevel@tonic-gate #include <k5-int.h>
827c478bd9Sstevel@tonic-gate #include <socket-utils.h>
837c478bd9Sstevel@tonic-gate #include "com_err.h"
847c478bd9Sstevel@tonic-gate #include <errno.h>
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #include "kprop.h"
877c478bd9Sstevel@tonic-gate #include <iprop_hdr.h>
887c478bd9Sstevel@tonic-gate #include "iprop.h"
897c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
907c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h>
917c478bd9Sstevel@tonic-gate 
927c64d375Smp /* Solaris Kerberos */
937c64d375Smp #include <libgen.h>
947c64d375Smp 
957c478bd9Sstevel@tonic-gate #define SYSLOG_CLASS LOG_DAEMON
96*83cba5f6SPeter Shoults #define	INITIAL_TIMER 10
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate char *poll_time = NULL;
997c478bd9Sstevel@tonic-gate char *def_realm = NULL;
1007c478bd9Sstevel@tonic-gate boolean_t runonce = B_FALSE;
1017c478bd9Sstevel@tonic-gate 
102*83cba5f6SPeter Shoults /*
103*83cba5f6SPeter Shoults  * Global fd to close upon alarm time-out.
104*83cba5f6SPeter Shoults  */
105*83cba5f6SPeter Shoults volatile int gfd = -1;
106*83cba5f6SPeter Shoults 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * This struct simulates the use of _kadm5_server_handle_t
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate typedef struct _kadm5_iprop_handle_t {
1117c478bd9Sstevel@tonic-gate 	krb5_ui_4	magic_number;
1127c478bd9Sstevel@tonic-gate 	krb5_ui_4	struct_version;
1137c478bd9Sstevel@tonic-gate 	krb5_ui_4	api_version;
1147c478bd9Sstevel@tonic-gate 	char 		*cache_name;
1157c478bd9Sstevel@tonic-gate 	int		destroy_cache;
1167c478bd9Sstevel@tonic-gate 	CLIENT		*clnt;
1177c478bd9Sstevel@tonic-gate 	krb5_context	context;
1187c478bd9Sstevel@tonic-gate 	kadm5_config_params params;
1197c478bd9Sstevel@tonic-gate 	struct _kadm5_iprop_handle_t *lhandle;
1207c478bd9Sstevel@tonic-gate } *kadm5_iprop_handle_t;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static char *kprop_version = KPROP_PROT_VERSION;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate char	*progname;
1257c478bd9Sstevel@tonic-gate int     debug = 0;
1267c478bd9Sstevel@tonic-gate char	*srvtab = 0;
1277c478bd9Sstevel@tonic-gate int	standalone = 0;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate krb5_principal	server;		/* This is our server principal name */
1307c478bd9Sstevel@tonic-gate krb5_principal	client;		/* This is who we're talking to */
1317c478bd9Sstevel@tonic-gate krb5_context kpropd_context;
1327c478bd9Sstevel@tonic-gate krb5_auth_context auth_context;
1337c478bd9Sstevel@tonic-gate char	*realm = NULL;		/* Our realm */
1347c478bd9Sstevel@tonic-gate char	*file = KPROPD_DEFAULT_FILE;
1357c478bd9Sstevel@tonic-gate char	*temp_file_name;
1367c478bd9Sstevel@tonic-gate char	*kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
1377c478bd9Sstevel@tonic-gate char	*kerb_database = NULL;
1387c478bd9Sstevel@tonic-gate char	*acl_file_name = KPROPD_ACL_FILE;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate krb5_address	sender_addr;
1417c478bd9Sstevel@tonic-gate krb5_address	receiver_addr;
1427c478bd9Sstevel@tonic-gate short 		port = 0;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate void	PRS
1457c478bd9Sstevel@tonic-gate 	 (int, char**);
1467c478bd9Sstevel@tonic-gate int	do_standalone
1477c478bd9Sstevel@tonic-gate 	 (iprop_role iproprole);
1487c478bd9Sstevel@tonic-gate void	doit
14956a424ccSmp 	(int);
1507c478bd9Sstevel@tonic-gate krb5_error_code	do_iprop(kdb_log_context *log_ctx);
1517c478bd9Sstevel@tonic-gate 
152f5918cfdS /* Solaris Kerberos */
1537c478bd9Sstevel@tonic-gate void	kerberos_authenticate
15456a424ccSmp 	(krb5_context,
1557c478bd9Sstevel@tonic-gate 		   int,
1567c478bd9Sstevel@tonic-gate 		   krb5_principal *,
1577c478bd9Sstevel@tonic-gate 		   krb5_enctype *,
158f5918cfdS 		   struct sockaddr_storage *);
1597c478bd9Sstevel@tonic-gate krb5_boolean authorized_principal
16056a424ccSmp 	(krb5_context,
1617c478bd9Sstevel@tonic-gate     		   krb5_principal,
1627c478bd9Sstevel@tonic-gate 		   krb5_enctype);
1637c478bd9Sstevel@tonic-gate void	recv_database
16456a424ccSmp 	(krb5_context,
1657c478bd9Sstevel@tonic-gate 		   int,
1667c478bd9Sstevel@tonic-gate 		   int,
1677c478bd9Sstevel@tonic-gate 		   krb5_data *);
1687c478bd9Sstevel@tonic-gate void	load_database
16956a424ccSmp 	(krb5_context,
1707c478bd9Sstevel@tonic-gate     		   char *,
1717c478bd9Sstevel@tonic-gate     		   char *);
1727c478bd9Sstevel@tonic-gate void	send_error
17356a424ccSmp 	(krb5_context,
1747c478bd9Sstevel@tonic-gate     		   int,
1757c478bd9Sstevel@tonic-gate 		   krb5_error_code,
1767c478bd9Sstevel@tonic-gate     		   char	*);
1777c478bd9Sstevel@tonic-gate void	recv_error
17856a424ccSmp 	(krb5_context,
1797c478bd9Sstevel@tonic-gate     		   krb5_data *);
1807c478bd9Sstevel@tonic-gate int	convert_polltime
1817c478bd9Sstevel@tonic-gate 	(char *);
1827c478bd9Sstevel@tonic-gate unsigned int	backoff_from_master
1837c478bd9Sstevel@tonic-gate 	(int *);
1847c478bd9Sstevel@tonic-gate 
usage()1857c478bd9Sstevel@tonic-gate static void usage()
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1887c478bd9Sstevel@tonic-gate 		gettext("\nUsage: %s\n"), /* progname may be a long pathname */
1897c478bd9Sstevel@tonic-gate 		progname);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1927c478bd9Sstevel@tonic-gate 		gettext("\t[-r realm] [-s srvtab] [-dS] [-f slave_file]\n"));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1957c478bd9Sstevel@tonic-gate 		gettext("\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n"));
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\t[-P port] [-a acl_file]\n"));
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	exit(1);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate int
main(argc,argv)2037c478bd9Sstevel@tonic-gate main(argc, argv)
2047c478bd9Sstevel@tonic-gate 	int	argc;
2057c478bd9Sstevel@tonic-gate 	char	**argv;
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 	krb5_error_code retval;
2087c478bd9Sstevel@tonic-gate 	int ret = 0;
2097c478bd9Sstevel@tonic-gate 	kdb_log_context	*log_ctx;
21054925bf6Swillf 	int iprop_supported;
2117c64d375Smp 	krb5_boolean is_master = FALSE;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	PRS(argc, argv);
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	log_ctx = kpropd_context->kdblog_context;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
2187c478bd9Sstevel@tonic-gate 		/*
2197c478bd9Sstevel@tonic-gate 		 * We wanna do iprop !
2207c478bd9Sstevel@tonic-gate 		 */
22154925bf6Swillf 		retval = krb5_db_supports_iprop(kpropd_context,
22254925bf6Swillf 		    &iprop_supported);
22354925bf6Swillf 		if (retval) {
2247c64d375Smp 			/* Solaris Kerberos: Keep error messages consistent */
22554925bf6Swillf 			com_err(progname, retval,
2267c64d375Smp 				gettext("while determining if dbmodule plugin "
2277c64d375Smp 					    "supports iprop"));
22854925bf6Swillf 			exit(1);
22954925bf6Swillf 		}
23054925bf6Swillf 		if (!iprop_supported) {
2317c64d375Smp 			/* Solaris Kerberos: Keep error messages consistent */
2327c64d375Smp 			com_err(progname, 0,
23354925bf6Swillf 				gettext("Current dbmodule plugin does not support "
2347c64d375Smp 				    "iprop"));
2357c64d375Smp 			exit(1);
2367c64d375Smp 		}
2377c64d375Smp 
2387c64d375Smp 		/*
2397c64d375Smp 		 * Solaris Kerberos:
2407c64d375Smp 		 * Ensure that kpropd is only run on a slave
2417c64d375Smp 		 */
2427c64d375Smp 		if (retval = kadm5_is_master(kpropd_context, def_realm,
2437c64d375Smp 		    &is_master)) {
2447c64d375Smp 			com_err(progname, retval,
2457c64d375Smp 			    gettext("while trying to determine whether host is "
2467c64d375Smp 			    "master KDC for realm %s"), def_realm);
2477c64d375Smp 			exit(1);
2487c64d375Smp 		}
2497c64d375Smp 
2507c64d375Smp 		if (is_master == TRUE) {
2517c64d375Smp 			char *master = NULL;
2527c64d375Smp 			kadm5_get_master(kpropd_context, def_realm, &master);
2537c64d375Smp 
2547c64d375Smp 			com_err(progname, 0,
2557c64d375Smp 			    gettext("%s is the master KDC for the realm %s. "
2567c64d375Smp 			    "%s can only be run on a slave KDC"),
2577c64d375Smp 			    master ? master : "unknown", def_realm, progname);
25854925bf6Swillf 			exit(1);
25954925bf6Swillf 		}
26054925bf6Swillf 
2617c478bd9Sstevel@tonic-gate 		retval = do_iprop(log_ctx);
2627c478bd9Sstevel@tonic-gate 		if (retval) {
2637c64d375Smp 			/* Solaris Kerberos: Keep error messages consistent */
2647c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
2657c64d375Smp 			    gettext("while doing iprop"));
2667c478bd9Sstevel@tonic-gate 			exit(1);
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	} else {
2707c64d375Smp 
2717c64d375Smp 		/*
2727c64d375Smp 		 * Solaris Kerberos:
2737c64d375Smp 		 * Ensure that the kpropd.acl file exists and contains at least
2747c64d375Smp 		 * 1 entry.
2757c64d375Smp 		 */
2767c64d375Smp 		FILE *tmp_acl_file;
2777c64d375Smp 		int seen_file = 0;
2787c64d375Smp 		char buf[1024];
2797c64d375Smp 
2807c64d375Smp 		tmp_acl_file = fopen(acl_file_name, "r");
2817c64d375Smp 		if (!tmp_acl_file) {
2827c64d375Smp 			com_err(progname, errno,
2837c64d375Smp 			    gettext("while opening acl file %s"),
2847c64d375Smp 			    acl_file_name);
2857c64d375Smp 			exit(1);
2867c64d375Smp 		}
2877c64d375Smp 
2887c64d375Smp 		while (!feof(tmp_acl_file) && !seen_file ) {
2897c64d375Smp 			if (!fgets(buf, sizeof(buf), tmp_acl_file))
2907c64d375Smp 				break;
2917c64d375Smp 
2927c64d375Smp 			if (buf[0] != '#' && !isspace(buf[0]))
2937c64d375Smp 				seen_file = 1;
2947c64d375Smp 		}
2957c64d375Smp 		if (!seen_file) {
2967c64d375Smp 			com_err(progname, 0,
2977c64d375Smp 			    gettext("No entries found in %s. Can't "
2987c64d375Smp 			    "authorize propagation requests"), acl_file_name);
2997c64d375Smp 			exit(1);
3007c64d375Smp 		}
3017c64d375Smp 		fclose(tmp_acl_file);
3027c64d375Smp 
3037c478bd9Sstevel@tonic-gate 		if (standalone)
3047c478bd9Sstevel@tonic-gate 			ret = do_standalone(IPROP_NULL);
3057c478bd9Sstevel@tonic-gate 		else
3067c478bd9Sstevel@tonic-gate 			doit(0);
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	exit(ret);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
resync_alarm(int sn)312*83cba5f6SPeter Shoults void resync_alarm(int sn)
313*83cba5f6SPeter Shoults {
314*83cba5f6SPeter Shoults 	close(gfd);
315*83cba5f6SPeter Shoults 	if (debug)
316*83cba5f6SPeter Shoults 		fprintf(stderr, gettext("resync_alarm: closing fd: %d\n"), gfd);
317*83cba5f6SPeter Shoults 	gfd = -1;
318*83cba5f6SPeter Shoults }
319*83cba5f6SPeter Shoults 
do_standalone(iprop_role iproprole)3207c478bd9Sstevel@tonic-gate int do_standalone(iprop_role iproprole)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate     struct	linger linger;
3237c478bd9Sstevel@tonic-gate     struct	servent *sp;
3247c478bd9Sstevel@tonic-gate     int	finet, fromlen, s;
3257c478bd9Sstevel@tonic-gate     int	on = 1;
3267c478bd9Sstevel@tonic-gate     int	ret, status = 0;
3277c478bd9Sstevel@tonic-gate     struct	sockaddr_in6 sin6 = { AF_INET6 };
3287c478bd9Sstevel@tonic-gate     int sin6_size = sizeof (sin6);
329*83cba5f6SPeter Shoults     /*
330*83cba5f6SPeter Shoults      * Timer for accept/read calls, in case of network type errors.
331*83cba5f6SPeter Shoults      */
332*83cba5f6SPeter Shoults     int backoff_timer = INITIAL_TIMER;
333*83cba5f6SPeter Shoults 
334*83cba5f6SPeter Shoults retry:
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate     /* listen for either ipv4 or ipv6 */
3377c478bd9Sstevel@tonic-gate     finet = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
3387c478bd9Sstevel@tonic-gate     if (finet < 0 ) {
3397c478bd9Sstevel@tonic-gate 	com_err(progname, errno, gettext("while obtaining socket"));
3407c478bd9Sstevel@tonic-gate 	exit(1);
3417c478bd9Sstevel@tonic-gate     }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate     if(!port) {
3447c478bd9Sstevel@tonic-gate 	sp = getservbyname(KPROP_SERVICE, "tcp");
3457c478bd9Sstevel@tonic-gate 	if (sp == NULL) {
3467c478bd9Sstevel@tonic-gate 	    com_err(progname, 0, gettext("%s/tcp: unknown service"),
3477c478bd9Sstevel@tonic-gate 		    KPROP_SERVICE);
3487c478bd9Sstevel@tonic-gate 	    exit(1);
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 	sin6.sin6_port = sp->s_port;
3517c478bd9Sstevel@tonic-gate     } else
3527c478bd9Sstevel@tonic-gate 	sin6.sin6_port = port;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate     /*
3557c478bd9Sstevel@tonic-gate      * We need to close the socket immediately if iprop is enabled,
3567c478bd9Sstevel@tonic-gate      * since back-to-back full resyncs are possible, so we do not
3577c478bd9Sstevel@tonic-gate      * linger around for too long
3587c478bd9Sstevel@tonic-gate      */
3597c478bd9Sstevel@tonic-gate     if (iproprole == IPROP_SLAVE) {
3607c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3617c478bd9Sstevel@tonic-gate 			(char *)&on, sizeof(on)) < 0)
3627c478bd9Sstevel@tonic-gate 		    com_err(progname, errno,
3637c64d375Smp 			    gettext("while setting socket option (SO_REUSEADDR)"));
3647c478bd9Sstevel@tonic-gate 	    linger.l_onoff = 1;
3657c478bd9Sstevel@tonic-gate 	    linger.l_linger = 2;
3667c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_LINGER,
3677c478bd9Sstevel@tonic-gate 			(void *)&linger, sizeof(linger)) < 0)
3687c478bd9Sstevel@tonic-gate 		    com_err(progname, errno,
3697c64d375Smp 			    gettext("while setting socket option (SO_LINGER)"));
370*83cba5f6SPeter Shoults 	    /*
371*83cba5f6SPeter Shoults 	     * We also want to set a timer so that the slave is not waiting
372*83cba5f6SPeter Shoults 	     * until infinity for an update from the master.
373*83cba5f6SPeter Shoults 	     */
374*83cba5f6SPeter Shoults 	    gfd = finet;
375*83cba5f6SPeter Shoults 	    signal(SIGALRM, resync_alarm);
376*83cba5f6SPeter Shoults 	    if (debug) {
377*83cba5f6SPeter Shoults 		fprintf(stderr, "do_standalone: setting resync alarm to %d\n",
378*83cba5f6SPeter Shoults 		    backoff_timer);
379*83cba5f6SPeter Shoults 	    }
380*83cba5f6SPeter Shoults 	    if (alarm(backoff_timer) != 0) {
381*83cba5f6SPeter Shoults 		if (debug) {
382*83cba5f6SPeter Shoults 		    fprintf(stderr,
383*83cba5f6SPeter Shoults 			gettext("%s: alarm already set\n"), progname);
384*83cba5f6SPeter Shoults 		}
385*83cba5f6SPeter Shoults 	    }
386*83cba5f6SPeter Shoults 	    backoff_timer *= 2;
3877c478bd9Sstevel@tonic-gate     }
3887c478bd9Sstevel@tonic-gate     if ((ret = bind(finet, (struct sockaddr *)&sin6, sizeof(sin6))) < 0) {
3897c478bd9Sstevel@tonic-gate 	if (debug) {
3907c478bd9Sstevel@tonic-gate 	    on = 1;
3917c478bd9Sstevel@tonic-gate 	    fprintf(stderr,
3927c478bd9Sstevel@tonic-gate 		    gettext("%s: attempting to rebind socket "
3937c478bd9Sstevel@tonic-gate 		    "with SO_REUSEADDR\n"), progname);
3947c478bd9Sstevel@tonic-gate 	    if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3957c478bd9Sstevel@tonic-gate 			(char *)&on, sizeof(on)) < 0) {
3967c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
3977c64d375Smp 			gettext("while setting socket option (SO_REUSEADDR)"));
3987c478bd9Sstevel@tonic-gate 	    }
3997c478bd9Sstevel@tonic-gate 	    ret = bind(finet, (struct sockaddr *) &sin6, sizeof(sin6));
40056a424ccSmp 	    }
4017c478bd9Sstevel@tonic-gate 
40256a424ccSmp 	    if (ret < 0) {
4037c64d375Smp 	/*
4047c64d375Smp 	 * Solaris Kerberos:
4057c64d375Smp 	 * com_err will print the err msg associated with errno
4067c64d375Smp 	 */
4077c64d375Smp #if 0
40856a424ccSmp 		perror(gettext("bind"));
4097c64d375Smp #endif
41056a424ccSmp 		com_err(progname, errno,
4117c478bd9Sstevel@tonic-gate 		    gettext("while binding listener socket"));
41256a424ccSmp 		exit(1);
41356a424ccSmp 	    }
4147c478bd9Sstevel@tonic-gate 	}
4157c64d375Smp 	if (!debug && (iproprole != IPROP_SLAVE)) {
4167c64d375Smp 	/* Solaris Kerberos: Indicate where further messages will be sent */
4177c64d375Smp 		fprintf(stderr,
4187c64d375Smp 		    gettext("%s: Logging to SYSLOG with LOG_DAEMON facility\n"),
4197c64d375Smp 		    progname);
4207c64d375Smp 		if (daemon(1, 0)) {
4217c64d375Smp 			com_err(progname, errno, gettext("while daemonizing"));
4227c64d375Smp 			exit(1);
4237c64d375Smp 		}
4247c64d375Smp 		rem_default_com_err_hook();
4257c64d375Smp 	}
4267c64d375Smp 
4277c478bd9Sstevel@tonic-gate #ifdef PID_FILE
42856a424ccSmp 	if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
42956a424ccSmp 		fprintf(pidfile, gettext("%d\n"), getpid());
43056a424ccSmp 		fclose(pidfile);
43156a424ccSmp 	} else
43256a424ccSmp 		com_err(progname, errno,
4337c478bd9Sstevel@tonic-gate 		gettext("while opening pid file %s for writing"),
4347c478bd9Sstevel@tonic-gate 		PID_FILE);
4357c478bd9Sstevel@tonic-gate #endif
43656a424ccSmp 	if (listen(finet, 5) < 0) {
4377c64d375Smp 		/* Solaris Kerberos: Keep error messages consistent */
4387c64d375Smp 		com_err(progname, errno, gettext("while listening on socket"));
43956a424ccSmp 		exit(1);
4407c478bd9Sstevel@tonic-gate 	}
44156a424ccSmp 	while (1) {
44256a424ccSmp 		int child_pid;
4437c478bd9Sstevel@tonic-gate 
44456a424ccSmp 		s = accept(finet, (struct sockaddr *) &sin6, &sin6_size);
4457c478bd9Sstevel@tonic-gate 
44656a424ccSmp 		if (s < 0) {
447*83cba5f6SPeter Shoults 			int e = errno;
448*83cba5f6SPeter Shoults 			if (e != EINTR) {
449*83cba5f6SPeter Shoults 				/*
450*83cba5f6SPeter Shoults 				 * Solaris Kerberos: Keep error messages
451*83cba5f6SPeter Shoults 				 * consistent
452*83cba5f6SPeter Shoults 				 */
453*83cba5f6SPeter Shoults 				com_err(progname, e,
454*83cba5f6SPeter Shoults 				    gettext("while accepting connection"));
455*83cba5f6SPeter Shoults 				backoff_timer = INITIAL_TIMER;
4567c64d375Smp 			}
457*83cba5f6SPeter Shoults 			/*
458*83cba5f6SPeter Shoults 			 * If we got EBADF, an alarm signal handler closed
459*83cba5f6SPeter Shoults 			 * the file descriptor on us.
460*83cba5f6SPeter Shoults 			 */
461*83cba5f6SPeter Shoults 			if (e != EBADF)
462*83cba5f6SPeter Shoults 				close(finet);
463*83cba5f6SPeter Shoults 			/*
464*83cba5f6SPeter Shoults 			 * An alarm could have been set and the fd closed, we
465*83cba5f6SPeter Shoults 			 * should retry in case of transient network error for
466*83cba5f6SPeter Shoults 			 * up to a couple of minutes.
467*83cba5f6SPeter Shoults 			 */
468*83cba5f6SPeter Shoults 			if (backoff_timer > 120)
469*83cba5f6SPeter Shoults 				return (EINTR);
470*83cba5f6SPeter Shoults 			goto retry;
47156a424ccSmp 		}
472*83cba5f6SPeter Shoults 		alarm(0);
473*83cba5f6SPeter Shoults 		gfd = -1;
47456a424ccSmp 		if (debug && (iproprole != IPROP_SLAVE))
47556a424ccSmp 			child_pid = 0;
47656a424ccSmp 		else
47756a424ccSmp 			child_pid = fork();
47856a424ccSmp 		switch (child_pid) {
47956a424ccSmp 		case -1:
48056a424ccSmp 			com_err(progname, errno, gettext("while forking"));
48156a424ccSmp 			exit(1);
4827c478bd9Sstevel@tonic-gate 	    /*NOTREACHED*/
48356a424ccSmp 		case 0:
4847c478bd9Sstevel@tonic-gate 	    /* child */
48556a424ccSmp 			(void) close(finet);
48656a424ccSmp 
48756a424ccSmp 			doit(s);
48856a424ccSmp 			close(s);
48956a424ccSmp 			_exit(0);
4907c478bd9Sstevel@tonic-gate 	    /*NOTREACHED*/
49156a424ccSmp 		default:
4927c478bd9Sstevel@tonic-gate 	    /* parent */
493*83cba5f6SPeter Shoults 	    /*
494*83cba5f6SPeter Shoults 	     * Errors should not be considered fatal in the iprop case as we
495*83cba5f6SPeter Shoults 	     * could have transient type errors, such as network outage, etc.
496*83cba5f6SPeter Shoults 	     * Sleeping 3s for 2s linger interval.
497*83cba5f6SPeter Shoults 	     */
4987c478bd9Sstevel@tonic-gate 	    if (wait(&status) < 0) {
4997c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
5007c478bd9Sstevel@tonic-gate 		    gettext("while waiting to receive database"));
501*83cba5f6SPeter Shoults 		if (iproprole != IPROP_SLAVE)
502*83cba5f6SPeter Shoults 		    exit(1);
503*83cba5f6SPeter Shoults 		sleep(3);
5047c478bd9Sstevel@tonic-gate 	    }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	    close(s);
5077c478bd9Sstevel@tonic-gate 	    if (iproprole == IPROP_SLAVE)
5087c478bd9Sstevel@tonic-gate 		close(finet);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	    if ((ret = WEXITSTATUS(status)) != 0)
5117c478bd9Sstevel@tonic-gate 		return (ret);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if (iproprole == IPROP_SLAVE)
5157c478bd9Sstevel@tonic-gate 	    break;
5167c478bd9Sstevel@tonic-gate     }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate     return (0);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
doit(fd)5217c478bd9Sstevel@tonic-gate void doit(fd)
5227c478bd9Sstevel@tonic-gate 	int	fd;
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	struct sockaddr_storage from;
5257c478bd9Sstevel@tonic-gate 	socklen_t fromlen;
5267c478bd9Sstevel@tonic-gate 	int on = 1;
5277c478bd9Sstevel@tonic-gate 	struct hostent	*hp;
5287c478bd9Sstevel@tonic-gate 	krb5_error_code	retval;
5297c478bd9Sstevel@tonic-gate 	krb5_data confmsg;
5307c478bd9Sstevel@tonic-gate 	int lock_fd;
53156a424ccSmp 	mode_t omask;
5327c478bd9Sstevel@tonic-gate 	krb5_enctype etype;
53356a424ccSmp 	int database_fd;
5347c478bd9Sstevel@tonic-gate 	char ntop[NI_MAXHOST] = "";
5357c478bd9Sstevel@tonic-gate 	krb5_context doit_context;
5367c478bd9Sstevel@tonic-gate 	kdb_log_context *log_ctx;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	retval = krb5_init_context(&doit_context);
5397c478bd9Sstevel@tonic-gate 	if (retval) {
5407c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while initializing krb5"));
5417c478bd9Sstevel@tonic-gate 		exit(1);
5427c478bd9Sstevel@tonic-gate 	}
5437c478bd9Sstevel@tonic-gate 	log_ctx = kpropd_context->kdblog_context;
544*83cba5f6SPeter Shoults 	if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
5457c478bd9Sstevel@tonic-gate 		ulog_set_role(doit_context, IPROP_SLAVE);
546*83cba5f6SPeter Shoults 		/*
547*83cba5f6SPeter Shoults 		 * We also want to set a timer so that the slave is not waiting
548*83cba5f6SPeter Shoults 		 * until infinity for an update from the master.
549*83cba5f6SPeter Shoults 		 */
550*83cba5f6SPeter Shoults 		if (debug)
551*83cba5f6SPeter Shoults 			fprintf(stderr, "doit: setting resync alarm to %ds\n",
552*83cba5f6SPeter Shoults 			    INITIAL_TIMER);
553*83cba5f6SPeter Shoults 		signal(SIGALRM, resync_alarm);
554*83cba5f6SPeter Shoults 		gfd = fd;
555*83cba5f6SPeter Shoults 		if (alarm(INITIAL_TIMER) != 0) {
556*83cba5f6SPeter Shoults 			if (debug) {
557*83cba5f6SPeter Shoults 				fprintf(stderr,
558*83cba5f6SPeter Shoults 				    gettext("%s: alarm already set\n"), progname);
559*83cba5f6SPeter Shoults 			}
560*83cba5f6SPeter Shoults 		}
561*83cba5f6SPeter Shoults 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	fromlen = (socklen_t)sizeof (from);
5647c478bd9Sstevel@tonic-gate 	if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) {
5657c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: ", progname);
5667c478bd9Sstevel@tonic-gate 		perror(gettext("getpeername"));
5677c478bd9Sstevel@tonic-gate 		exit(1);
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate 	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (caddr_t) &on,
5707c478bd9Sstevel@tonic-gate 		       sizeof (on)) < 0) {
5717c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
5727c478bd9Sstevel@tonic-gate 		gettext("while attempting setsockopt (SO_KEEPALIVE)"));
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
5767c478bd9Sstevel@tonic-gate 		NULL, 0, NI_NUMERICHOST) != 0) {
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		/* getnameifo failed so use inet_ntop() to get printable addresses */
5797c478bd9Sstevel@tonic-gate 		if (from.ss_family == AF_INET) {
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET,
5827c478bd9Sstevel@tonic-gate 			    (const void *)&ss2sin(&from)->sin_addr,
5837c478bd9Sstevel@tonic-gate 			    ntop, sizeof(ntop));
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 		} else if (from.ss_family == AF_INET6 &&
5867c478bd9Sstevel@tonic-gate 			! IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 			ipaddr_t v4addr;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET6,
5917c478bd9Sstevel@tonic-gate 				(const void *)&ss2sin6(&from)->sin6_addr, ntop,
5927c478bd9Sstevel@tonic-gate 				sizeof(ntop));
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 		/* ipv4 mapped ipv6 addrs handled later */
5957c478bd9Sstevel@tonic-gate 	}
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	if (from.ss_family == AF_INET || from.ss_family == AF_INET6) {
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 		if (from.ss_family == AF_INET6 &&
6007c478bd9Sstevel@tonic-gate 			IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			ipaddr_t v4addr;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 			/* coerce ipv4 mapped ipv6 addr to normal ipv4 addr */
6057c478bd9Sstevel@tonic-gate 			IN6_V4MAPPED_TO_IPADDR(&(ss2sin6(&from)->sin6_addr),
6067c478bd9Sstevel@tonic-gate 				v4addr);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 			inet_ntop(AF_INET, (const void *) &v4addr,
6097c478bd9Sstevel@tonic-gate 				ntop, sizeof(ntop));
6107c478bd9Sstevel@tonic-gate 		}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO, gettext("Connection from %s"), ntop);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 		if (debug)
6157c478bd9Sstevel@tonic-gate 			printf("Connection from %s\n", ntop);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	} else {
6187c478bd9Sstevel@tonic-gate 		/* address family isn't either AF_INET || AF_INET6 */
6197c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO,
6207c478bd9Sstevel@tonic-gate 		    gettext("Connection from unknown address family:%d"),
6217c478bd9Sstevel@tonic-gate 		    from.ss_family);
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 		if (debug) {
6247c478bd9Sstevel@tonic-gate 			printf(gettext("Connection from unknown address family:%d"),
6257c478bd9Sstevel@tonic-gate 			    from.ss_family);
6267c478bd9Sstevel@tonic-gate 		}
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/*
6307c478bd9Sstevel@tonic-gate 	 * Now do the authentication
6317c478bd9Sstevel@tonic-gate 	 */
632f5918cfdS 	/* Solaris Kerberos */
633f5918cfdS 	kerberos_authenticate(doit_context, fd, &client, &etype, &from);
6347c478bd9Sstevel@tonic-gate 
635*83cba5f6SPeter Shoults 	/*
636*83cba5f6SPeter Shoults 	 * Turn off alarm upon successful authentication from master.
637*83cba5f6SPeter Shoults 	 */
638*83cba5f6SPeter Shoults 	alarm(0);
639*83cba5f6SPeter Shoults 	gfd = -1;
640*83cba5f6SPeter Shoults 
6417c478bd9Sstevel@tonic-gate 	if (!authorized_principal(doit_context, client, etype)) {
64256a424ccSmp 		char	*name;
6437c478bd9Sstevel@tonic-gate 
64456a424ccSmp 		retval = krb5_unparse_name(doit_context, client, &name);
64556a424ccSmp 		if (retval) {
6467c64d375Smp 			/* Solaris Kerberos: Keep error messages consistent */
64756a424ccSmp 			com_err(progname, retval,
6487c64d375Smp 		    gettext("while unparsing client name"));
64956a424ccSmp 			exit(1);
65056a424ccSmp 		}
65156a424ccSmp 		syslog(LOG_WARNING,
6527c478bd9Sstevel@tonic-gate 		gettext("Rejected connection from unauthorized principal %s"),
65356a424ccSmp 		       name);
65456a424ccSmp 		free(name);
65556a424ccSmp 		exit(1);
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate 	omask = umask(077);
6587c478bd9Sstevel@tonic-gate 	lock_fd = open(temp_file_name, O_RDWR|O_CREAT, 0600);
6597c478bd9Sstevel@tonic-gate 	(void) umask(omask);
6607c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd,
6617c478bd9Sstevel@tonic-gate 				KRB5_LOCKMODE_EXCLUSIVE|KRB5_LOCKMODE_DONTBLOCK);
6627c478bd9Sstevel@tonic-gate 	if (retval) {
6637c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
6647c478bd9Sstevel@tonic-gate 			gettext("while trying to lock '%s'"),
6657c478bd9Sstevel@tonic-gate 		    temp_file_name);
6667c478bd9Sstevel@tonic-gate 	    exit(1);
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate 	if ((database_fd = open(temp_file_name,
6697c478bd9Sstevel@tonic-gate 				O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
6707c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
6717c478bd9Sstevel@tonic-gate 			gettext("while opening database file, '%s'"),
6727c478bd9Sstevel@tonic-gate 			temp_file_name);
6737c478bd9Sstevel@tonic-gate 		exit(1);
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 	recv_database(doit_context, fd, database_fd, &confmsg);
6767c478bd9Sstevel@tonic-gate 	if (rename(temp_file_name, file)) {
6777c64d375Smp 		/* Solaris Kerberos: Keep error messages consistent */
6787c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
6797c64d375Smp 			gettext("while renaming %s to %s"),
6807c478bd9Sstevel@tonic-gate 			temp_file_name, file);
6817c478bd9Sstevel@tonic-gate 		exit(1);
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_SHARED);
6847c478bd9Sstevel@tonic-gate 	if (retval) {
6857c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
6867c478bd9Sstevel@tonic-gate 			gettext("while downgrading lock on '%s'"),
6877c478bd9Sstevel@tonic-gate 		    temp_file_name);
6887c478bd9Sstevel@tonic-gate 	    exit(1);
6897c478bd9Sstevel@tonic-gate 	}
6907c478bd9Sstevel@tonic-gate 	load_database(doit_context, kdb5_util, file);
6917c478bd9Sstevel@tonic-gate 	retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_UNLOCK);
6927c478bd9Sstevel@tonic-gate 	if (retval) {
6937c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
6947c478bd9Sstevel@tonic-gate 		gettext("while unlocking '%s'"), temp_file_name);
6957c478bd9Sstevel@tonic-gate 	    exit(1);
6967c478bd9Sstevel@tonic-gate 	}
6977c478bd9Sstevel@tonic-gate 	(void)close(lock_fd);
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	/*
7007c478bd9Sstevel@tonic-gate 	 * Send the acknowledgement message generated in
7017c478bd9Sstevel@tonic-gate 	 * recv_database, then close the socket.
7027c478bd9Sstevel@tonic-gate 	 */
70356a424ccSmp 	retval = krb5_write_message(doit_context, (void *) &fd, &confmsg);
70456a424ccSmp 	if (retval) {
7057c478bd9Sstevel@tonic-gate 		krb5_free_data_contents(doit_context, &confmsg);
7067c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
7077c478bd9Sstevel@tonic-gate 			gettext("while sending # of received bytes"));
7087c478bd9Sstevel@tonic-gate 		exit(1);
7097c478bd9Sstevel@tonic-gate 	}
7107c478bd9Sstevel@tonic-gate 	krb5_free_data_contents(doit_context, &confmsg);
7117c478bd9Sstevel@tonic-gate 	if (close(fd) < 0) {
7127c478bd9Sstevel@tonic-gate 		com_err(progname, errno,
7137c478bd9Sstevel@tonic-gate 			gettext("while trying to close database file"));
7147c478bd9Sstevel@tonic-gate 		exit(1);
7157c478bd9Sstevel@tonic-gate 	}
71656a424ccSmp 
7177c478bd9Sstevel@tonic-gate 	exit(0);
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate /*
7227c478bd9Sstevel@tonic-gate  * Routine to handle incremental update transfer(s) from master KDC
7237c478bd9Sstevel@tonic-gate  */
do_iprop(kdb_log_context * log_ctx)7247c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx) {
7257c478bd9Sstevel@tonic-gate 	CLIENT *cl;
7267c478bd9Sstevel@tonic-gate 	kadm5_ret_t retval;
7277c478bd9Sstevel@tonic-gate 	kadm5_config_params params;
7287c478bd9Sstevel@tonic-gate 	krb5_ccache cc;
7297c478bd9Sstevel@tonic-gate 	krb5_principal iprop_svc_principal;
7307c478bd9Sstevel@tonic-gate 	void *server_handle = NULL;
7317c478bd9Sstevel@tonic-gate 	char *iprop_svc_princstr = NULL;
7327c478bd9Sstevel@tonic-gate 	char *master_svc_princstr = NULL;
7337c478bd9Sstevel@tonic-gate 	char *admin_server = NULL;
7347c478bd9Sstevel@tonic-gate 	char *keytab_name = NULL;
7357c478bd9Sstevel@tonic-gate 	unsigned int pollin, backoff_time;
7367c478bd9Sstevel@tonic-gate 	int backoff_cnt = 0;
7377c478bd9Sstevel@tonic-gate 	int reinit_cnt = 0;
7387c478bd9Sstevel@tonic-gate 	int ret;
7397c478bd9Sstevel@tonic-gate 	boolean_t frdone = B_FALSE;
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	kdb_incr_result_t *incr_ret;
7427c478bd9Sstevel@tonic-gate 	static kdb_last_t mylast;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	kdb_fullresync_result_t *full_ret;
7457c478bd9Sstevel@tonic-gate 	char *full_resync_arg = NULL;
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	kadm5_iprop_handle_t handle;
7487c478bd9Sstevel@tonic-gate 	kdb_hlog_t *ulog;
7497c478bd9Sstevel@tonic-gate 
7507c64d375Smp 	krb5_keytab kt;
7517c64d375Smp 	krb5_keytab_entry entry;
7527c64d375Smp 	char kt_name[MAX_KEYTAB_NAME_LEN];
7537c64d375Smp 
7547c64d375Smp 	/*
7557c64d375Smp 	 * Solaris Kerberos:
7567c64d375Smp 	 * Delay daemonizing until some basic configuration checks have been
7577c64d375Smp 	 * performed
7587c64d375Smp 	 */
7597c64d375Smp #if 0
7607c478bd9Sstevel@tonic-gate 	if (!debug)
7617c478bd9Sstevel@tonic-gate 		daemon(0, 0);
7627c64d375Smp #endif
7637c478bd9Sstevel@tonic-gate 	pollin = (unsigned int)0;
7647c478bd9Sstevel@tonic-gate 	(void) memset((char *)&params, 0, sizeof (params));
7657c478bd9Sstevel@tonic-gate 	ulog = log_ctx->ulog;
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	params.mask |= KADM5_CONFIG_REALM;
7687c478bd9Sstevel@tonic-gate 	params.realm = def_realm;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 	if (master_svc_princstr == NULL) {
7717c478bd9Sstevel@tonic-gate 		if (retval = kadm5_get_kiprop_host_srv_name(kpropd_context,
7727c478bd9Sstevel@tonic-gate 					def_realm, &master_svc_princstr)) {
7737c64d375Smp 			/* Solaris Kerberos: keep error messages consistent */
7747c478bd9Sstevel@tonic-gate 			com_err(progname, retval,
7757c64d375Smp 				gettext("while getting kiprop host based "
7767c64d375Smp 					"service name for realm %s"), def_realm);
7777c478bd9Sstevel@tonic-gate 			exit(1);
7787c478bd9Sstevel@tonic-gate 		}
7797c478bd9Sstevel@tonic-gate 	}
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	/*
7827c478bd9Sstevel@tonic-gate 	 * Set cc to the default credentials cache
7837c478bd9Sstevel@tonic-gate 	 */
7847c478bd9Sstevel@tonic-gate 	if (retval = krb5_cc_default(kpropd_context, &cc)) {
7857c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
7867c478bd9Sstevel@tonic-gate 			gettext("while opening default "
7877c478bd9Sstevel@tonic-gate 				"credentials cache"));
7887c478bd9Sstevel@tonic-gate 		exit(1);
7897c478bd9Sstevel@tonic-gate 	}
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME,
7927c478bd9Sstevel@tonic-gate 				KRB5_NT_SRV_HST, &iprop_svc_principal);
7937c478bd9Sstevel@tonic-gate 	if (retval) {
7947c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while trying to construct "
7957c478bd9Sstevel@tonic-gate 						"host service principal"));
7967c478bd9Sstevel@tonic-gate 		exit(1);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
799159d09a2SMark Phalan 	/* Solaris Kerberos */
800159d09a2SMark Phalan 	if (krb5_is_referral_realm(krb5_princ_realm(kpropd_context,
801159d09a2SMark Phalan 	    iprop_svc_principal))) {
802159d09a2SMark Phalan 		krb5_data *r = krb5_princ_realm(kpropd_context,
803159d09a2SMark Phalan 		    iprop_svc_principal);
804159d09a2SMark Phalan 		assert(def_realm != NULL);
805159d09a2SMark Phalan 		r->length = strlen(def_realm);
806159d09a2SMark Phalan 		r->data = strdup(def_realm);
807159d09a2SMark Phalan 		if (r->data == NULL) {
808159d09a2SMark Phalan 			com_err(progname, retval,
809159d09a2SMark Phalan 			    ("while determining local service principal name"));
810159d09a2SMark Phalan 			exit(1);
811159d09a2SMark Phalan 		}
812159d09a2SMark Phalan 	}
813159d09a2SMark Phalan 
8147c478bd9Sstevel@tonic-gate 	if (retval = krb5_unparse_name(kpropd_context, iprop_svc_principal,
8157c478bd9Sstevel@tonic-gate 				&iprop_svc_princstr)) {
8167c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
8177c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing "
8187c478bd9Sstevel@tonic-gate 				"principal name"));
8197c478bd9Sstevel@tonic-gate 		krb5_free_principal(kpropd_context, iprop_svc_principal);
8207c478bd9Sstevel@tonic-gate 		exit(1);
8217c478bd9Sstevel@tonic-gate 	}
8227c64d375Smp 
8237c64d375Smp 	/*
8247c64d375Smp 	 * Solaris Kerberos:
8257c64d375Smp 	 * Check to see if kiprop/<fqdn>@REALM is in the keytab
8267c64d375Smp 	 */
8277c64d375Smp 	kt_name[0] = '\0';
8287c64d375Smp 	if (retval = krb5_kt_default_name(kpropd_context, kt_name,
8297c64d375Smp 	    MAX_KEYTAB_NAME_LEN)){
8307c64d375Smp 		com_err(progname, retval, gettext ("while resolving the "
831