1 /* $Id: startinnfeed.c 7065 2004-12-19 21:49:18Z rra $
3 ** Raise system limits and exec innfeed.
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.
19 /* FreeBSD 3.4 RELEASE needs <sys/time.h> before <sys/resource.h>. */
22 # include <sys/time.h>
24 # include <sys/resource.h>
27 #include "inn/innconf.h"
28 #include "inn/messages.h"
31 /* Options for debugging malloc. */
33 # define DMALLOC_OPTIONS \
34 "DMALLOC_OPTIONS=debug=0x4e405c3,inter=100,log=innfeed-logfile"
39 main(int argc, char *argv[])
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);
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;
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);
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))
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);
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). */
89 rl.rlim_cur = RLIM_INFINITY;
90 rl.rlim_max = RLIM_INFINITY;
92 setrlimit(RLIMIT_DATA, &rl);
94 #endif /* HAVE_SETRLIMIT */
96 /* Permanently drop privileges. */
97 if (setuid(news_uid) < 0 || getuid() != news_uid)
98 sysdie("can't setuid to %lu", (unsigned long) news_uid);
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))
106 spawn_path = concat(innconf->pathbin, "/imapfeed", (char *) 0);
109 spawn_path = concat(innconf->pathbin, "/innfeed", (char *) 0);
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;
119 /* Set debugging malloc options. */
121 putenv(DMALLOC_OPTIONS);
125 execv(innfeed_argv[0], innfeed_argv);
126 sysdie("can't exec %s", innfeed_argv[0]);