1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include "mhd_local.h" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <grp.h> 32*0Sstevel@tonic-gate #include <pwd.h> 33*0Sstevel@tonic-gate #include <signal.h> 34*0Sstevel@tonic-gate #include <syslog.h> 35*0Sstevel@tonic-gate #include <netdir.h> 36*0Sstevel@tonic-gate #include <netdb.h> 37*0Sstevel@tonic-gate #include <sys/resource.h> 38*0Sstevel@tonic-gate #include <sys/priocntl.h> 39*0Sstevel@tonic-gate #include <sys/rtpriocntl.h> 40*0Sstevel@tonic-gate #include <sys/utsname.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate extern void nc_perror(const char *msg); 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* daemon name */ 45*0Sstevel@tonic-gate static char *myname = "rpc.metamhd"; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * reset and exit daemon 49*0Sstevel@tonic-gate */ 50*0Sstevel@tonic-gate void 51*0Sstevel@tonic-gate mhd_exit( 52*0Sstevel@tonic-gate int eval 53*0Sstevel@tonic-gate ) 54*0Sstevel@tonic-gate { 55*0Sstevel@tonic-gate /* log exit */ 56*0Sstevel@tonic-gate mhd_eprintf("exiting with %d\n", eval); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* exit with value */ 59*0Sstevel@tonic-gate exit(eval); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* 63*0Sstevel@tonic-gate * signal catchers 64*0Sstevel@tonic-gate */ 65*0Sstevel@tonic-gate static void 66*0Sstevel@tonic-gate mhd_catcher( 67*0Sstevel@tonic-gate int sig 68*0Sstevel@tonic-gate ) 69*0Sstevel@tonic-gate { 70*0Sstevel@tonic-gate char buf[128]; 71*0Sstevel@tonic-gate char *msg; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* log signal */ 74*0Sstevel@tonic-gate if ((msg = strsignal(sig)) == NULL) { 75*0Sstevel@tonic-gate (void) sprintf(buf, "unknown signal %d", sig); 76*0Sstevel@tonic-gate msg = buf; 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate mhd_eprintf("%s\n", msg); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate /* let default handler do it's thing */ 81*0Sstevel@tonic-gate (void) sigset(sig, SIG_DFL); 82*0Sstevel@tonic-gate if (kill(getpid(), sig) != 0) { 83*0Sstevel@tonic-gate mhd_perror("kill(getpid())"); 84*0Sstevel@tonic-gate mhd_exit(-sig); 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate /* 89*0Sstevel@tonic-gate * initialize daemon 90*0Sstevel@tonic-gate */ 91*0Sstevel@tonic-gate static int 92*0Sstevel@tonic-gate mhd_setup( 93*0Sstevel@tonic-gate mhd_error_t *mhep 94*0Sstevel@tonic-gate ) 95*0Sstevel@tonic-gate { 96*0Sstevel@tonic-gate struct rlimit rlimit; 97*0Sstevel@tonic-gate pcinfo_t pcinfo; 98*0Sstevel@tonic-gate pcparms_t pcparms; 99*0Sstevel@tonic-gate rtparms_t *rtparmsp = (rtparms_t *)pcparms.pc_clparms; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* catch common signals */ 102*0Sstevel@tonic-gate if ((sigset(SIGHUP, mhd_catcher) == SIG_ERR) || 103*0Sstevel@tonic-gate (sigset(SIGINT, mhd_catcher) == SIG_ERR) || 104*0Sstevel@tonic-gate (sigset(SIGABRT, mhd_catcher) == SIG_ERR) || 105*0Sstevel@tonic-gate (sigset(SIGBUS, mhd_catcher) == SIG_ERR) || 106*0Sstevel@tonic-gate (sigset(SIGSEGV, mhd_catcher) == SIG_ERR) || 107*0Sstevel@tonic-gate (sigset(SIGPIPE, mhd_catcher) == SIG_ERR) || 108*0Sstevel@tonic-gate (sigset(SIGTERM, mhd_catcher) == SIG_ERR)) { 109*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "sigset")); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* ignore SIGHUP (used in mhd_cv_timedwait) */ 113*0Sstevel@tonic-gate if (sigset(SIGALRM, SIG_IGN) == SIG_ERR) { 114*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "sigset")); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate /* increase number of file descriptors */ 118*0Sstevel@tonic-gate (void) memset(&rlimit, 0, sizeof (rlimit)); 119*0Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlimit) != 0) 120*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "getrlimit(RLIMIT_NOFILE)")); 121*0Sstevel@tonic-gate rlimit.rlim_cur = rlimit.rlim_max = 1024; 122*0Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlimit) != 0) 123*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "setrlimit(RLIMIT_NOFILE)")); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* set default RT priority */ 126*0Sstevel@tonic-gate (void) memset(&pcinfo, 0, sizeof (pcinfo)); 127*0Sstevel@tonic-gate (void) strncpy(pcinfo.pc_clname, "RT", sizeof (pcinfo.pc_clname)); 128*0Sstevel@tonic-gate if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) < 0) 129*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "priocntl(PC_GETCID): \"RT\"")); 130*0Sstevel@tonic-gate (void) memset(&pcparms, 0, sizeof (pcparms)); 131*0Sstevel@tonic-gate pcparms.pc_cid = pcinfo.pc_cid; 132*0Sstevel@tonic-gate rtparmsp->rt_pri = RT_NOCHANGE; 133*0Sstevel@tonic-gate rtparmsp->rt_tqsecs = (ulong_t)RT_NOCHANGE; 134*0Sstevel@tonic-gate rtparmsp->rt_tqnsecs = RT_NOCHANGE; 135*0Sstevel@tonic-gate if (priocntl(P_PID, getpid(), PC_SETPARMS, (caddr_t)&pcparms) != 0) 136*0Sstevel@tonic-gate return (mhd_error(mhep, errno, "priocntl(PC_SETPARMS)")); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* return success */ 139*0Sstevel@tonic-gate return (0); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * (re)initalize daemon 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate static int 146*0Sstevel@tonic-gate mhd_init_daemon( 147*0Sstevel@tonic-gate mhd_error_t *mhep 148*0Sstevel@tonic-gate ) 149*0Sstevel@tonic-gate { 150*0Sstevel@tonic-gate static int already = 0; 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate /* setup */ 153*0Sstevel@tonic-gate if (! already) { 154*0Sstevel@tonic-gate if (mhd_setup(mhep) != 0) 155*0Sstevel@tonic-gate return (-1); 156*0Sstevel@tonic-gate openlog(myname, LOG_CONS, LOG_DAEMON); 157*0Sstevel@tonic-gate already = 1; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* return success */ 161*0Sstevel@tonic-gate return (0); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * get my nodename 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate static char * 168*0Sstevel@tonic-gate mynodename() 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate static struct utsname myuname; 171*0Sstevel@tonic-gate static int done = 0; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate if (! done) { 174*0Sstevel@tonic-gate if (uname(&myuname) == -1) { 175*0Sstevel@tonic-gate mhd_perror("uname"); 176*0Sstevel@tonic-gate assert(0); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate done = 1; 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate return (myuname.nodename); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * check for trusted host and user 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate static int 187*0Sstevel@tonic-gate check_host( 188*0Sstevel@tonic-gate struct svc_req *rqstp /* RPC stuff */ 189*0Sstevel@tonic-gate ) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate struct authsys_parms *sys_credp; 192*0Sstevel@tonic-gate SVCXPRT *transp = rqstp->rq_xprt; 193*0Sstevel@tonic-gate struct netconfig *nconfp = NULL; 194*0Sstevel@tonic-gate struct nd_hostservlist *hservlistp = NULL; 195*0Sstevel@tonic-gate int i; 196*0Sstevel@tonic-gate int rval = -1; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* check for root */ 199*0Sstevel@tonic-gate /*LINTED*/ 200*0Sstevel@tonic-gate sys_credp = (struct authsys_parms *)rqstp->rq_clntcred; 201*0Sstevel@tonic-gate assert(sys_credp != NULL); 202*0Sstevel@tonic-gate if (sys_credp->aup_uid != 0) 203*0Sstevel@tonic-gate goto out; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* get hostnames */ 206*0Sstevel@tonic-gate if (transp->xp_netid == NULL) { 207*0Sstevel@tonic-gate mhd_eprintf("transp->xp_netid == NULL\n"); 208*0Sstevel@tonic-gate goto out; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate if ((nconfp = getnetconfigent(transp->xp_netid)) == NULL) { 211*0Sstevel@tonic-gate #ifdef DEBUG 212*0Sstevel@tonic-gate nc_perror("getnetconfigent(transp->xp_netid)"); 213*0Sstevel@tonic-gate #endif 214*0Sstevel@tonic-gate goto out; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate if ((__netdir_getbyaddr_nosrv(nconfp, &hservlistp, &transp->xp_rtaddr) 217*0Sstevel@tonic-gate != 0) || (hservlistp == NULL)) { 218*0Sstevel@tonic-gate #ifdef DEBUG 219*0Sstevel@tonic-gate netdir_perror("netdir_getbyaddr(transp->xp_rtaddr)"); 220*0Sstevel@tonic-gate #endif 221*0Sstevel@tonic-gate goto out; 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate /* check hostnames */ 225*0Sstevel@tonic-gate for (i = 0; (i < hservlistp->h_cnt); ++i) { 226*0Sstevel@tonic-gate struct nd_hostserv *hservp = &hservlistp->h_hostservs[i]; 227*0Sstevel@tonic-gate char *hostname = hservp->h_host; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* localhost is OK */ 230*0Sstevel@tonic-gate if (strcmp(hostname, mynodename()) == 0) { 231*0Sstevel@tonic-gate rval = 0; 232*0Sstevel@tonic-gate goto out; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* check for remote root access */ 236*0Sstevel@tonic-gate if (ruserok(hostname, 1, "root", "root") == 0) { 237*0Sstevel@tonic-gate rval = 0; 238*0Sstevel@tonic-gate goto out; 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* cleanup, return success */ 243*0Sstevel@tonic-gate out: 244*0Sstevel@tonic-gate if (hservlistp != NULL) 245*0Sstevel@tonic-gate netdir_free(hservlistp, ND_HOSTSERVLIST); 246*0Sstevel@tonic-gate if (nconfp != NULL) 247*0Sstevel@tonic-gate Free(nconfp); 248*0Sstevel@tonic-gate return (rval); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * check for user in local group 14 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate static int 255*0Sstevel@tonic-gate check_gid14( 256*0Sstevel@tonic-gate uid_t uid 257*0Sstevel@tonic-gate ) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate struct passwd *pwp; 260*0Sstevel@tonic-gate struct group *grp; 261*0Sstevel@tonic-gate char **namep; 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* get user info, check default GID */ 264*0Sstevel@tonic-gate if ((pwp = getpwuid(uid)) == NULL) 265*0Sstevel@tonic-gate return (-1); 266*0Sstevel@tonic-gate if (pwp->pw_gid == METAMHD_GID) 267*0Sstevel@tonic-gate return (0); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /* check in group */ 270*0Sstevel@tonic-gate if ((grp = getgrgid(METAMHD_GID)) == NULL) 271*0Sstevel@tonic-gate return (-1); 272*0Sstevel@tonic-gate for (namep = grp->gr_mem; ((*namep != NULL) && (**namep != '\0')); 273*0Sstevel@tonic-gate ++namep) { 274*0Sstevel@tonic-gate if (strcmp(*namep, pwp->pw_name) == 0) 275*0Sstevel@tonic-gate return (0); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate return (-1); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate /* 281*0Sstevel@tonic-gate * check AUTH_SYS 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate static int 284*0Sstevel@tonic-gate check_sys( 285*0Sstevel@tonic-gate struct svc_req *rqstp, /* RPC stuff */ 286*0Sstevel@tonic-gate int amode, /* R_OK | W_OK */ 287*0Sstevel@tonic-gate mhd_error_t *mhep /* returned status */ 288*0Sstevel@tonic-gate ) 289*0Sstevel@tonic-gate { 290*0Sstevel@tonic-gate static mutex_t mx = DEFAULTMUTEX; 291*0Sstevel@tonic-gate struct authsys_parms *sys_credp; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate /* for read, anything is OK */ 294*0Sstevel@tonic-gate if (! (amode & W_OK)) 295*0Sstevel@tonic-gate return (0); 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* single thread (not really needed if daemon stays single threaded) */ 298*0Sstevel@tonic-gate mutex_lock(&mx); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate /* check for remote root or METAMHD_GID */ 301*0Sstevel@tonic-gate /*LINTED*/ 302*0Sstevel@tonic-gate sys_credp = (struct authsys_parms *)rqstp->rq_clntcred; 303*0Sstevel@tonic-gate if ((check_gid14(sys_credp->aup_uid) == 0) || 304*0Sstevel@tonic-gate (check_host(rqstp) == 0)) { 305*0Sstevel@tonic-gate mutex_unlock(&mx); 306*0Sstevel@tonic-gate return (0); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* return failure */ 310*0Sstevel@tonic-gate mutex_unlock(&mx); 311*0Sstevel@tonic-gate return (mhd_error(mhep, EACCES, myname)); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * setup RPC service 316*0Sstevel@tonic-gate * 317*0Sstevel@tonic-gate * if can't authenticate return < 0 318*0Sstevel@tonic-gate * if any other error return > 0 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate int 321*0Sstevel@tonic-gate mhd_init( 322*0Sstevel@tonic-gate struct svc_req *rqstp, /* RPC stuff */ 323*0Sstevel@tonic-gate int amode, /* R_OK | W_OK */ 324*0Sstevel@tonic-gate mhd_error_t *mhep /* returned status */ 325*0Sstevel@tonic-gate ) 326*0Sstevel@tonic-gate { 327*0Sstevel@tonic-gate SVCXPRT *transp = rqstp->rq_xprt; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * initialize 331*0Sstevel@tonic-gate */ 332*0Sstevel@tonic-gate (void) memset(mhep, 0, sizeof (*mhep)); 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate /* 335*0Sstevel@tonic-gate * check credentials 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate switch (rqstp->rq_cred.oa_flavor) { 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate /* UNIX flavor */ 340*0Sstevel@tonic-gate case AUTH_SYS: 341*0Sstevel@tonic-gate { 342*0Sstevel@tonic-gate if (check_sys(rqstp, amode, mhep) != 0) 343*0Sstevel@tonic-gate return (1); /* error */ 344*0Sstevel@tonic-gate break; 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate /* can't authenticate anything else */ 348*0Sstevel@tonic-gate default: 349*0Sstevel@tonic-gate svcerr_weakauth(transp); 350*0Sstevel@tonic-gate return (-1); /* weak authentication */ 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* 355*0Sstevel@tonic-gate * (re)initialize 356*0Sstevel@tonic-gate */ 357*0Sstevel@tonic-gate if (mhd_init_daemon(mhep) != 0) 358*0Sstevel@tonic-gate return (1); /* error */ 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* return success */ 361*0Sstevel@tonic-gate return (0); 362*0Sstevel@tonic-gate } 363