xref: /onnv-gate/usr/src/cmd/krb5/kadmin/server/ipropd_svc.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate #include <stdio.h>
10*0Sstevel@tonic-gate #include <stdlib.h> /* getenv, exit */
11*0Sstevel@tonic-gate #include <signal.h>
12*0Sstevel@tonic-gate #include <sys/types.h>
13*0Sstevel@tonic-gate #include <memory.h>
14*0Sstevel@tonic-gate #include <stropts.h>
15*0Sstevel@tonic-gate #include <netconfig.h>
16*0Sstevel@tonic-gate #include <sys/resource.h> /* rlimit */
17*0Sstevel@tonic-gate #include <syslog.h>
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate #include <kadm5/admin.h>
20*0Sstevel@tonic-gate #include <kadm5/kadm_rpc.h>
21*0Sstevel@tonic-gate #include <kadm5/server_internal.h>
22*0Sstevel@tonic-gate #include <server_acl.h>
23*0Sstevel@tonic-gate #include <krb5/adm_proto.h>
24*0Sstevel@tonic-gate #include <string.h>
25*0Sstevel@tonic-gate #include <gssapi_krb5.h>
26*0Sstevel@tonic-gate #include <sys/socket.h>
27*0Sstevel@tonic-gate #include <netinet/in.h>
28*0Sstevel@tonic-gate #include <arpa/inet.h>
29*0Sstevel@tonic-gate #include <netdb.h>
30*0Sstevel@tonic-gate #include <libintl.h>
31*0Sstevel@tonic-gate #include <kdb/kdb_log.h>
32*0Sstevel@tonic-gate #include "misc.h"
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate extern int setup_gss_names(struct svc_req *, char **, char **);
37*0Sstevel@tonic-gate extern gss_name_t get_clnt_name(struct svc_req *);
38*0Sstevel@tonic-gate extern char *client_addr(struct svc_req *, char *);
39*0Sstevel@tonic-gate extern void *global_server_handle;
40*0Sstevel@tonic-gate extern int nofork;
41*0Sstevel@tonic-gate extern short l_port;
42*0Sstevel@tonic-gate static char abuf[33];
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate static char *reply_ok_str	= "UPDATE_OK";
45*0Sstevel@tonic-gate static char *reply_err_str	= "UPDATE_ERROR";
46*0Sstevel@tonic-gate static char *reply_fr_str	= "UPDATE_FULL_RESYNC_NEEDED";
47*0Sstevel@tonic-gate static char *reply_busy_str	= "UPDATE_BUSY";
48*0Sstevel@tonic-gate static char *reply_nil_str	= "UPDATE_NIL";
49*0Sstevel@tonic-gate static char *reply_perm_str	= "UPDATE_PERM_DENIED";
50*0Sstevel@tonic-gate static char *reply_unknown_str	= "<UNKNOWN_CODE>";
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #define	LOG_UNAUTH  gettext("Unauthorized request: %s, %s, " \
53*0Sstevel@tonic-gate 			"client=%s, service=%s, addr=%s")
54*0Sstevel@tonic-gate #define	LOG_DONE    gettext("Request: %s, %s, %s, client=%s, " \
55*0Sstevel@tonic-gate 			"service=%s, addr=%s")
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate #define	KDB5_UTIL_DUMP_STR "/usr/sbin/kdb5_util dump -i "
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #ifdef	DPRINT
60*0Sstevel@tonic-gate #undef	DPRINT
61*0Sstevel@tonic-gate #endif
62*0Sstevel@tonic-gate #define	DPRINT(i) if (nofork) printf i
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate static void
66*0Sstevel@tonic-gate debprret(char *w, update_status_t ret, kdb_sno_t sno)
67*0Sstevel@tonic-gate {
68*0Sstevel@tonic-gate 	switch (ret) {
69*0Sstevel@tonic-gate 	case UPDATE_OK:
70*0Sstevel@tonic-gate 		printf("%s: end (OK, sno=%u)\n",
71*0Sstevel@tonic-gate 		    w, sno);
72*0Sstevel@tonic-gate 		break;
73*0Sstevel@tonic-gate 	case UPDATE_ERROR:
74*0Sstevel@tonic-gate 		printf("%s: end (ERROR)\n", w);
75*0Sstevel@tonic-gate 		break;
76*0Sstevel@tonic-gate 	case UPDATE_FULL_RESYNC_NEEDED:
77*0Sstevel@tonic-gate 		printf("%s: end (FR NEEDED)\n", w);
78*0Sstevel@tonic-gate 		break;
79*0Sstevel@tonic-gate 	case UPDATE_BUSY:
80*0Sstevel@tonic-gate 		printf("%s: end (BUSY)\n", w);
81*0Sstevel@tonic-gate 		break;
82*0Sstevel@tonic-gate 	case UPDATE_NIL:
83*0Sstevel@tonic-gate 		printf("%s: end (NIL)\n", w);
84*0Sstevel@tonic-gate 		break;
85*0Sstevel@tonic-gate 	case UPDATE_PERM_DENIED:
86*0Sstevel@tonic-gate 		printf("%s: end (PERM)\n", w);
87*0Sstevel@tonic-gate 		break;
88*0Sstevel@tonic-gate 	default:
89*0Sstevel@tonic-gate 		printf("%s: end (UNKNOWN return code (%d))\n", w, ret);
90*0Sstevel@tonic-gate 	}
91*0Sstevel@tonic-gate }
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate static char *
94*0Sstevel@tonic-gate replystr(update_status_t ret)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate 	switch (ret) {
97*0Sstevel@tonic-gate 	case UPDATE_OK:
98*0Sstevel@tonic-gate 		return (reply_ok_str);
99*0Sstevel@tonic-gate 	case UPDATE_ERROR:
100*0Sstevel@tonic-gate 		return (reply_err_str);
101*0Sstevel@tonic-gate 	case UPDATE_FULL_RESYNC_NEEDED:
102*0Sstevel@tonic-gate 		return (reply_fr_str);
103*0Sstevel@tonic-gate 	case UPDATE_BUSY:
104*0Sstevel@tonic-gate 		return (reply_busy_str);
105*0Sstevel@tonic-gate 	case UPDATE_NIL:
106*0Sstevel@tonic-gate 		return (reply_nil_str);
107*0Sstevel@tonic-gate 	case UPDATE_PERM_DENIED:
108*0Sstevel@tonic-gate 		return (reply_perm_str);
109*0Sstevel@tonic-gate 	default:
110*0Sstevel@tonic-gate 		return (reply_unknown_str);
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate }
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate kdb_incr_result_t *
115*0Sstevel@tonic-gate iprop_get_updates_1(kdb_last_t *arg, struct svc_req *rqstp)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	static kdb_incr_result_t ret;
118*0Sstevel@tonic-gate 	char *whoami = "iprop_get_updates_1";
119*0Sstevel@tonic-gate 	int kret;
120*0Sstevel@tonic-gate 	kadm5_server_handle_t handle = global_server_handle;
121*0Sstevel@tonic-gate 	char *client_name = NULL, *service_name = NULL;
122*0Sstevel@tonic-gate 	gss_name_t name = NULL;
123*0Sstevel@tonic-gate 	OM_uint32 min_stat;
124*0Sstevel@tonic-gate 	char obuf[256] = {0};
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	/* default return code */
127*0Sstevel@tonic-gate 	ret.ret = UPDATE_ERROR;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	DPRINT(("%s: start, last_sno=%u\n", whoami, (ulong_t)arg->last_sno));
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 	if (!handle) {
132*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
133*0Sstevel@tonic-gate 				gettext("%s: server handle is NULL"),
134*0Sstevel@tonic-gate 					whoami);
135*0Sstevel@tonic-gate 		goto out;
136*0Sstevel@tonic-gate 	}
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
139*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
140*0Sstevel@tonic-gate 			gettext("%s: setup_gss_names failed"),
141*0Sstevel@tonic-gate 			whoami);
142*0Sstevel@tonic-gate 		goto out;
143*0Sstevel@tonic-gate 	}
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
146*0Sstevel@tonic-gate 		whoami, client_name, service_name));
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	if (!(name = get_clnt_name(rqstp))) {
149*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
150*0Sstevel@tonic-gate 			gettext("%s: Couldn't obtain client's name"),
151*0Sstevel@tonic-gate 			whoami);
152*0Sstevel@tonic-gate 		goto out;
153*0Sstevel@tonic-gate 	}
154*0Sstevel@tonic-gate 	if (!acl_check(handle->context,
155*0Sstevel@tonic-gate 		    name,
156*0Sstevel@tonic-gate 		    ACL_IPROP,
157*0Sstevel@tonic-gate 		    NULL,
158*0Sstevel@tonic-gate 		    NULL)) {
159*0Sstevel@tonic-gate 		ret.ret = UPDATE_PERM_DENIED;
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
162*0Sstevel@tonic-gate 				    whoami,
163*0Sstevel@tonic-gate 				    "<null>", client_name);
164*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
165*0Sstevel@tonic-gate 				"<null>", client_name, service_name,
166*0Sstevel@tonic-gate 				client_addr(rqstp, abuf));
167*0Sstevel@tonic-gate 		goto out;
168*0Sstevel@tonic-gate 	}
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	kret = ulog_get_entries(handle->context, *arg, &ret);
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	if (ret.ret == UPDATE_OK) {
173*0Sstevel@tonic-gate 		(void) snprintf(obuf, sizeof (obuf),
174*0Sstevel@tonic-gate 		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=%u"),
175*0Sstevel@tonic-gate 				replystr(ret.ret),
176*0Sstevel@tonic-gate 				(ulong_t)arg->last_sno,
177*0Sstevel@tonic-gate 				(ulong_t)ret.lastentry.last_sno);
178*0Sstevel@tonic-gate 	} else {
179*0Sstevel@tonic-gate 		(void) snprintf(obuf, sizeof (obuf),
180*0Sstevel@tonic-gate 		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=N/A"),
181*0Sstevel@tonic-gate 				replystr(ret.ret),
182*0Sstevel@tonic-gate 				(ulong_t)arg->last_sno);
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	audit_kadmind_auth(rqstp->rq_xprt, l_port,
186*0Sstevel@tonic-gate 			whoami,
187*0Sstevel@tonic-gate 			obuf, client_name, kret);
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
190*0Sstevel@tonic-gate 			obuf,
191*0Sstevel@tonic-gate 			((kret == 0) ? "success" : error_message(kret)),
192*0Sstevel@tonic-gate 			client_name, service_name,
193*0Sstevel@tonic-gate 			client_addr(rqstp, abuf));
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate out:
196*0Sstevel@tonic-gate 	if (nofork)
197*0Sstevel@tonic-gate 		debprret(whoami, ret.ret, ret.lastentry.last_sno);
198*0Sstevel@tonic-gate 	if (client_name)
199*0Sstevel@tonic-gate 		free(client_name);
200*0Sstevel@tonic-gate 	if (service_name)
201*0Sstevel@tonic-gate 		free(service_name);
202*0Sstevel@tonic-gate 	if (name)
203*0Sstevel@tonic-gate 		gss_release_name(&min_stat, &name);
204*0Sstevel@tonic-gate 	return (&ret);
205*0Sstevel@tonic-gate }
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate /*
209*0Sstevel@tonic-gate  * Given a client princ (foo/fqdn@R), copy (in arg cl) the fqdn substring.
210*0Sstevel@tonic-gate  * Return arg cl str ptr on success, else NULL.
211*0Sstevel@tonic-gate  */
212*0Sstevel@tonic-gate static char *
213*0Sstevel@tonic-gate getclhoststr(char *clprinc, char *cl, int len)
214*0Sstevel@tonic-gate {
215*0Sstevel@tonic-gate 	char *s;
216*0Sstevel@tonic-gate 	if (s = strchr(clprinc, '/')) {
217*0Sstevel@tonic-gate 		if (!++s || strlcpy(cl, s, len) >= len) {
218*0Sstevel@tonic-gate 			return (NULL);
219*0Sstevel@tonic-gate 		}
220*0Sstevel@tonic-gate 		if (s = strchr(cl, '@')) {
221*0Sstevel@tonic-gate 			*s = '\0';
222*0Sstevel@tonic-gate 			return (cl); /* success */
223*0Sstevel@tonic-gate 		}
224*0Sstevel@tonic-gate 	}
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	return (NULL);
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate kdb_fullresync_result_t *
230*0Sstevel@tonic-gate iprop_full_resync_1(
231*0Sstevel@tonic-gate 	/* LINTED */
232*0Sstevel@tonic-gate 	void *argp,
233*0Sstevel@tonic-gate 	struct svc_req *rqstp)
234*0Sstevel@tonic-gate {
235*0Sstevel@tonic-gate 	static kdb_fullresync_result_t ret;
236*0Sstevel@tonic-gate 	char tmpf[MAX_FILENAME] = {0};
237*0Sstevel@tonic-gate 	char ubuf[MAX_FILENAME + sizeof (KDB5_UTIL_DUMP_STR)] = {0};
238*0Sstevel@tonic-gate 	char clhost[MAXHOSTNAMELEN] = {0};
239*0Sstevel@tonic-gate 	int pret, fret;
240*0Sstevel@tonic-gate 	kadm5_server_handle_t handle = global_server_handle;
241*0Sstevel@tonic-gate 	OM_uint32 min_stat;
242*0Sstevel@tonic-gate 	gss_name_t name = NULL;
243*0Sstevel@tonic-gate 	char *client_name = NULL, *service_name = NULL;
244*0Sstevel@tonic-gate 	char *whoami = "iprop_full_resync_1";
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	/* default return code */
247*0Sstevel@tonic-gate 	ret.ret = UPDATE_ERROR;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 	if (!handle) {
250*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
251*0Sstevel@tonic-gate 				gettext("%s: server handle is NULL"),
252*0Sstevel@tonic-gate 					whoami);
253*0Sstevel@tonic-gate 		goto out;
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	DPRINT(("%s: start\n", whoami));
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
259*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
260*0Sstevel@tonic-gate 			gettext("%s: setup_gss_names failed"),
261*0Sstevel@tonic-gate 			whoami);
262*0Sstevel@tonic-gate 		goto out;
263*0Sstevel@tonic-gate 	}
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
266*0Sstevel@tonic-gate 		whoami, client_name, service_name));
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	if (!(name = get_clnt_name(rqstp))) {
269*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
270*0Sstevel@tonic-gate 			gettext("%s: Couldn't obtain client's name"),
271*0Sstevel@tonic-gate 			whoami);
272*0Sstevel@tonic-gate 		goto out;
273*0Sstevel@tonic-gate 	}
274*0Sstevel@tonic-gate 	if (!acl_check(handle->context,
275*0Sstevel@tonic-gate 		    name,
276*0Sstevel@tonic-gate 		    ACL_IPROP,
277*0Sstevel@tonic-gate 		    NULL,
278*0Sstevel@tonic-gate 		    NULL)) {
279*0Sstevel@tonic-gate 		ret.ret = UPDATE_PERM_DENIED;
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
282*0Sstevel@tonic-gate 				    whoami,
283*0Sstevel@tonic-gate 				    "<null>", client_name);
284*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
285*0Sstevel@tonic-gate 				"<null>", client_name, service_name,
286*0Sstevel@tonic-gate 				client_addr(rqstp, abuf));
287*0Sstevel@tonic-gate 		goto out;
288*0Sstevel@tonic-gate 	}
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate 	if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
291*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
292*0Sstevel@tonic-gate 			gettext("%s: getclhoststr failed"),
293*0Sstevel@tonic-gate 			whoami);
294*0Sstevel@tonic-gate 		goto out;
295*0Sstevel@tonic-gate 	}
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 	/*
298*0Sstevel@tonic-gate 	 * construct db dump file name; kprop style name + clnt fqdn
299*0Sstevel@tonic-gate 	 */
300*0Sstevel@tonic-gate 	(void) strcpy(tmpf, "/var/krb5/slave_datatrans_");
301*0Sstevel@tonic-gate 	if (strlcat(tmpf, clhost, sizeof (tmpf)) >= sizeof (tmpf)) {
302*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
303*0Sstevel@tonic-gate 		gettext("%s: db dump file name too long; max length=%d"),
304*0Sstevel@tonic-gate 				whoami,
305*0Sstevel@tonic-gate 				(sizeof (tmpf) - 1));
306*0Sstevel@tonic-gate 		goto out;
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	/*
310*0Sstevel@tonic-gate 	 * note the -i; modified version of kdb5_util dump format
311*0Sstevel@tonic-gate 	 * to include sno (serial number)
312*0Sstevel@tonic-gate 	 */
313*0Sstevel@tonic-gate 	if (strlcpy(ubuf, KDB5_UTIL_DUMP_STR, sizeof (ubuf)) >=
314*0Sstevel@tonic-gate 	    sizeof (ubuf)) {
315*0Sstevel@tonic-gate 		goto out;
316*0Sstevel@tonic-gate 	}
317*0Sstevel@tonic-gate 	if (strlcat(ubuf, tmpf, sizeof (ubuf)) >= sizeof (ubuf)) {
318*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
319*0Sstevel@tonic-gate 		gettext("%s: kdb5 util dump string too long; max length=%d"),
320*0Sstevel@tonic-gate 				whoami,
321*0Sstevel@tonic-gate 				(sizeof (ubuf) - 1));
322*0Sstevel@tonic-gate 		goto out;
323*0Sstevel@tonic-gate 	}
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	/*
326*0Sstevel@tonic-gate 	 * Fork to dump the db and xfer it to the slave.
327*0Sstevel@tonic-gate 	 * (the fork allows parent to return quickly and the child
328*0Sstevel@tonic-gate 	 * acts like a callback to the slave).
329*0Sstevel@tonic-gate 	 */
330*0Sstevel@tonic-gate 	fret = fork();
331*0Sstevel@tonic-gate 	DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid()));
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate 	switch (fret) {
334*0Sstevel@tonic-gate 	case -1: /* error */
335*0Sstevel@tonic-gate 		if (nofork) {
336*0Sstevel@tonic-gate 			perror(whoami);
337*0Sstevel@tonic-gate 		}
338*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
339*0Sstevel@tonic-gate 				gettext("%s: fork failed: %s"),
340*0Sstevel@tonic-gate 				whoami,
341*0Sstevel@tonic-gate 				error_message(errno));
342*0Sstevel@tonic-gate 		goto out;
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	case 0: /* child */
345*0Sstevel@tonic-gate 		DPRINT(("%s: run `%s' ...\n", whoami, ubuf));
346*0Sstevel@tonic-gate 		(void) signal(SIGCHLD, SIG_DFL);
347*0Sstevel@tonic-gate 		/* run kdb5_util(1M) dump for IProp */
348*0Sstevel@tonic-gate 		pret = pclose(popen(ubuf, "w"));
349*0Sstevel@tonic-gate 		DPRINT(("%s: pclose=%d\n", whoami, pret));
350*0Sstevel@tonic-gate 		if (pret == -1) {
351*0Sstevel@tonic-gate 			if (nofork) {
352*0Sstevel@tonic-gate 				perror(whoami);
353*0Sstevel@tonic-gate 			}
354*0Sstevel@tonic-gate 			krb5_klog_syslog(LOG_ERR,
355*0Sstevel@tonic-gate 				gettext("%s: pclose(popen) failed: %s"),
356*0Sstevel@tonic-gate 					whoami,
357*0Sstevel@tonic-gate 					error_message(errno));
358*0Sstevel@tonic-gate 			goto out;
359*0Sstevel@tonic-gate 		}
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 		DPRINT(("%s: exec `kprop -f %s %s' ...\n",
362*0Sstevel@tonic-gate 			whoami, tmpf, clhost));
363*0Sstevel@tonic-gate 		pret = execl("/usr/lib/krb5/kprop", "kprop", "-f", tmpf,
364*0Sstevel@tonic-gate 			    clhost, NULL);
365*0Sstevel@tonic-gate 		if (pret == -1) {
366*0Sstevel@tonic-gate 			if (nofork) {
367*0Sstevel@tonic-gate 				perror(whoami);
368*0Sstevel@tonic-gate 			}
369*0Sstevel@tonic-gate 			krb5_klog_syslog(LOG_ERR,
370*0Sstevel@tonic-gate 					gettext("%s: exec failed: %s"),
371*0Sstevel@tonic-gate 					whoami,
372*0Sstevel@tonic-gate 					error_message(errno));
373*0Sstevel@tonic-gate 			goto out;
374*0Sstevel@tonic-gate 		}
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 	default: /* parent */
377*0Sstevel@tonic-gate 		ret.ret = UPDATE_OK;
378*0Sstevel@tonic-gate 		/* not used by slave (sno is retrieved from kdb5_util dump) */
379*0Sstevel@tonic-gate 		ret.lastentry.last_sno = 0;
380*0Sstevel@tonic-gate 		ret.lastentry.last_time.seconds = 0;
381*0Sstevel@tonic-gate 		ret.lastentry.last_time.useconds = 0;
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 		audit_kadmind_auth(rqstp->rq_xprt, l_port,
384*0Sstevel@tonic-gate 				whoami,
385*0Sstevel@tonic-gate 				"<null>", client_name, 0);
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
388*0Sstevel@tonic-gate 				"<null>",
389*0Sstevel@tonic-gate 				"success",
390*0Sstevel@tonic-gate 				client_name, service_name,
391*0Sstevel@tonic-gate 				client_addr(rqstp, abuf));
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 		goto out;
394*0Sstevel@tonic-gate 	}
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate out:
397*0Sstevel@tonic-gate 	if (nofork)
398*0Sstevel@tonic-gate 		debprret(whoami, ret.ret, 0);
399*0Sstevel@tonic-gate 	if (client_name)
400*0Sstevel@tonic-gate 		free(client_name);
401*0Sstevel@tonic-gate 	if (service_name)
402*0Sstevel@tonic-gate 		free(service_name);
403*0Sstevel@tonic-gate 	if (name)
404*0Sstevel@tonic-gate 		gss_release_name(&min_stat, &name);
405*0Sstevel@tonic-gate 	return (&ret);
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate void
409*0Sstevel@tonic-gate krb5_iprop_prog_1(
410*0Sstevel@tonic-gate 	struct svc_req *rqstp,
411*0Sstevel@tonic-gate 	register SVCXPRT *transp)
412*0Sstevel@tonic-gate {
413*0Sstevel@tonic-gate 	union {
414*0Sstevel@tonic-gate 		kdb_last_t iprop_get_updates_1_arg;
415*0Sstevel@tonic-gate 	} argument;
416*0Sstevel@tonic-gate 	char *result;
417*0Sstevel@tonic-gate 	bool_t (*_xdr_argument)(), (*_xdr_result)();
418*0Sstevel@tonic-gate 	char *(*local)();
419*0Sstevel@tonic-gate 	char *whoami = "krb5_iprop_prog_1";
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
422*0Sstevel@tonic-gate 	case NULLPROC:
423*0Sstevel@tonic-gate 		(void) svc_sendreply(transp, xdr_void,
424*0Sstevel@tonic-gate 			(char *)NULL);
425*0Sstevel@tonic-gate 		return;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	case IPROP_GET_UPDATES:
428*0Sstevel@tonic-gate 		_xdr_argument = xdr_kdb_last_t;
429*0Sstevel@tonic-gate 		_xdr_result = xdr_kdb_incr_result_t;
430*0Sstevel@tonic-gate 		local = (char *(*)()) iprop_get_updates_1;
431*0Sstevel@tonic-gate 		break;
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 	case IPROP_FULL_RESYNC:
434*0Sstevel@tonic-gate 		_xdr_argument = xdr_void;
435*0Sstevel@tonic-gate 		_xdr_result = xdr_kdb_fullresync_result_t;
436*0Sstevel@tonic-gate 		local = (char *(*)()) iprop_full_resync_1;
437*0Sstevel@tonic-gate 		break;
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	default:
440*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
441*0Sstevel@tonic-gate 				gettext("RPC unknown request: %d (%s)"),
442*0Sstevel@tonic-gate 				rqstp->rq_proc, whoami);
443*0Sstevel@tonic-gate 		svcerr_noproc(transp);
444*0Sstevel@tonic-gate 		return;
445*0Sstevel@tonic-gate 	}
446*0Sstevel@tonic-gate 	(void) memset((char *)&argument, 0, sizeof (argument));
447*0Sstevel@tonic-gate 	if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
448*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
449*0Sstevel@tonic-gate 				gettext("RPC svc_getargs failed (%s)"),
450*0Sstevel@tonic-gate 				whoami);
451*0Sstevel@tonic-gate 		svcerr_decode(transp);
452*0Sstevel@tonic-gate 		return;
453*0Sstevel@tonic-gate 	}
454*0Sstevel@tonic-gate 	result = (*local)(&argument, rqstp);
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate 	if (_xdr_result && result != NULL &&
457*0Sstevel@tonic-gate 	    !svc_sendreply(transp, _xdr_result, result)) {
458*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
459*0Sstevel@tonic-gate 				gettext("RPC svc_sendreply failed (%s)"),
460*0Sstevel@tonic-gate 				whoami);
461*0Sstevel@tonic-gate 		svcerr_systemerr(transp);
462*0Sstevel@tonic-gate 	}
463*0Sstevel@tonic-gate 	if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
464*0Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR,
465*0Sstevel@tonic-gate 				gettext("RPC svc_freeargs failed (%s)"),
466*0Sstevel@tonic-gate 				whoami);
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 		exit(1);
469*0Sstevel@tonic-gate 	}
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	if (rqstp->rq_proc == IPROP_GET_UPDATES) {
472*0Sstevel@tonic-gate 		/* LINTED */
473*0Sstevel@tonic-gate 		kdb_incr_result_t *r = (kdb_incr_result_t *)result;
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 		if (r->ret == UPDATE_OK) {
476*0Sstevel@tonic-gate 			ulog_free_entries(r->updates.kdb_ulog_t_val,
477*0Sstevel@tonic-gate 					r->updates.kdb_ulog_t_len);
478*0Sstevel@tonic-gate 			r->updates.kdb_ulog_t_val = NULL;
479*0Sstevel@tonic-gate 			r->updates.kdb_ulog_t_len = 0;
480*0Sstevel@tonic-gate 		}
481*0Sstevel@tonic-gate 	}
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate }
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate /*
486*0Sstevel@tonic-gate  * Get the host base service name for the kiprop principal. Returns
487*0Sstevel@tonic-gate  * KADM5_OK on success. Caller must free the storage allocated for
488*0Sstevel@tonic-gate  * host_service_name.
489*0Sstevel@tonic-gate  */
490*0Sstevel@tonic-gate kadm5_ret_t
491*0Sstevel@tonic-gate kiprop_get_adm_host_srv_name(
492*0Sstevel@tonic-gate 	krb5_context context,
493*0Sstevel@tonic-gate 	const char *realm,
494*0Sstevel@tonic-gate 	char **host_service_name)
495*0Sstevel@tonic-gate {
496*0Sstevel@tonic-gate 	kadm5_ret_t ret;
497*0Sstevel@tonic-gate 	char *name;
498*0Sstevel@tonic-gate 	char *host;
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 	if (ret = kadm5_get_master(context, realm, &host))
501*0Sstevel@tonic-gate 		return (ret);
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 	name = malloc(strlen(KIPROP_SVC_NAME)+ strlen(host) + 2);
504*0Sstevel@tonic-gate 	if (name == NULL) {
505*0Sstevel@tonic-gate 		free(host);
506*0Sstevel@tonic-gate 		return (ENOMEM);
507*0Sstevel@tonic-gate 	}
508*0Sstevel@tonic-gate 	(void) sprintf(name, "%s@%s", KIPROP_SVC_NAME, host);
509*0Sstevel@tonic-gate 	free(host);
510*0Sstevel@tonic-gate 	*host_service_name = name;
511*0Sstevel@tonic-gate 
512*0Sstevel@tonic-gate 	return (KADM5_OK);
513*0Sstevel@tonic-gate }
514