From 2104b80446dfd4bbc26d0d75691de4b4603a30f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Jan 2004 20:48:55 +0000 Subject: implemented user id switching some locking fixups git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@24 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- conf/msntab | 2 +- doc/TODO | 17 +++++++++---- src/ivamd.ggo | 1 + src/lock.c | 22 ++++++++++++++++- src/main.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/main.h | 5 +++- 6 files changed, 112 insertions(+), 13 deletions(-) diff --git a/conf/msntab b/conf/msntab index 251e906..16d8e5e 100644 --- a/conf/msntab +++ b/conf/msntab @@ -1,6 +1,6 @@ # local MSN remote MSN options action -41264179 * rings=0,pipehack ivam-autobox +#41264179 * rings=0,pipehack ivam-autobox #41264179 41264177 rings=0 ivam-dialup --pin=4711 ppp0 #* 41264179 rings=0 @hangup diff --git a/doc/TODO b/doc/TODO index 97e6c8f..c9aad71 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,13 +1,20 @@ +post 1.0: + * implement shbuf support -* uid switching support -* autoconf -* documentation +* uid switching for each client * regexp support * @same support -* uid switching for each client + +pre 1.0: + +* autoconf +* documentation * init script -* mail on successful mailbox creation in ivam-autobox +done: + +* uid switching support (DONE) +* mail on successful mailbox creation in ivam-autobox (DONE) * --no-record --record-only (for voicebox) (DONE) * make it a daemon (DONE) * newmessage script (DONE) diff --git a/src/ivamd.ggo b/src/ivamd.ggo index 67e6f7e..ca280a4 100644 --- a/src/ivamd.ggo +++ b/src/ivamd.ggo @@ -27,3 +27,4 @@ option "check" c "Check if the daemon is currently running" flag off option "channels" C "Specify how many channels to allocate, defaults to 2" int default="2" no option "msntab" T "Specify non standard msntab file" string no option "listen" L "Specify a glob pattern matchin the MSNs to listen on" string no +option "no-drop-root" - "Do not drop root priviliges" flag off diff --git a/src/lock.c b/src/lock.c index 42ad213..efce0bb 100644 --- a/src/lock.c +++ b/src/lock.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -35,6 +36,7 @@ int device_lock(const char *dev) { int fd; const char *path, *temp; char buf[100]; + char uidbuf[32]; if (stat(LOCK_PATH, &st) != 0 || !S_ISDIR(st.st_mode)) { daemon_log(LOG_ERR, "Failed to lock device, directory "LOCK_PATH" not existent."); @@ -45,6 +47,9 @@ int device_lock(const char *dev) { temp = tempfile(path); for (;;) { + mode_t u; + struct passwd* pw; + char *username; if ((fd = open(path, O_RDONLY)) < 0) { if (errno != ENOENT) { @@ -87,18 +92,33 @@ int device_lock(const char *dev) { } } } + + u = umask(0033); + fd = open(temp, O_WRONLY | O_CREAT | O_EXCL, 0666); + umask(u); - if ((fd = open(temp, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) { + if (fd < 0) { daemon_log(LOG_ERR, "Failed to create temporary lock file: %s", strerror(errno)); return -1; } + if ((pw = getpwuid(target_uid))) + username = pw->pw_name; + else + snprintf(username = uidbuf, sizeof(uidbuf), "%lu", (unsigned long) target_uid); + snprintf(buf, sizeof(buf), "%10lu %s %.20s\n", (unsigned long) getpid(), appname, username); if (loop_write(fd, buf, strlen(buf)) < 0) { daemon_log(LOG_ERR, "Failed to write to temporary lock file: %s", strerror(errno)); close(fd); return -1; } + + if (fchown(fd, target_uid, target_gid) < 0) { + daemon_log(LOG_ERR, "Failed to change owners of temporary lock file: %s", strerror(errno)); + close(fd); + return -1; + } close(fd); diff --git a/src/main.c b/src/main.c index 204fc69..53f8e80 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include #include @@ -15,9 +18,14 @@ oop_source* event_source = NULL; struct gengetopt_args_info args; -const char *appname = NULL, *username = NULL; +const char *appname = NULL; + +uid_t target_uid = 0; +gid_t target_gid = 0; #define DEFAULT_MSNTABLE "../conf/msntab" +#define IVAM_USER "ivam" +#define IVAM_GROUP "ivam" static void *oop_exit_cb(oop_source *source, int sig, void *user) { daemon_log(LOG_ERR, "Recieved signal %s", sig == SIGINT ? "SIGINT" : (sig == SIGTERM ? "SIGTERM" : "UNKNWON")); @@ -42,11 +50,66 @@ static void *oop_dump_cb(oop_source *source, int sig, void *user) { } +static int change_uid_gid(void) { + if (args.no_drop_root_flag) + return 0; + + if (initgroups(IVAM_USER, target_gid) != 0) { + daemon_log(LOG_ERR, "Failed to change group list: %s", strerror(errno)); + return -1; + } + + if (setgid(target_gid) != 0) { + daemon_log(LOG_ERR, "Failed to change GID: %s", strerror(errno)); + return -1; + } + + if (setuid(target_uid) != 0) { + daemon_log(LOG_ERR, "Failed to change UID: %s", strerror(errno)); + return -1; + } + + daemon_log(LOG_INFO, "Successfully dropped root privileges."); + + return 0; +} + +static int get_target_uid_gid(void) { + struct passwd *pw; + struct group * gr; + + if (args.no_drop_root_flag) { + target_uid = getuid(); + target_gid = getgid(); + return 0; + } + + if (!(pw = getpwnam(IVAM_USER))) { + daemon_log(LOG_ERR, "Failed to find user '%s'.", IVAM_USER); + return -1; + } + + if (!(gr = getgrnam(IVAM_GROUP))) { + daemon_log(LOG_ERR, "Failed to find group '%s'.", IVAM_GROUP); + return -1; + } + + target_uid = pw->pw_uid; + target_gid = gr->gr_gid; + + daemon_log(LOG_INFO, "Found user '%s' (UID %lu) and group '%s' (GID %lu).", IVAM_USER, (unsigned long) target_uid, IVAM_GROUP, (unsigned long) target_gid); + + return 0; +} + int main_loop(void) { int r = -1, retval_sent = 0; oop_source_sys *sys = NULL; daemon_log(LOG_INFO, "Starting up."); + + if (get_target_uid_gid() < 0) + goto finish; if (!(sys = oop_sys_new())) { daemon_log(LOG_ERR, "Failed to create system source."); @@ -55,6 +118,12 @@ int main_loop(void) { event_source = oop_sys_source(sys); assert(event_source); + + if (modem_manager_init(args.channels_arg) < 0) + goto finish; + + if (change_uid_gid() < 0) + goto finish; if (child_process_init() < 0) goto finish; @@ -62,9 +131,6 @@ int main_loop(void) { if (msntab_load(args.msntab_arg ? args.msntab_arg : DEFAULT_MSNTABLE) < 0) goto finish; - if (modem_manager_init(args.channels_arg) < 0) - goto finish; - event_source->on_signal(event_source, SIGINT, oop_exit_cb, NULL); event_source->on_signal(event_source, SIGTERM, oop_exit_cb, NULL); event_source->on_signal(event_source, SIGHUP, oop_reload_cb, NULL); @@ -177,7 +243,9 @@ int main(int argc, char*argv[]) { ret = main_loop() < 0 ? 1 : 0; - daemon_pid_file_remove(); + if (daemon_pid_file_remove() < 0) + daemon_log(LOG_WARNING, "Failed to remove PID file (%s).", strerror(errno)); + return ret; } diff --git a/src/main.h b/src/main.h index c23d87d..6ceb7f2 100644 --- a/src/main.h +++ b/src/main.h @@ -7,8 +7,11 @@ extern oop_source* event_source; -extern const char *appname, *username; +extern const char *appname; extern struct gengetopt_args_info args; +extern uid_t target_uid; +extern gid_t target_gid; + #endif -- cgit