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
sigalarmhandler(int sig)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
check_host(struct svc_req * rqstp)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
check_gid14(uid_t uid)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
check_sys(struct svc_req * rqstp,int amode,md_error_t * ep)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
svc_init(struct svc_req * rqstp,int amode,md_error_t * ep)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
svc_fini(md_error_t * ep)270 svc_fini(md_error_t *ep)
271 {
272 return (0);
273 }
274
275 int
check_set_lock(int amode,md_setkey_t * cl_sk,md_error_t * ep)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