chiark / gitweb /
abolish xk_Malloc
[inn-innduct.git] / innfeed / startinnfeed.c
1 /*  $Id: startinnfeed.c 7065 2004-12-19 21:49:18Z rra $
2 **
3 **  Raise system limits and exec innfeed.
4 **
5 **  This is a setuid root wrapper around innfeed to increase system limits
6 **  (file descriptor limits and stack and data sizes).  In order to prevent
7 **  abuse, it uses roughly the same security model as inndstart; only the
8 **  news user can run this program, and it attempts to drop privileges when
9 **  doing operations that don't require it.
10 */
11
12 #include "config.h"
13 #include "clibrary.h"
14 #include <syslog.h>
15 #include <errno.h>
16 #include <grp.h>
17 #include <pwd.h>
18
19 /* FreeBSD 3.4 RELEASE needs <sys/time.h> before <sys/resource.h>. */
20 #if HAVE_SETRLIMIT
21 # if HAVE_SYS_TIME_H
22 #  include <sys/time.h>
23 # endif
24 # include <sys/resource.h>
25 #endif
26
27 #include "inn/innconf.h"
28 #include "inn/messages.h"
29 #include "libinn.h"
30
31 /* Options for debugging malloc. */
32 #ifdef USE_DMALLOC
33 # define DMALLOC_OPTIONS \
34     "DMALLOC_OPTIONS=debug=0x4e405c3,inter=100,log=innfeed-logfile"
35 #endif
36
37
38 int
39 main(int argc, char *argv[])
40 {
41     struct passwd *     pwd;
42     struct group *      grp;
43     uid_t               news_uid;
44     gid_t               news_gid;
45     char **             innfeed_argv;
46     char *              spawn_path;
47     int                 i;
48
49 #if HAVE_SETRLIMIT
50     struct rlimit       rl;
51 #endif
52
53     openlog("innfeed", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
54     message_handlers_warn(1, message_log_syslog_warning);
55     message_handlers_die(1, message_log_syslog_err);
56
57     /* Convert NEWSUSER and NEWSGRP to a UID and GID.  getpwnam() and
58        getgrnam() don't set errno normally, so don't print strerror() on
59        failure; it probably contains garbage.*/
60     pwd = getpwnam(NEWSUSER);
61     if (!pwd) die("can't getpwnam(%s)", NEWSUSER);
62     news_uid = pwd->pw_uid;
63     grp = getgrnam(NEWSGRP);
64     if (!grp) die("can't getgrnam(%s)", NEWSGRP);
65     news_gid = grp->gr_gid;
66
67     /* Exit if run by another user. */
68     if (getuid() != news_uid)
69         die("ran by UID %lu, who isn't %s (%lu)", (unsigned long) getuid(),
70             NEWSUSER, (unsigned long) news_uid);
71
72     /* Drop privileges to read inn.conf. */
73     if (seteuid(news_uid) < 0)
74         sysdie("can't seteuid(%lu)", (unsigned long) news_uid);
75     if (!innconf_read(NULL))
76         exit(1);
77
78     /* Regain privileges to increase system limits. */
79     if (seteuid(0) < 0) sysdie("can't seteuid(0)");
80     if (innconf->rlimitnofile >= 0)
81         if (setfdlimit(innconf->rlimitnofile) < 0)
82             syswarn("can't set file descriptor limit to %ld",
83                     innconf->rlimitnofile);
84
85     /* These calls will fail on some systems, such as HP-UX 11.00.  On those
86        systems, we just blindly assume that the stack and data limits are
87        high enough (they generally are). */
88 #if HAVE_SETRLIMIT
89     rl.rlim_cur = RLIM_INFINITY;
90     rl.rlim_max = RLIM_INFINITY;
91 # ifdef RLIMIT_DATA
92     setrlimit(RLIMIT_DATA, &rl);
93 # endif
94 #endif /* HAVE_SETRLIMIT */
95
96     /* Permanently drop privileges. */
97     if (setuid(news_uid) < 0 || getuid() != news_uid)
98         sysdie("can't setuid to %lu", (unsigned long) news_uid);
99
100     /* Check for imapfeed -- continue to use "innfeed" in variable
101        names for historical reasons regardless */
102     if ((argc > 1) && (strcmp(argv[1],"imapfeed") == 0))
103     {
104         argc--;
105         argv++;
106         spawn_path = concat(innconf->pathbin, "/imapfeed", (char *) 0);
107     }
108     else
109         spawn_path = concat(innconf->pathbin, "/innfeed",  (char *) 0);
110
111
112     /* Build the argument vector for innfeed. */
113     innfeed_argv = xmalloc((argc + 1) * sizeof(char *));
114     innfeed_argv[0] = spawn_path;
115     for (i = 1; i <= argc; i++)
116         innfeed_argv[i] = argv[i];
117     innfeed_argv[argc] = NULL;
118
119     /* Set debugging malloc options. */
120 #ifdef USE_DMALLOC
121     putenv(DMALLOC_OPTIONS);
122 #endif
123
124     /* Exec innfeed. */
125     execv(innfeed_argv[0], innfeed_argv);
126     sysdie("can't exec %s", innfeed_argv[0]);
127
128     /* Not reached. */
129     return 1;
130 }