aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2004-12-22 17:11:53 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2004-12-22 17:11:53 +0000
commit558379a898cb3b6d88df1b70512b0da8beca3b7a (patch)
treee59138ac8408c412fff5159eb978cc632c1b64ee /src
parenta937d33de16c39f2a613c9b33e77ab8066be2900 (diff)
downloadipacct-558379a898cb3b6d88df1b70512b0da8beca3b7a.tar.gz
ipacct-558379a898cb3b6d88df1b70512b0da8beca3b7a.tar.bz2
(user): New variable
(options): New option --user (parse_opt): Handle --user (main): Change to non-root privileges.
Diffstat (limited to 'src')
-rw-r--r--src/main.c130
1 files changed, 129 insertions, 1 deletions
diff --git a/src/main.c b/src/main.c
index 1667227..59e8eaf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* $Id: main.c,v 1.5 2002/06/17 16:30:07 gray Exp $ */
+/* $Id: main.c,v 1.6 2004/12/22 17:11:53 gray Exp $ */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
@@ -26,6 +26,7 @@
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
+#include <pwd.h>
#include <syslog.h>
#include <time.h>
#include <errno.h>
@@ -73,6 +74,7 @@ static char *expr = NULL;
static time_t ttw = 0;
static int syntax_check = 0; /* check the config file and exit */
static int test_mode = 0;
+char *user = NULL;
const char *argp_program_version = "ipacct (" PACKAGE ") " VERSION;
static char doc[] = "ip traffic accounting daemon";
@@ -106,6 +108,8 @@ static struct argp_option options[] = {
"Increase verbosity level", 0 },
{ "fixed-clocks", 'x', NULL, 0,
"Dump statistics at precise time intervals", 0 },
+ { "user", 'u', "USER-NAME", 0,
+ "Run with this user privileges", 0 },
{NULL, 0, NULL, 0, NULL, 0}
};
@@ -165,6 +169,9 @@ parse_opt (key, arg, state)
case 'x':
fixed_clocks++;
break;
+ case 'u':
+ user = optarg;
+ break;
default:
return ARGP_ERR_UNKNOWN;
}
@@ -180,6 +187,126 @@ static struct argp argp = {
NULL, NULL
};
+/* Change to the given uid/gid. Clear the supplementary group list.
+ On success returns 0.
+ On failure returns 1 (or exits, depending on topt settings. See
+ anubis_error) */
+static int
+change_privs (uid_t uid, gid_t gid)
+{
+ int rc = 0;
+ gid_t emptygidset[1];
+
+ /* Reset group permissions */
+ emptygidset[0] = gid ? gid : getegid();
+ if (geteuid() == 0 && setgroups(1, emptygidset)) {
+ error ("setgroups(1, %lu) failed: %s",
+ (u_long) emptygidset[0],
+ strerror (errno));
+ rc = 1;
+ }
+
+ /* Switch to the user's gid. On some OSes the effective gid must
+ be reset first */
+
+#if defined(HAVE_SETEGID)
+ if ((rc = setegid(gid)) < 0)
+ error ("setegid(%lu) failed: %s",
+ (u_long) gid, strerror (errno));
+#elif defined(HAVE_SETREGID)
+ if ((rc = setregid(gid, gid)) < 0)
+ error ("setregid(%lu,%lu) failed: %s",
+ (u_long) gid, (u_long) gid, strerror (errno));
+#elif defined(HAVE_SETRESGID)
+ if ((rc = setresgid(gid, gid, gid)) < 0)
+ error ("setresgid(%lu,%lu,%lu) failed: %s",
+ (u_long) gid,
+ (u_long) gid,
+ (u_long) gid,
+ strerror (errno));
+#endif
+
+ if (rc == 0 && gid != 0) {
+ if ((rc = setgid(gid)) < 0 && getegid() != gid)
+ error ("setgid(%lu) failed: %s",
+ (u_long) gid,
+ strerror (errno));
+ if (rc == 0 && getegid() != gid) {
+ error("cannot set effective gid to %lu: %s",
+ (u_long) gid,
+ strerror (errno));
+ rc = 1;
+ }
+ }
+
+ /* now reset uid */
+ if (rc == 0 && uid != 0) {
+ uid_t euid;
+
+ if (setuid(uid)
+ || geteuid() != uid
+ || (getuid() != uid
+ && (geteuid() == 0 || getuid() == 0))) {
+
+#if defined(have_setreuid)
+ if (geteuid() != uid) {
+ if (setreuid(uid, -1) < 0) {
+ syslog (log_error,
+ "setreuid(%lu,-1) failed: %s",
+ (u_long) uid,
+ strerror (errno));
+ rc = 1;
+ }
+ if (setuid(uid) < 0) {
+ syslog (log_error,
+ "second setuid(%lu) failed: %s",
+ (u_long) uid,
+ strerror (errno));
+ rc = 1;
+ }
+ } else
+#endif
+ {
+ error ("setuid(%lu) failed: %s",
+ (u_long) uid,
+ strerror (errno));
+ rc = 1;
+ }
+ }
+
+
+ euid = geteuid();
+ if (uid != 0 && setuid(0) == 0) {
+ error ("seteuid(0) succeeded when it should not");
+ rc = 1;
+ } else if (uid != euid && setuid(euid) == 0) {
+ error ("cannot drop non-root setuid privileges");
+ rc = 1;
+ }
+ }
+ return rc;
+}
+
+void
+change_user ()
+{
+ struct passwd *pwd;
+
+ if (user == NULL)
+ return;
+
+ pwd = getpwnam (user);
+ if (pwd) {
+ if (change_privs (pwd->pw_uid, pwd->pw_gid))
+ exit (1);
+
+ chdir (pwd->pw_dir);
+ syslog (LOG_INFO, "UID:%d (%s), GID:%d, EUID:%d, EGID:%d",
+ (int) getuid (), pwd->pw_name, (int) getgid (),
+ (int) geteuid (), (int) getegid ());
+ }
+}
+
int
main(argc, argv)
int argc;
@@ -245,6 +372,7 @@ main(argc, argv)
init_syslog();
}
+ change_user();
run(pcap, callback);
cleanup();

Return to:

Send suggestions and report system problems to the System administrator.