summaryrefslogtreecommitdiffstats
path: root/usbmuxd
diff options
context:
space:
mode:
Diffstat (limited to 'usbmuxd')
-rw-r--r--usbmuxd/main.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/usbmuxd/main.c b/usbmuxd/main.c
index ec52ce0..f1aa1cc 100644
--- a/usbmuxd/main.c
+++ b/usbmuxd/main.c
@@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/fcntl.h>
#include <getopt.h>
#include <pwd.h>
+#include <grp.h>
#include "log.h"
#include "usb.h"
@@ -50,6 +51,7 @@ int should_exit;
static int verbose = 0;
static int foreground = 0;
static int drop_privileges = 0;
+static const char *drop_user = "usbmux";
static int opt_udev = 0;
static int opt_exit = 0;
static int exit_signal = 0;
@@ -236,8 +238,9 @@ static void usage()
printf("\t-h|--help Print this message.\n");
printf("\t-v|--verbose Be verbose (use twice or more to increase).\n");
printf("\t-f|--foreground Do not daemonize (implies one -v).\n");
- printf("\t-d|--drop-privileges Drop privileges after startup.\n");
- printf("\t-u|--udev Run in udev operation mode.\n");
+ printf("\t-u|--user[=USER] Change to this user after startup (needs usb privileges).\n");
+ printf("\t If USER is not specified, defaults to usbmux.\n");
+ printf("\t-d|--udev Run in udev operation mode.\n");
printf("\t-x|--exit Tell a running instance to exit.\n");
printf("\t-X|--force-exit Tell a running instance to exit, even if\n");
printf("\t there are still devices connected.\n");
@@ -250,8 +253,8 @@ static void parse_opts(int argc, char **argv)
{"help", 0, NULL, 'h'},
{"foreground", 0, NULL, 'f'},
{"verbose", 0, NULL, 'v'},
- {"drop-privileges", 0, NULL, 'd'},
- {"udev", 0, NULL, 'u'},
+ {"user", 2, NULL, 'u'},
+ {"udev", 0, NULL, 'd'},
{"exit", 0, NULL, 'x'},
{"force-exit", 0, NULL, 'X'},
{NULL, 0, NULL, 0}
@@ -259,7 +262,7 @@ static void parse_opts(int argc, char **argv)
int c;
while (1) {
- c = getopt_long(argc, argv, "hfvduxX", longopts, (int *) 0);
+ c = getopt_long(argc, argv, "hfvdu::xX", longopts, (int *) 0);
if (c == -1) {
break;
}
@@ -274,10 +277,12 @@ static void parse_opts(int argc, char **argv)
case 'v':
++verbose;
break;
- case 'd':
+ case 'u':
drop_privileges = 1;
+ if(optarg)
+ drop_user = optarg;
break;
- case 'u':
+ case 'd':
opt_udev = 1;
break;
case 'x':
@@ -403,23 +408,38 @@ int main(int argc, char *argv[])
// drop elevated privileges
if (drop_privileges && (getuid() == 0 || geteuid() == 0)) {
- struct passwd *pw = getpwnam("nobody");
- if (pw) {
- setuid(pw->pw_uid);
- } else {
- usbmuxd_log(LL_ERROR,
- "ERROR: Dropping privileges failed, check if user 'nobody' exists! Will now terminate.");
- log_disable_syslog();
- exit(EXIT_FAILURE);
+ struct passwd *pw = getpwnam(drop_user);
+ if (!pw) {
+ usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user);
+ res = 1;
+ goto terminate;
+ }
+
+ if ((res = initgroups(drop_user, pw->pw_gid)) < 0) {
+ usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set supplementary groups)");
+ goto terminate;
+ }
+ if ((res = setgid(pw->pw_gid)) < 0) {
+ usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set group ID to %d)", pw->pw_gid);
+ goto terminate;
+ }
+ if ((res = setuid(pw->pw_uid)) < 0) {
+ usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set user ID to %d)", pw->pw_uid);
+ goto terminate;
}
// security check
if (setuid(0) != -1) {
- usbmuxd_log(LL_ERROR, "ERROR: Failed to drop privileges properly!");
- log_disable_syslog();
- exit(EXIT_FAILURE);
+ usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
+ res = 1;
+ goto terminate;
+ }
+ if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {
+ usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
+ res = 1;
+ goto terminate;
}
- usbmuxd_log(LL_NOTICE, "Successfully dropped privileges");
+ usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user);
}
res = main_loop(listenfd);