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