1 /*
2  * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3  * Copyright (c) 2006-2014 Sippy Software, Inc., http://www.sippysoft.com
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/sysctl.h>
32 #include <sys/resource.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <stdint.h>
36 #include <signal.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "config.h"
42 
43 #include "rtpp_log.h"
44 #include "rtpp_cfg_stable.h"
45 #include "rtpp_defines.h"
46 #include "rtpp_util.h"
47 #include "rtpp_types.h"
48 #include "rtpp_log_obj.h"
49 
50 void
seedrandom(void)51 seedrandom(void)
52 {
53     int fd;
54     unsigned long junk;
55     struct timeval tv;
56 
57     fd = open("/dev/urandom", O_RDONLY, 0);
58     if (fd >= 0) {
59 	read(fd, &junk, sizeof(junk));
60 	close(fd);
61     } else {
62         junk = 0;
63     }
64 
65     gettimeofday(&tv, NULL);
66     srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
67 }
68 
69 int
set_rlimits(struct cfg * cf)70 set_rlimits(struct cfg *cf)
71 {
72     struct rlimit rlp;
73 
74     if (getrlimit(RLIMIT_CORE, &rlp) < 0) {
75         RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "getrlimit(RLIMIT_CORE)");
76         return (-1);
77     }
78     rlp.rlim_cur = RLIM_INFINITY;
79     rlp.rlim_max = RLIM_INFINITY;
80     if (setrlimit(RLIMIT_CORE, &rlp) < 0) {
81         RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "setrlimit(RLIMIT_CORE)");
82         return (-1);
83     }
84     return (0);
85 }
86 
87 int
drop_privileges(struct cfg * cf)88 drop_privileges(struct cfg *cf)
89 {
90 
91     if (cf->stable->run_gname != NULL) {
92 	if (setgid(cf->stable->run_gid) != 0) {
93 	    RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "can't set current group ID: %d", cf->stable->run_gid);
94 	    return -1;
95 	}
96     }
97     if (cf->stable->run_uname == NULL)
98 	return 0;
99     if (setuid(cf->stable->run_uid) != 0) {
100 	RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "can't set current user ID: %d", cf->stable->run_uid);
101 	return -1;
102     }
103     return 0;
104 }
105 
106 /*
107  * Portable strsep(3) implementation, borrowed from FreeBSD. For license
108  * and other information see:
109  *
110  * $FreeBSD: src/lib/libc/string/strsep.c,v 1.6 2007/01/09 00:28:12 imp Exp $
111  */
112 char *
rtpp_strsep(char ** stringp,const char * delim)113 rtpp_strsep(char **stringp, const char *delim)
114 {
115     char *s;
116     const char *spanp;
117     int c, sc;
118     char *tok;
119 
120     if ((s = *stringp) == NULL)
121 	return (NULL);
122     for (tok = s;;) {
123 	c = *s++;
124 	spanp = delim;
125 	do {
126 	    if ((sc = *spanp++) == c) {
127 		if (c == 0)
128 		    s = NULL;
129 		else
130 		    s[-1] = 0;
131 		*stringp = s;
132 		return (tok);
133 	    }
134 	} while (sc != 0);
135     }
136     /* NOTREACHED */
137 }
138 
139 /*
140  * Portable daemon(3) implementation, borrowed from FreeBSD. For license
141  * and other information see:
142  *
143  * $FreeBSD: src/lib/libc/gen/daemon.c,v 1.8 2007/01/09 00:27:53 imp Exp $
144  */
145 int
rtpp_daemon(int nochdir,int noclose)146 rtpp_daemon(int nochdir, int noclose)
147 {
148     struct sigaction osa, sa;
149     int fd;
150     pid_t newgrp;
151     int oerrno;
152     int osa_ok;
153 
154     /* A SIGHUP may be thrown when the parent exits below. */
155     sigemptyset(&sa.sa_mask);
156     sa.sa_handler = SIG_IGN;
157     sa.sa_flags = 0;
158     osa_ok = sigaction(SIGHUP, &sa, &osa);
159 
160     switch (fork()) {
161     case -1:
162         return (-1);
163     case 0:
164         break;
165     default:
166         _exit(0);
167     }
168 
169     newgrp = setsid();
170     oerrno = errno;
171     if (osa_ok != -1)
172         sigaction(SIGHUP, &osa, NULL);
173 
174     if (newgrp == -1) {
175         errno = oerrno;
176         return (-1);
177     }
178 
179     if (!nochdir)
180         (void)chdir("/");
181 
182     if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
183         (void)dup2(fd, STDIN_FILENO);
184 #if !defined(RTPP_DEBUG)
185         (void)dup2(fd, STDOUT_FILENO);
186         (void)dup2(fd, STDERR_FILENO);
187 #endif
188         if (fd > 2)
189             (void)close(fd);
190     }
191     return (0);
192 }
193 
194 static int8_t hex2char[128] = {
195     -1,  -1,  -1,  -1,  -1,  -1,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
196     -1,  -1,  -1,  -1,  -1,  -1,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
197     -1,  -1,  -1,  -1,  -1,  -1,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
198      0,   1,   2,   3,   4,   5,   6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
199     -1, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, -1, -1, -1, -1, -1, -1, -1, -1, -1,
200     -1,  -1,  -1,  -1,  -1,  -1,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
201     -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
202     -1,  -1,  -1,  -1,  -1,  -1,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
203 };
204 
205 int
url_unquote(unsigned char * buf,int len)206 url_unquote(unsigned char *buf, int len)
207 {
208     int outlen;
209     uint8_t *cp;
210 
211     outlen = len;
212     while (len > 0) {
213         cp = memchr(buf, '%', len);
214         if (cp == NULL)
215             return (outlen);
216         if (cp - buf + 2 > len)
217             return (-1);
218         if (cp[1] > 127 || cp[2] > 127 ||
219           hex2char[cp[1]] == -1 || hex2char[cp[2]] == -1)
220             return (-1);
221         cp[0] = (hex2char[cp[1]] << 4) | hex2char[cp[2]];
222         len -= cp - buf + 3;
223         if (len > 0)
224             memmove(cp + 1, cp + 3, len);
225         buf = cp + 1;
226         outlen -= 2;
227     }
228     return (outlen);
229 }
230 
231 #if defined(_SC_CLK_TCK) && !defined(__FreeBSD__)
232 #if defined(LINUX_XXX)
233 static int
rtpp_get_sched_hz_linux(void)234 rtpp_get_sched_hz_linux(void)
235 {
236     int fd, rlen;
237     char buf[16], *cp;
238     int64_t n;
239 
240     fd = open("/proc/sys/kernel/sched_min_granularity_ns", O_RDONLY, 0);
241     if (fd == -1) {
242         return (-1);
243     }
244     rlen = read(fd, buf, sizeof(buf) - 1);
245     close(fd);
246     if (rlen <= 0) {
247         return (-1);
248     }
249     buf[rlen] = '\0';
250     n = strtol(buf, &cp, 10);
251     if (cp == buf) {
252         return (-1);
253     }
254     return ((int64_t)1000000000 / n);
255 }
256 #endif
257 
258 int
rtpp_get_sched_hz(void)259 rtpp_get_sched_hz(void)
260 {
261     int sched_hz;
262 
263 #if defined (LINUX_XXX)
264     sched_hz = rtpp_get_sched_hz_linux();
265     if (sched_hz > 0) {
266         return (sched_hz);
267     }
268 #endif
269     sched_hz = sysconf(_SC_CLK_TCK);
270     return (sched_hz > 0 ? sched_hz : 100);
271 }
272 #else
273 int
rtpp_get_sched_hz(void)274 rtpp_get_sched_hz(void)
275 {
276     int sched_hz;
277     size_t len;
278 
279     len = sizeof(sched_hz);
280     if (sysctlbyname("kern.hz", &sched_hz, &len, NULL, 0) == -1 || sched_hz <= 0)
281         return 1000;
282     return (sched_hz);
283 }
284 #endif
285 
286 #ifndef HAVE_STRLCPY
287 /*
288  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
289  * All rights reserved.
290  *
291  * Redistribution and use in source and binary forms, with or without
292  * modification, are permitted provided that the following conditions
293  * are met:
294  * 1. Redistributions of source code must retain the above copyright
295  *    notice, this list of conditions and the following disclaimer.
296  * 2. Redistributions in binary form must reproduce the above copyright
297  *    notice, this list of conditions and the following disclaimer in the
298  *    documentation and/or other materials provided with the distribution.
299  * 3. The name of the author may not be used to endorse or promote products
300  *    derived from this software without specific prior written permission.
301  *
302  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
303  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
304  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
305  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
306  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
307  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
308  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
309  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
310  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
311  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
312  */
313 
314 /*
315  * Copy src to string dst of size siz.  At most siz-1 characters
316  * will be copied.  Always NUL terminates (unless siz == 0).
317  * Returns strlen(src); if retval >= siz, truncation occurred.
318  */
strlcpy(dst,src,siz)319 size_t strlcpy(dst, src, siz)
320 	char *dst;
321 	const char *src;
322 	size_t siz;
323 {
324 	char *d = dst;
325 	const char *s = src;
326 	size_t n = siz;
327 
328 	/* Copy as many bytes as will fit */
329 	if (n != 0 && --n != 0) {
330 		do {
331 			if ((*d++ = *s++) == 0)
332 				break;
333 		} while (--n != 0);
334 	}
335 
336 	/* Not enough room in dst, add NUL and traverse rest of src */
337 	if (n == 0) {
338 		if (siz != 0)
339 			*d = '\0';		/* NUL-terminate dst */
340 		while (*s++)
341 			;
342 	}
343 
344 	return(s - src - 1);	/* count does not include NUL */
345 }
346 
347 #endif /* !HAVE_STRLCPY */
348