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 "med_local.h" 30 #include <sdssc.h> 31 32 #include <grp.h> 33 #include <pwd.h> 34 #include <signal.h> 35 #include <syslog.h> 36 #include <netdir.h> 37 #include <netdb.h> 38 #include <sys/resource.h> 39 #include <sys/priocntl.h> 40 #include <sys/rtpriocntl.h> 41 #include <sys/utsname.h> 42 43 extern void nc_perror(const char *msg); 44 45 /* daemon name */ 46 static char *medname = MED_SERVNAME; 47 48 /* 49 * reset and exit daemon 50 */ 51 void 52 med_exit( 53 int eval 54 ) 55 { 56 med_err_t status = med_null_err; 57 58 if (med_db_finit(&status)) 59 medde_perror(&status, "med_db_finit"); 60 61 /* log exit */ 62 med_eprintf("exiting with %d\n", eval); 63 64 /* exit with value */ 65 exit(eval); 66 } 67 68 /* 69 * signal catchers 70 */ 71 static void 72 med_catcher( 73 int sig 74 ) 75 { 76 char buf[128]; 77 char *msg; 78 79 /* log signal */ 80 if ((msg = strsignal(sig)) == NULL) { 81 (void) sprintf(buf, "unknown signal %d", sig); 82 msg = buf; 83 } 84 med_eprintf("%s\n", msg); 85 86 /* let default handler do it's thing */ 87 (void) sigset(sig, SIG_DFL); 88 if (kill(getpid(), sig) != 0) { 89 med_perror("kill(getpid())"); 90 med_exit(-sig); 91 } 92 } 93 94 /* 95 * initialize daemon 96 */ 97 static int 98 med_setup( 99 med_err_t *medep 100 ) 101 { 102 /* catch common signals */ 103 if ((sigset(SIGHUP, med_catcher) == SIG_ERR) || 104 (sigset(SIGINT, med_catcher) == SIG_ERR) || 105 (sigset(SIGABRT, med_catcher) == SIG_ERR) || 106 (sigset(SIGBUS, med_catcher) == SIG_ERR) || 107 (sigset(SIGSEGV, med_catcher) == SIG_ERR) || 108 (sigset(SIGPIPE, med_catcher) == SIG_ERR) || 109 (sigset(SIGTERM, med_catcher) == SIG_ERR)) { 110 return (med_error(medep, errno, "sigset")); 111 } 112 113 /* ignore SIGALRM (used in med_cv_timedwait) */ 114 if (sigset(SIGALRM, SIG_IGN) == SIG_ERR) { 115 return (med_error(medep, errno, "sigset")); 116 } 117 118 /* return success */ 119 return (0); 120 } 121 122 /* 123 * (re)initalize daemon 124 */ 125 static int 126 med_init_daemon( 127 med_err_t *medep 128 ) 129 { 130 static int already = 0; 131 132 /* setup */ 133 if (! already) { 134 if (med_setup(medep) != 0) 135 return (-1); 136 openlog(medname, LOG_CONS, LOG_DAEMON); 137 already = 1; 138 } 139 140 /* return success */ 141 return (0); 142 } 143 144 /* 145 * get my nodename 146 */ 147 char * 148 mynode(void) 149 { 150 static struct utsname myuname; 151 static int done = 0; 152 153 if (! done) { 154 if (uname(&myuname) == -1) { 155 med_perror("uname"); 156 assert(0); 157 } 158 done = 1; 159 } 160 return (myuname.nodename); 161 } 162 163 /* 164 * check for trusted host and user 165 */ 166 static int 167 check_host( 168 struct svc_req *rqstp /* RPC stuff */ 169 ) 170 { 171 struct authsys_parms *sys_credp; 172 SVCXPRT *transp = rqstp->rq_xprt; 173 struct netconfig *nconfp = NULL; 174 struct nd_hostservlist *hservlistp = NULL; 175 int i; 176 int rval = -1; 177 char *inplace = NULL; 178 179 /* check for root */ 180 /*LINTED*/ 181 sys_credp = (struct authsys_parms *)rqstp->rq_clntcred; 182 assert(sys_credp != NULL); 183 if (sys_credp->aup_uid != 0) 184 goto out; 185 186 /* get hostnames */ 187 if (transp->xp_netid == NULL) { 188 med_eprintf("transp->xp_netid == NULL\n"); 189 goto out; 190 } 191 if ((nconfp = getnetconfigent(transp->xp_netid)) == NULL) { 192 #ifdef DEBUG 193 nc_perror("getnetconfigent(transp->xp_netid)"); 194 #endif 195 goto out; 196 } 197 if ((__netdir_getbyaddr_nosrv(nconfp, &hservlistp, &transp->xp_rtaddr) 198 != 0) || (hservlistp == NULL)) { 199 #ifdef DEBUG 200 netdir_perror("netdir_getbyaddr(transp->xp_rtaddr)"); 201 #endif 202 goto out; 203 } 204 205 /* check hostnames */ 206 for (i = 0; (i < hservlistp->h_cnt); ++i) { 207 struct nd_hostserv *hservp = &hservlistp->h_hostservs[i]; 208 char *hostname = hservp->h_host; 209 210 inplace = strdup(hostname); 211 sdssc_cm_nm2nid(inplace); 212 if (strcmp(inplace, hostname)) { 213 214 /* 215 * If the names are now different it indicates 216 * that hostname was converted to a nodeid. This 217 * will only occur if hostname is part of the same 218 * cluster that the current node is in. 219 * If the machine is not running in a cluster than 220 * sdssc_cm_nm2nid is a noop which leaves inplace 221 * alone. 222 */ 223 rval = 0; 224 goto out; 225 } 226 227 /* localhost is OK */ 228 if (strcmp(hostname, mynode()) == 0) { 229 rval = 0; 230 goto out; 231 } 232 233 if (strcmp(hostname, "localhost") == 0) { 234 rval = 0; 235 goto out; 236 } 237 238 /* check for remote root access */ 239 if (ruserok(hostname, 1, "root", "root") == 0) { 240 rval = 0; 241 goto out; 242 } 243 } 244 245 /* cleanup, return success */ 246 out: 247 if (inplace) 248 free(inplace); 249 if (hservlistp != NULL) 250 netdir_free(hservlistp, ND_HOSTSERVLIST); 251 if (nconfp != NULL) 252 Free(nconfp); 253 return (rval); 254 } 255 256 /* 257 * check for user in local group 14 258 */ 259 static int 260 check_gid14( 261 uid_t uid 262 ) 263 { 264 struct passwd *pwp; 265 struct group *grp; 266 char **namep; 267 268 /* get user info, check default GID */ 269 if ((pwp = getpwuid(uid)) == NULL) 270 return (-1); 271 if (pwp->pw_gid == MED_GID) 272 return (0); 273 274 /* check in group */ 275 if ((grp = getgrgid(MED_GID)) == NULL) 276 return (-1); 277 for (namep = grp->gr_mem; ((*namep != NULL) && (**namep != '\0')); 278 ++namep) { 279 if (strcmp(*namep, pwp->pw_name) == 0) 280 return (0); 281 } 282 return (-1); 283 } 284 285 /* 286 * check AUTH_SYS 287 */ 288 static int 289 check_sys( 290 struct svc_req *rqstp, /* RPC stuff */ 291 int amode, /* R_OK | W_OK */ 292 med_err_t *medep /* returned status */ 293 ) 294 { 295 #ifdef _REENTRANT 296 static mutex_t mx = DEFAULTMUTEX; 297 #endif /* _REENTRANT */ 298 struct authsys_parms *sys_credp; 299 300 /* for read, anything is OK */ 301 if (! (amode & W_OK)) 302 return (0); 303 304 #ifdef _REENTRANT 305 /* single thread (not really needed if daemon stays single threaded) */ 306 mutex_lock(&mx); 307 #endif /* _REENTRANT */ 308 309 /* check for remote root or METAMED_GID */ 310 /*LINTED*/ 311 sys_credp = (struct authsys_parms *)rqstp->rq_clntcred; 312 if ((check_gid14(sys_credp->aup_uid) == 0) || 313 (check_host(rqstp) == 0)) { 314 #ifdef _REENTRANT 315 mutex_unlock(&mx); 316 #endif /* _REENTRANT */ 317 return (0); 318 } 319 320 /* return failure */ 321 #ifdef _REENTRANT 322 mutex_unlock(&mx); 323 #endif /* _REENTRANT */ 324 return (med_error(medep, EACCES, medname)); 325 } 326 327 /* 328 * setup RPC service 329 * 330 * if can't authenticate return < 0 331 * if any other error return > 0 332 */ 333 int 334 med_init( 335 struct svc_req *rqstp, /* RPC stuff */ 336 int amode, /* R_OK | W_OK */ 337 med_err_t *medep /* returned status */ 338 ) 339 { 340 SVCXPRT *transp = rqstp->rq_xprt; 341 342 /* 343 * initialize 344 */ 345 (void) memset(medep, 0, sizeof (*medep)); 346 347 if (sdssc_bind_library() == SDSSC_ERROR) { 348 (void) med_error(medep, EACCES, 349 "can't bind to cluster library"); 350 return (1); 351 } 352 353 /* 354 * check credentials 355 */ 356 switch (rqstp->rq_cred.oa_flavor) { 357 358 /* UNIX flavor */ 359 case AUTH_SYS: 360 { 361 if (check_sys(rqstp, amode, medep) != 0) 362 return (1); /* error */ 363 break; 364 } 365 366 /* can't authenticate anything else */ 367 default: 368 svcerr_weakauth(transp); 369 return (-1); /* weak authentication */ 370 371 } 372 373 /* 374 * (re)initialize 375 */ 376 if (med_init_daemon(medep) != 0) 377 return (1); /* error */ 378 379 /* return success */ 380 return (0); 381 } 382