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