7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / cmd / lvm / rpc.metamhd / mhd_init.c
blobd0c47e0b4917540a535ca598a45b373fe8ffe235
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include "mhd_local.h"
28 #include <grp.h>
29 #include <pwd.h>
30 #include <signal.h>
31 #include <stdio_ext.h>
32 #include <syslog.h>
33 #include <netdir.h>
34 #include <netdb.h>
35 #include <sys/resource.h>
36 #include <sys/priocntl.h>
37 #include <sys/rtpriocntl.h>
38 #include <sys/utsname.h>
40 extern void nc_perror(const char *msg);
42 /* daemon name */
43 static char *myname = "rpc.metamhd";
46 * reset and exit daemon
48 void
49 mhd_exit(
50 int eval
53 /* log exit */
54 mhd_eprintf("exiting with %d\n", eval);
56 /* exit with value */
57 exit(eval);
61 * signal catchers
63 static void
64 mhd_catcher(
65 int sig
68 char buf[128];
69 char *msg;
71 /* log signal */
72 if ((msg = strsignal(sig)) == NULL) {
73 (void) sprintf(buf, "unknown signal %d", sig);
74 msg = buf;
76 mhd_eprintf("%s\n", msg);
78 /* let default handler do it's thing */
79 (void) sigset(sig, SIG_DFL);
80 if (kill(getpid(), sig) != 0) {
81 mhd_perror("kill(getpid())");
82 mhd_exit(-sig);
87 * initialize daemon
89 static int
90 mhd_setup(
91 mhd_error_t *mhep
94 struct rlimit rlimit;
95 pcinfo_t pcinfo;
96 pcparms_t pcparms;
97 rtparms_t *rtparmsp = (rtparms_t *)pcparms.pc_clparms;
99 /* catch common signals */
100 if ((sigset(SIGHUP, mhd_catcher) == SIG_ERR) ||
101 (sigset(SIGINT, mhd_catcher) == SIG_ERR) ||
102 (sigset(SIGABRT, mhd_catcher) == SIG_ERR) ||
103 (sigset(SIGBUS, mhd_catcher) == SIG_ERR) ||
104 (sigset(SIGSEGV, mhd_catcher) == SIG_ERR) ||
105 (sigset(SIGPIPE, mhd_catcher) == SIG_ERR) ||
106 (sigset(SIGTERM, mhd_catcher) == SIG_ERR)) {
107 return (mhd_error(mhep, errno, "sigset"));
110 /* ignore SIGHUP (used in mhd_cv_timedwait) */
111 if (sigset(SIGALRM, SIG_IGN) == SIG_ERR) {
112 return (mhd_error(mhep, errno, "sigset"));
115 /* increase number of file descriptors */
116 (void) memset(&rlimit, 0, sizeof (rlimit));
117 if (getrlimit(RLIMIT_NOFILE, &rlimit) != 0)
118 return (mhd_error(mhep, errno, "getrlimit(RLIMIT_NOFILE)"));
119 rlimit.rlim_cur = rlimit.rlim_max = 1024;
120 if (setrlimit(RLIMIT_NOFILE, &rlimit) != 0)
121 return (mhd_error(mhep, errno, "setrlimit(RLIMIT_NOFILE)"));
122 (void) enable_extended_FILE_stdio(-1, -1);
124 /* set default RT priority */
125 (void) memset(&pcinfo, 0, sizeof (pcinfo));
126 (void) strncpy(pcinfo.pc_clname, "RT", sizeof (pcinfo.pc_clname));
127 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) < 0)
128 return (mhd_error(mhep, errno, "priocntl(PC_GETCID): \"RT\""));
129 (void) memset(&pcparms, 0, sizeof (pcparms));
130 pcparms.pc_cid = pcinfo.pc_cid;
131 rtparmsp->rt_pri = RT_NOCHANGE;
132 rtparmsp->rt_tqsecs = (ulong_t)RT_NOCHANGE;
133 rtparmsp->rt_tqnsecs = RT_NOCHANGE;
134 if (priocntl(P_PID, getpid(), PC_SETPARMS, (caddr_t)&pcparms) != 0)
135 return (mhd_error(mhep, errno, "priocntl(PC_SETPARMS)"));
137 /* return success */
138 return (0);
142 * (re)initalize daemon
144 static int
145 mhd_init_daemon(
146 mhd_error_t *mhep
149 static int already = 0;
151 /* setup */
152 if (! already) {
153 if (mhd_setup(mhep) != 0)
154 return (-1);
155 openlog(myname, LOG_CONS, LOG_DAEMON);
156 already = 1;
159 /* return success */
160 return (0);
164 * get my nodename
166 static char *
167 mynodename()
169 static struct utsname myuname;
170 static int done = 0;
172 if (! done) {
173 if (uname(&myuname) == -1) {
174 mhd_perror("uname");
175 assert(0);
177 done = 1;
179 return (myuname.nodename);
183 * check for trusted host and user
185 static int
186 check_host(
187 struct svc_req *rqstp /* RPC stuff */
190 struct authsys_parms *sys_credp;
191 SVCXPRT *transp = rqstp->rq_xprt;
192 struct netconfig *nconfp = NULL;
193 struct nd_hostservlist *hservlistp = NULL;
194 int i;
195 int rval = -1;
197 /* check for root */
198 /*LINTED*/
199 sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
200 assert(sys_credp != NULL);
201 if (sys_credp->aup_uid != 0)
202 goto out;
204 /* get hostnames */
205 if (transp->xp_netid == NULL) {
206 mhd_eprintf("transp->xp_netid == NULL\n");
207 goto out;
209 if ((nconfp = getnetconfigent(transp->xp_netid)) == NULL) {
210 #ifdef DEBUG
211 nc_perror("getnetconfigent(transp->xp_netid)");
212 #endif
213 goto out;
215 if ((__netdir_getbyaddr_nosrv(nconfp, &hservlistp, &transp->xp_rtaddr)
216 != 0) || (hservlistp == NULL)) {
217 #ifdef DEBUG
218 netdir_perror("netdir_getbyaddr(transp->xp_rtaddr)");
219 #endif
220 goto out;
223 /* check hostnames */
224 for (i = 0; (i < hservlistp->h_cnt); ++i) {
225 struct nd_hostserv *hservp = &hservlistp->h_hostservs[i];
226 char *hostname = hservp->h_host;
228 /* localhost is OK */
229 if (strcmp(hostname, mynodename()) == 0) {
230 rval = 0;
231 goto out;
234 /* check for remote root access */
235 if (ruserok(hostname, 1, "root", "root") == 0) {
236 rval = 0;
237 goto out;
241 /* cleanup, return success */
242 out:
243 if (hservlistp != NULL)
244 netdir_free(hservlistp, ND_HOSTSERVLIST);
245 if (nconfp != NULL)
246 Free(nconfp);
247 return (rval);
251 * check for user in local group 14
253 static int
254 check_gid14(
255 uid_t uid
258 struct passwd *pwp;
259 struct group *grp;
260 char **namep;
262 /* get user info, check default GID */
263 if ((pwp = getpwuid(uid)) == NULL)
264 return (-1);
265 if (pwp->pw_gid == METAMHD_GID)
266 return (0);
268 /* check in group */
269 if ((grp = getgrgid(METAMHD_GID)) == NULL)
270 return (-1);
271 for (namep = grp->gr_mem; ((*namep != NULL) && (**namep != '\0'));
272 ++namep) {
273 if (strcmp(*namep, pwp->pw_name) == 0)
274 return (0);
276 return (-1);
280 * check AUTH_SYS
282 static int
283 check_sys(
284 struct svc_req *rqstp, /* RPC stuff */
285 int amode, /* R_OK | W_OK */
286 mhd_error_t *mhep /* returned status */
289 static mutex_t mx = DEFAULTMUTEX;
290 struct authsys_parms *sys_credp;
292 /* for read, anything is OK */
293 if (! (amode & W_OK))
294 return (0);
296 /* single thread (not really needed if daemon stays single threaded) */
297 (void) mutex_lock(&mx);
299 /* check for remote root or METAMHD_GID */
300 /*LINTED*/
301 sys_credp = (struct authsys_parms *)rqstp->rq_clntcred;
302 if ((check_gid14(sys_credp->aup_uid) == 0) ||
303 (check_host(rqstp) == 0)) {
304 (void) mutex_unlock(&mx);
305 return (0);
308 /* return failure */
309 (void) mutex_unlock(&mx);
310 return (mhd_error(mhep, EACCES, myname));
314 * setup RPC service
316 * if can't authenticate return < 0
317 * if any other error return > 0
320 mhd_init(
321 struct svc_req *rqstp, /* RPC stuff */
322 int amode, /* R_OK | W_OK */
323 mhd_error_t *mhep /* returned status */
326 SVCXPRT *transp = rqstp->rq_xprt;
329 * initialize
331 (void) memset(mhep, 0, sizeof (*mhep));
334 * check credentials
336 switch (rqstp->rq_cred.oa_flavor) {
338 /* UNIX flavor */
339 case AUTH_SYS:
341 if (check_sys(rqstp, amode, mhep) != 0)
342 return (1); /* error */
343 break;
346 /* can't authenticate anything else */
347 default:
348 svcerr_weakauth(transp);
349 return (-1); /* weak authentication */
354 * (re)initialize
356 if (mhd_init_daemon(mhep) != 0)
357 return (1); /* error */
359 /* return success */
360 return (0);