xref: /titanic_41/usr/src/cmd/lvm/rpc.metad/metad_init.c (revision ed5289f91b9bf164dccd6c75398362be77a4478d)
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 "metad_local.h"
30 #include <metad.h>
31 
32 #include <grp.h>
33 #include <pwd.h>
34 #include <synch.h>
35 #include <netdir.h>
36 #include <netdb.h>
37 #include <sdssc.h>
38 
39 extern	void	nc_perror(const char *msg);
40 
41 /*ARGSUSED*/
42 void
43 sigalarmhandler(int sig)
44 {
45 	md_exit(NULL, 0);
46 }
47 
48 
49 /*
50  * check for trusted host and user
51  */
52 static int
53 check_host(
54 	struct svc_req		*rqstp		/* RPC stuff */
55 )
56 {
57 	struct authsys_parms	*sys_credp;
58 	SVCXPRT			*transp = rqstp->rq_xprt;
59 	struct netconfig	*nconfp = NULL;
60 	struct nd_hostservlist	*hservlistp = NULL;
61 	int			i;
62 	int			rval = -1;
63 	char			*inplace = NULL;
64 
65 	/* check for root */
66 	/*LINTED*/
67 	sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
68 	assert(sys_credp != NULL);
69 	if (sys_credp->aup_uid != 0)
70 		goto out;
71 
72 	/* get hostnames */
73 	if (transp->xp_netid == NULL) {
74 		md_eprintf("transp->xp_netid == NULL\n");
75 		goto out;
76 	}
77 	if ((nconfp = getnetconfigent(transp->xp_netid)) == NULL) {
78 #ifdef	DEBUG
79 		nc_perror("getnetconfigent(transp->xp_netid)");
80 #endif
81 		goto out;
82 	}
83 	if ((__netdir_getbyaddr_nosrv(nconfp, &hservlistp, &transp->xp_rtaddr)
84 	    != 0) || (hservlistp == NULL)) {
85 #ifdef	DEBUG
86 		netdir_perror("netdir_getbyaddr(transp->xp_rtaddr)");
87 #endif
88 		goto out;
89 	}
90 
91 	/* check hostnames */
92 	for (i = 0; (i < hservlistp->h_cnt); ++i) {
93 		struct nd_hostserv	*hservp = &hservlistp->h_hostservs[i];
94 		char			*hostname = hservp->h_host;
95 
96 		inplace = strdup(hostname);
97 
98 		/* localhost is OK */
99 		if (strcmp(hostname, mynode()) == 0) {
100 			rval = 0;
101 			goto out;
102 		}
103 
104 		/* check for remote root access */
105 		if (ruserok(hostname, 1, "root", "root") == 0) {
106 			rval = 0;
107 			goto out;
108 		}
109 
110 		sdssc_cm_nm2nid(inplace);
111 		if (strcmp(inplace, hostname)) {
112 
113 			/*
114 			 * If the names are now different it indicates
115 			 * that hostname was converted to a nodeid. This
116 			 * will only occur if hostname is part of the same
117 			 * cluster that the current node is in.
118 			 * If the machine is not running in a cluster than
119 			 * sdssc_cm_nm2nid is a noop which leaves inplace
120 			 * alone.
121 			 */
122 			rval = 0;
123 			goto out;
124 		}
125 	}
126 
127 	/* cleanup, return success */
128 out:
129 	if (inplace)
130 		free(inplace);
131 	if (hservlistp != NULL)
132 		netdir_free(hservlistp, ND_HOSTSERVLIST);
133 	if (nconfp != NULL)
134 		Free(nconfp);
135 	return (rval);
136 }
137 
138 /*
139  * check for user in local group 14
140  */
141 static int
142 check_gid14(
143 	uid_t		uid
144 )
145 {
146 	struct passwd	*pwp;
147 	struct group	*grp;
148 	char		**namep;
149 
150 	/* get user info, check default GID */
151 	if ((pwp = getpwuid(uid)) == NULL)
152 		return (-1);
153 	if (pwp->pw_gid == METAD_GID)
154 		return (0);
155 
156 	/* check in group */
157 	if ((grp = getgrgid(METAD_GID)) == NULL)
158 		return (-1);
159 	for (namep = grp->gr_mem; ((*namep != NULL) && (**namep != '\0'));
160 	    ++namep) {
161 		if (strcmp(*namep, pwp->pw_name) == 0)
162 			return (0);
163 	}
164 	return (-1);
165 }
166 
167 /*
168  * check AUTH_SYS
169  */
170 static int
171 check_sys(
172 	struct svc_req		*rqstp,		/* RPC stuff */
173 	int			amode,		/* R_OK | W_OK */
174 	md_error_t		*ep		/* returned status */
175 )
176 {
177 	static mutex_t		mx = DEFAULTMUTEX;
178 	struct authsys_parms	*sys_credp;
179 
180 	/* for read, anything is OK */
181 	if (! (amode & W_OK))
182 		return (0);
183 
184 	/* single thread (not really needed if daemon stays single threaded) */
185 	mutex_lock(&mx);
186 
187 	/* check for remote root or METAD_GID */
188 	/*LINTED*/
189 	sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
190 	if ((check_gid14(sys_credp->aup_uid) == 0) ||
191 	    (check_host(rqstp) == 0)) {
192 		mutex_unlock(&mx);
193 		return (0);
194 	}
195 
196 	/* return failure */
197 	mutex_unlock(&mx);
198 	return (mdsyserror(ep, EACCES, "rpc.metad"));
199 }
200 
201 /*
202  * setup RPC service
203  *
204  * if can't authenticate return < 0
205  * any other error return > 0
206  */
207 int
208 svc_init(
209 	struct svc_req	*rqstp,	/* RPC stuff */
210 	int		amode,	/* R_OK | W_OK */
211 	md_error_t	*ep	/* returned status */
212 )
213 {
214 	SVCXPRT		*transp;
215 
216 	if (sdssc_bind_library() == SDSSC_ERROR) {
217 		mdsyserror(ep, EACCES, "can't bind to cluster library");
218 		return (1);
219 	}
220 
221 	/*
222 	 * if we have no rpc service info, we must have been
223 	 * called recursively from within the daemon
224 	 */
225 	if (rqstp == NULL) {
226 		mdclrerror(ep);
227 		return (0);		/* OK */
228 	}
229 
230 	/*
231 	 * initialize
232 	 */
233 	transp = rqstp->rq_xprt;
234 	assert(transp != NULL);
235 	*ep = mdnullerror;
236 
237 	/*
238 	 * check credentials
239 	 */
240 	switch (rqstp->rq_cred.oa_flavor) {
241 
242 	/* UNIX flavor */
243 	case AUTH_SYS:
244 	{
245 		if (check_sys(rqstp, amode, ep) != 0)
246 			return (1);	/* error */
247 		break;
248 	}
249 
250 	/* can't authenticate anything else */
251 	default:
252 		svcerr_weakauth(transp);
253 		return (-1);		/* weak authentication */
254 	}
255 
256 	/*
257 	 * (re)initialize
258 	 */
259 	if (md_init_daemon("rpc.metad", ep) != 0)
260 		return (1);		/* error */
261 
262 	if (set_snarf(ep))
263 		return (1);
264 
265 	sr_validate();
266 
267 	/* success */
268 	return (0);
269 }
270 
271 /*ARGSUSED*/
272 int
273 svc_fini(md_error_t *ep)
274 {
275 	return (0);
276 }
277 
278 int
279 check_set_lock(
280 	int		amode,	/* R_OK | W_OK */
281 	md_setkey_t	*cl_sk,	/* clients idea of set locked */
282 	md_error_t	*ep	/* returned status */
283 )
284 {
285 	md_setkey_t	*svc_sk;
286 
287 	if (cl_sk == NULL)
288 		return (0);
289 
290 	svc_sk = svc_get_setkey(cl_sk->sk_setno);
291 
292 	/* The set is not locked */
293 	if (svc_sk == NULL) {
294 		if ((amode & W_OK) == W_OK) {
295 			(void) mddserror(ep, MDE_DS_WRITEWITHSULK,
296 			    cl_sk->sk_setno, mynode(), NULL, cl_sk->sk_setname);
297 			return (1);
298 		}
299 		return (0);
300 	}
301 
302 	/* The set is locked, do we have the key? */
303 	if (cl_sk->sk_key.tv_sec == svc_sk->sk_key.tv_sec &&
304 	    cl_sk->sk_key.tv_usec == svc_sk->sk_key.tv_usec)
305 		return (0);
306 
307 	(void) mddserror(ep, MDE_DS_SETLOCKED, MD_SET_BAD, mynode(),
308 	    svc_sk->sk_host, svc_sk->sk_setname);
309 
310 	return (1);
311 }
312