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