]> git.ipfire.org Git - people/ms/dma.git/blame - util.c
Merge pull request #34 from mtremer/better-authentication
[people/ms/dma.git] / util.c
CommitLineData
de13a881 1/*
e458e5f0 2 * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
de13a881
SS
3 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 *
5 * This code is derived from software contributed to The DragonFly Project
e458e5f0 6 * by Simon Schubert <2@0x2c.org>.
de13a881
SS
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/param.h>
9b921550
SS
37#include <sys/file.h>
38
27905878 39#include <ctype.h>
de13a881
SS
40#include <errno.h>
41#include <fcntl.h>
42#include <netdb.h>
43#include <pwd.h>
a71122e7
SS
44#include <setjmp.h>
45#include <signal.h>
de13a881
SS
46#include <stdio.h>
47#include <syslog.h>
48#include <unistd.h>
49
50#include "dma.h"
51
52const char *
53hostname(void)
54{
6ec95705
SS
55#ifndef HOST_NAME_MAX
56#define HOST_NAME_MAX 255
57#endif
d6240370 58 static char name[HOST_NAME_MAX+1];
3b322ad4 59 static int initialized = 0;
c3fb272b 60 char *s;
de13a881
SS
61
62 if (initialized)
63 return (name);
64
27905878
SS
65 if (config.mailname == NULL || !*config.mailname)
66 goto local;
67
68 if (config.mailname[0] == '/') {
69 /*
70 * If the mailname looks like an absolute path,
71 * treat it as a file.
72 */
73 FILE *fp;
27905878
SS
74
75 fp = fopen(config.mailname, "r");
76 if (fp == NULL)
77 goto local;
78
c3fb272b 79 s = fgets(name, sizeof(name), fp);
27905878 80 fclose(fp);
c3fb272b 81 if (s == NULL)
27905878
SS
82 goto local;
83
c3fb272b
SS
84 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
85 /* NOTHING */;
86 *s = 0;
27905878
SS
87
88 if (!*name)
89 goto local;
90
91 initialized = 1;
92 return (name);
93 } else {
a0c4afa6 94 snprintf(name, sizeof(name), "%s", config.mailname);
de13a881
SS
95 initialized = 1;
96 return (name);
97 }
27905878
SS
98
99local:
de13a881 100 if (gethostname(name, sizeof(name)) != 0)
c3fb272b 101 *name = 0;
d6240370
SS
102 /*
103 * gethostname() is allowed to truncate name without NUL-termination
104 * and at the same time not return an error.
105 */
106 name[sizeof(name) - 1] = 0;
c3fb272b
SS
107
108 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
109 /* NOTHING */;
110 *s = 0;
111
112 if (!*name)
113 snprintf(name, sizeof(name), "unknown-hostname");
114
de13a881 115 initialized = 1;
27905878 116 return (name);
de13a881
SS
117}
118
119void
120setlogident(const char *fmt, ...)
121{
42916656 122 static char tag[50];
de13a881 123
249ee966 124 snprintf(tag, sizeof(tag), "%s", logident_base);
de13a881
SS
125 if (fmt != NULL) {
126 va_list ap;
249ee966 127 char sufx[50];
de13a881
SS
128
129 va_start(ap, fmt);
249ee966 130 vsnprintf(sufx, sizeof(sufx), fmt, ap);
de13a881 131 va_end(ap);
249ee966 132 snprintf(tag, sizeof(tag), "%s[%s]", logident_base, sufx);
de13a881
SS
133 }
134 closelog();
249ee966 135 openlog(tag, 0, LOG_MAIL);
de13a881
SS
136}
137
138void
139errlog(int exitcode, const char *fmt, ...)
140{
141 int oerrno = errno;
142 va_list ap;
249ee966 143 char outs[ERRMSG_SIZE];
de13a881 144
249ee966 145 outs[0] = 0;
de13a881
SS
146 if (fmt != NULL) {
147 va_start(ap, fmt);
249ee966 148 vsnprintf(outs, sizeof(outs), fmt, ap);
de13a881
SS
149 va_end(ap);
150 }
151
65da520c 152 errno = oerrno;
249ee966 153 if (*outs != 0) {
de13a881
SS
154 syslog(LOG_ERR, "%s: %m", outs);
155 fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
156 } else {
157 syslog(LOG_ERR, "%m");
158 fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
159 }
160
161 exit(exitcode);
162}
163
164void
165errlogx(int exitcode, const char *fmt, ...)
166{
167 va_list ap;
249ee966 168 char outs[ERRMSG_SIZE];
de13a881 169
249ee966 170 outs[0] = 0;
de13a881
SS
171 if (fmt != NULL) {
172 va_start(ap, fmt);
249ee966 173 vsnprintf(outs, sizeof(outs), fmt, ap);
de13a881
SS
174 va_end(ap);
175 }
176
249ee966 177 if (*outs != 0) {
de13a881
SS
178 syslog(LOG_ERR, "%s", outs);
179 fprintf(stderr, "%s: %s\n", getprogname(), outs);
180 } else {
181 syslog(LOG_ERR, "Unknown error");
182 fprintf(stderr, "%s: Unknown error\n", getprogname());
183 }
184
185 exit(exitcode);
186}
187
249ee966 188static int
de13a881
SS
189check_username(const char *name, uid_t ckuid)
190{
191 struct passwd *pwd;
192
193 if (name == NULL)
249ee966 194 return (0);
de13a881
SS
195 pwd = getpwnam(name);
196 if (pwd == NULL || pwd->pw_uid != ckuid)
249ee966
SS
197 return (0);
198 snprintf(username, sizeof(username), "%s", name);
199 return (1);
de13a881
SS
200}
201
202void
203set_username(void)
204{
205 struct passwd *pwd;
de13a881 206
75fdf182
SS
207 useruid = getuid();
208 if (check_username(getlogin(), useruid))
de13a881 209 return;
75fdf182 210 if (check_username(getenv("LOGNAME"), useruid))
de13a881 211 return;
75fdf182 212 if (check_username(getenv("USER"), useruid))
de13a881 213 return;
75fdf182 214 pwd = getpwuid(useruid);
249ee966 215 if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0') {
75fdf182 216 if (check_username(pwd->pw_name, useruid))
de13a881 217 return;
de13a881 218 }
75fdf182 219 snprintf(username, sizeof(username), "uid=%ld", (long)useruid);
de13a881
SS
220}
221
222void
223deltmp(void)
224{
225 struct stritem *t;
226
227 SLIST_FOREACH(t, &tmpfs, next) {
228 unlink(t->str);
229 }
230}
231
a71122e7
SS
232static sigjmp_buf sigbuf;
233static int sigbuf_valid;
234
235static void
236sigalrm_handler(int signo)
237{
238 (void)signo; /* so that gcc doesn't complain */
239 if (sigbuf_valid)
240 siglongjmp(sigbuf, 1);
241}
242
243int
244do_timeout(int timeout, int dojmp)
245{
246 struct sigaction act;
247 int ret = 0;
248
249 sigemptyset(&act.sa_mask);
250 act.sa_flags = 0;
251
252 if (timeout) {
253 act.sa_handler = sigalrm_handler;
254 if (sigaction(SIGALRM, &act, NULL) != 0)
255 syslog(LOG_WARNING, "can not set signal handler: %m");
256 if (dojmp) {
257 ret = sigsetjmp(sigbuf, 1);
258 if (ret)
259 goto disable;
260 /* else just programmed */
261 sigbuf_valid = 1;
262 }
263
264 alarm(timeout);
265 } else {
266disable:
267 alarm(0);
268
269 act.sa_handler = SIG_IGN;
270 if (sigaction(SIGALRM, &act, NULL) != 0)
271 syslog(LOG_WARNING, "can not remove signal handler: %m");
272 sigbuf_valid = 0;
273 }
274
275 return (ret);
276}
277
de13a881
SS
278int
279open_locked(const char *fname, int flags, ...)
280{
281 int mode = 0;
282
283 if (flags & O_CREAT) {
284 va_list ap;
285 va_start(ap, flags);
286 mode = va_arg(ap, int);
287 va_end(ap);
288 }
289
290#ifndef O_EXLOCK
291 int fd, save_errno;
292
293 fd = open(fname, flags, mode);
294 if (fd < 0)
295 return(fd);
296 if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
297 save_errno = errno;
298 close(fd);
299 errno = save_errno;
300 return(-1);
301 }
302 return(fd);
303#else
304 return(open(fname, flags|O_EXLOCK, mode));
305#endif
306}
307
308char *
309rfc822date(void)
310{
311 static char str[50];
312 size_t error;
313 time_t now;
314
315 now = time(NULL);
316 error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
317 localtime(&now));
318 if (error == 0)
319 strcpy(str, "(date fail)");
320 return (str);
321}
322
323int
324strprefixcmp(const char *str, const char *prefix)
325{
326 return (strncasecmp(str, prefix, strlen(prefix)));
327}
328
ee613428
SS
329void
330init_random(void)
331{
332 unsigned int seed;
333 int rf;
334
335 rf = open("/dev/urandom", O_RDONLY);
336 if (rf == -1)
337 rf = open("/dev/random", O_RDONLY);
338
339 if (!(rf != -1 && read(rf, &seed, sizeof(seed)) == sizeof(seed)))
340 seed = (time(NULL) ^ getpid()) + (uintptr_t)&seed;
341
342 srandom(seed);
343
344 if (rf != -1)
345 close(rf);
346}