xref: /titanic_41/usr/src/cmd/lvm/rpc.metamedd/med_init.c (revision 95efa359b507db290a2484b8f615822b1e06096f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "med_local.h"
30 #include <sdssc.h>
31 
32 #include <grp.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <syslog.h>
36 #include <netdir.h>
37 #include <netdb.h>
38 #include <sys/resource.h>
39 #include <sys/priocntl.h>
40 #include <sys/rtpriocntl.h>
41 #include <sys/utsname.h>
42 
43 extern	void	nc_perror(const char *msg);
44 
45 /* daemon name */
46 static char	*medname = MED_SERVNAME;
47 
48 /*
49  * reset and exit daemon
50  */
51 void
52 med_exit(
53 	int	eval
54 )
55 {
56 	med_err_t	status = med_null_err;
57 
58 	if (med_db_finit(&status))
59 		medde_perror(&status, "med_db_finit");
60 
61 	/* log exit */
62 	med_eprintf("exiting with %d\n", eval);
63 
64 	/* exit with value */
65 	exit(eval);
66 }
67 
68 /*
69  * signal catchers
70  */
71 static void
72 med_catcher(
73 	int	sig
74 )
75 {
76 	char	buf[128];
77 	char	*msg;
78 
79 	/* log signal */
80 	if ((msg = strsignal(sig)) == NULL) {
81 		(void) sprintf(buf, "unknown signal %d", sig);
82 		msg = buf;
83 	}
84 	med_eprintf("%s\n", msg);
85 
86 	/* let default handler do it's thing */
87 	(void) sigset(sig, SIG_DFL);
88 	if (kill(getpid(), sig) != 0) {
89 		med_perror("kill(getpid())");
90 		med_exit(-sig);
91 	}
92 }
93 
94 /*
95  * initialize daemon
96  */
97 static int
98 med_setup(
99 	med_err_t	*medep
100 )
101 {
102 	/* catch common signals */
103 	if ((sigset(SIGHUP, med_catcher) == SIG_ERR) ||
104 	    (sigset(SIGINT, med_catcher) == SIG_ERR) ||
105 	    (sigset(SIGABRT, med_catcher) == SIG_ERR) ||
106 	    (sigset(SIGBUS, med_catcher) == SIG_ERR) ||
107 	    (sigset(SIGSEGV, med_catcher) == SIG_ERR) ||
108 	    (sigset(SIGPIPE, med_catcher) == SIG_ERR) ||
109 	    (sigset(SIGTERM, med_catcher) == SIG_ERR)) {
110 		return (med_error(medep, errno, "sigset"));
111 	}
112 
113 	/* ignore SIGALRM (used in med_cv_timedwait) */
114 	if (sigset(SIGALRM, SIG_IGN) == SIG_ERR) {
115 		return (med_error(medep, errno, "sigset"));
116 	}
117 
118 	/* return success */
119 	return (0);
120 }
121 
122 /*
123  * (re)initalize daemon
124  */
125 static int
126 med_init_daemon(
127 	med_err_t	*medep
128 )
129 {
130 	static int	already = 0;
131 
132 	/* setup */
133 	if (! already) {
134 		if (med_setup(medep) != 0)
135 			return (-1);
136 		openlog(medname, LOG_CONS, LOG_DAEMON);
137 		already = 1;
138 	}
139 
140 	/* return success */
141 	return (0);
142 }
143 
144 /*
145  * get my nodename
146  */
147 char *
148 mynode(void)
149 {
150 	static struct utsname	myuname;
151 	static int		done = 0;
152 
153 	if (! done) {
154 		if (uname(&myuname) == -1) {
155 			med_perror("uname");
156 			assert(0);
157 		}
158 		done = 1;
159 	}
160 	return (myuname.nodename);
161 }
162 
163 /*
164  * check for trusted host and user
165  */
166 static int
167 check_host(
168 	struct svc_req		*rqstp		/* RPC stuff */
169 )
170 {
171 	struct authsys_parms	*sys_credp;
172 	SVCXPRT			*transp = rqstp->rq_xprt;
173 	struct netconfig	*nconfp = NULL;
174 	struct nd_hostservlist	*hservlistp = NULL;
175 	int			i;
176 	int			rval = -1;
177 	char			*inplace = NULL;
178 
179 	/* check for root */
180 	/*LINTED*/
181 	sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
182 	assert(sys_credp != NULL);
183 	if (sys_credp->aup_uid != 0)
184 		goto out;
185 
186 	/* get hostnames */
187 	if (transp->xp_netid == NULL) {
188 		med_eprintf("transp->xp_netid == NULL\n");
189 		goto out;
190 	}
191 	if ((nconfp = getnetconfigent(transp->xp_netid)) == NULL) {
192 #ifdef	DEBUG
193 		nc_perror("getnetconfigent(transp->xp_netid)");
194 #endif
195 		goto out;
196 	}
197 	if ((__netdir_getbyaddr_nosrv(nconfp, &hservlistp, &transp->xp_rtaddr)
198 	    != 0) || (hservlistp == NULL)) {
199 #ifdef	DEBUG
200 		netdir_perror("netdir_getbyaddr(transp->xp_rtaddr)");
201 #endif
202 		goto out;
203 	}
204 
205 	/* check hostnames */
206 	for (i = 0; (i < hservlistp->h_cnt); ++i) {
207 		struct nd_hostserv	*hservp = &hservlistp->h_hostservs[i];
208 		char			*hostname = hservp->h_host;
209 
210 		inplace = strdup(hostname);
211 		sdssc_cm_nm2nid(inplace);
212 		if (strcmp(inplace, hostname)) {
213 
214 			/*
215 			 * If the names are now different it indicates
216 			 * that hostname was converted to a nodeid. This
217 			 * will only occur if hostname is part of the same
218 			 * cluster that the current node is in.
219 			 * If the machine is not running in a cluster than
220 			 * sdssc_cm_nm2nid is a noop which leaves inplace
221 			 * alone.
222 			 */
223 			rval = 0;
224 			goto out;
225 		}
226 
227 		/* localhost is OK */
228 		if (strcmp(hostname, mynode()) == 0) {
229 			rval = 0;
230 			goto out;
231 		}
232 
233 		if (strcmp(hostname, "localhost") == 0) {
234 			rval = 0;
235 			goto out;
236 		}
237 
238 		/* check for remote root access */
239 		if (ruserok(hostname, 1, "root", "root") == 0) {
240 			rval = 0;
241 			goto out;
242 		}
243 	}
244 
245 	/* cleanup, return success */
246 out:
247 	if (inplace)
248 		free(inplace);
249 	if (hservlistp != NULL)
250 		netdir_free(hservlistp, ND_HOSTSERVLIST);
251 	if (nconfp != NULL)
252 		Free(nconfp);
253 	return (rval);
254 }
255 
256 /*
257  * check for user in local group 14
258  */
259 static int
260 check_gid14(
261 	uid_t		uid
262 )
263 {
264 	struct passwd	*pwp;
265 	struct group	*grp;
266 	char		**namep;
267 
268 	/* get user info, check default GID */
269 	if ((pwp = getpwuid(uid)) == NULL)
270 		return (-1);
271 	if (pwp->pw_gid == MED_GID)
272 		return (0);
273 
274 	/* check in group */
275 	if ((grp = getgrgid(MED_GID)) == NULL)
276 		return (-1);
277 	for (namep = grp->gr_mem; ((*namep != NULL) && (**namep != '\0'));
278 	    ++namep) {
279 		if (strcmp(*namep, pwp->pw_name) == 0)
280 			return (0);
281 	}
282 	return (-1);
283 }
284 
285 /*
286  * check AUTH_SYS
287  */
288 static int
289 check_sys(
290 	struct svc_req		*rqstp,		/* RPC stuff */
291 	int			amode,		/* R_OK | W_OK */
292 	med_err_t		*medep		/* returned status */
293 )
294 {
295 #ifdef	_REENTRANT
296 	static mutex_t		mx = DEFAULTMUTEX;
297 #endif	/* _REENTRANT */
298 	struct authsys_parms	*sys_credp;
299 
300 	/* for read, anything is OK */
301 	if (! (amode & W_OK))
302 		return (0);
303 
304 #ifdef	_REENTRANT
305 	/* single thread (not really needed if daemon stays single threaded) */
306 	mutex_lock(&mx);
307 #endif	/* _REENTRANT */
308 
309 	/* check for remote root or METAMED_GID */
310 	/*LINTED*/
311 	sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
312 	if ((check_gid14(sys_credp->aup_uid) == 0) ||
313 	    (check_host(rqstp) == 0)) {
314 #ifdef	_REENTRANT
315 		mutex_unlock(&mx);
316 #endif	/* _REENTRANT */
317 		return (0);
318 	}
319 
320 	/* return failure */
321 #ifdef	_REENTRANT
322 	mutex_unlock(&mx);
323 #endif	/* _REENTRANT */
324 	return (med_error(medep, EACCES, medname));
325 }
326 
327 /*
328  * setup RPC service
329  *
330  * if can't authenticate return < 0
331  * if any other error return > 0
332  */
333 int
334 med_init(
335 	struct svc_req	*rqstp,		/* RPC stuff */
336 	int		amode,		/* R_OK | W_OK */
337 	med_err_t	*medep		/* returned status */
338 )
339 {
340 	SVCXPRT		*transp = rqstp->rq_xprt;
341 
342 	/*
343 	 * initialize
344 	 */
345 	(void) memset(medep, 0, sizeof (*medep));
346 
347 	if (sdssc_bind_library() == SDSSC_ERROR) {
348 		(void) med_error(medep, EACCES,
349 		    "can't bind to cluster library");
350 		return (1);
351 	}
352 
353 	/*
354 	 * check credentials
355 	 */
356 	switch (rqstp->rq_cred.oa_flavor) {
357 
358 	/* UNIX flavor */
359 	case AUTH_SYS:
360 	{
361 		if (check_sys(rqstp, amode, medep) != 0)
362 			return (1);	/* error */
363 		break;
364 	}
365 
366 	/* can't authenticate anything else */
367 	default:
368 		svcerr_weakauth(transp);
369 		return (-1);		/* weak authentication */
370 
371 	}
372 
373 	/*
374 	 * (re)initialize
375 	 */
376 	if (med_init_daemon(medep) != 0)
377 		return (1);		/* error */
378 
379 	/* return success */
380 	return (0);
381 }
382