dtms

diff src/main.c @ 4:db4bb4b5905a

security fixes: - refuse to run as root - drop privileges without an explicit -u argument when running setuid-root fixed argument parsing fixed mem leak added install and uninstall rules (Makefile)
author Eleni Maria Stea <eleni@mutantstargoat.com>
date Sun, 15 May 2016 00:15:45 +0300
parents bf6dda0e9daf
children
line diff
     1.1 --- a/src/main.c	Fri May 13 23:02:26 2016 +0300
     1.2 +++ b/src/main.c	Sun May 15 00:15:45 2016 +0300
     1.3 @@ -29,41 +29,58 @@
     1.4  
     1.5  static int parse_args(int argc, char **argv);
     1.6  static void print_help();
     1.7 -static void check_device(char *device_path);
     1.8 -static char* concatenate(char *mp_path, char *data_path);
     1.9 +static int check_device(char *device_path);
    1.10  
    1.11 -static int uid;
    1.12 -static char *path;
    1.13 +static int uid = -1;
    1.14 +static char *player_path;
    1.15  static char *dev_path;
    1.16  
    1.17 +#ifdef PREFIX
    1.18 +static const char* player_arg = PREFIX "/share/dtms/dtms.mp3";
    1.19 +#else
    1.20 +static const char* player_arg = "data/dtms.mp3";
    1.21 +#endif
    1.22 +
    1.23  int main(int argc, char **argv)
    1.24  {
    1.25      time_t last_touch_time = 0;
    1.26      int fd;
    1.27  
    1.28 -    if(parse_args(argc, argv))
    1.29 +    if(parse_args(argc, argv) == -1)
    1.30  	return 1;
    1.31  
    1.32 -    check_device(dev_path);
    1.33 +    if(getuid() == 0 && uid == -1) {
    1.34 +	fprintf(stderr, "It's a bad idea to run this program as root, either make it setuid-root, or use the -u option to specify an unprivileged user.\n");
    1.35 +	return 1;
    1.36 +    }
    1.37 +
    1.38 +    if(check_device(dev_path) == -1)
    1.39 +	return 1;
    1.40  
    1.41      if((fd = open(dev_path, O_RDONLY | O_NONBLOCK)) == -1) {
    1.42  	fprintf(stderr, "Failed to open device: %s, error: %s\n", dev_path, strerror(errno));
    1.43  	return 1;
    1.44      }
    1.45  
    1.46 +    if(uid == -1) {
    1.47 +	uid = getuid();
    1.48 +    }
    1.49 +
    1.50      if(seteuid(uid) == -1) {
    1.51  	perror("Set uid failed");
    1.52 -	uid = 0;
    1.53 +	return 1;
    1.54      }
    1.55  
    1.56      if(!uid) {
    1.57 -	const char *st = "/";
    1.58 -	if(strncmp(path, st, 1) != 0) {
    1.59 +	if(player_path[0] != '/') {
    1.60  	    fprintf(stderr, "If you run this program as root you should pass the absolute path to a valid mp3 player.\n");
    1.61  	    return 1;
    1.62  	}
    1.63      }
    1.64  
    1.65 +    char *cmd = malloc(strlen(player_path) + 1 + strlen(player_arg) + 1);
    1.66 +    sprintf(cmd, "%s %s", player_path, player_arg);
    1.67 +
    1.68      while(1) {
    1.69  	fd_set read_set;
    1.70  	FD_ZERO(&read_set);
    1.71 @@ -83,13 +100,16 @@
    1.72  	    time_t now = time(0);
    1.73  	    while(read(fd, buf, sizeof buf) > 0);
    1.74  	    if (now - last_touch_time > 2) {
    1.75 -		char *cmd = concatenate(path, "data/dtms.mp3");
    1.76  		system(cmd);
    1.77  		last_touch_time = now;
    1.78  	    }
    1.79  	}
    1.80      }
    1.81 +
    1.82 +    free(cmd);
    1.83      close(fd);
    1.84 +
    1.85 +    return 0;
    1.86  }
    1.87  
    1.88  static int parse_args(int argc, char **argv)
    1.89 @@ -99,39 +119,48 @@
    1.90  	    print_help();
    1.91  	    exit(0);
    1.92  	}
    1.93 -	if((strcmp(argv[i], "-p") == 0)) {
    1.94 -	    if(argv[i+1]) {
    1.95 -		path = argv[i+1];
    1.96 +
    1.97 +	else if((strcmp(argv[i], "-p") == 0)) {
    1.98 +	    if(argv[++i]) {
    1.99 +		player_path = argv[i];
   1.100  	    }
   1.101  	    else {
   1.102  		fprintf(stderr, "Invalid path. Please give the absolute path to an mp3 player.\n");
   1.103 -		exit(1);
   1.104 +		return -1;
   1.105  	    }
   1.106  	}
   1.107  
   1.108 -	if((strcmp(argv[i], "-u") == 0)) {
   1.109 -	    if(argv[i+1]) {
   1.110 -		struct passwd *passwd = getpwnam(argv[i+1]);
   1.111 +	else if((strcmp(argv[i], "-u") == 0)) {
   1.112 +	    if(argv[++i]) {
   1.113 +		struct passwd *passwd = getpwnam(argv[i]);
   1.114  		if(!passwd) {
   1.115 -		    fprintf(stderr, "Failed to get uid for: %s : %s.\n", argv[i+1], strerror(errno));
   1.116 -		    exit(1);
   1.117 +		    fprintf(stderr, "Failed to get uid for: %s : %s.\n", argv[i], strerror(errno));
   1.118 +		    return -1;
   1.119  		}
   1.120  		uid = passwd->pw_uid;
   1.121 +		if(uid == 0) {
   1.122 +		    fprintf(stderr, "You should pass an unprivileged username.\n");
   1.123 +		    return -1;
   1.124 +		}
   1.125  	    }
   1.126  	    else {
   1.127 -		fprintf(stderr, "Invalid username. Type -u `whoami`.\n");
   1.128 -		exit(1);
   1.129 +		fprintf(stderr, "Missing username.\n");
   1.130 +		return -1;
   1.131  	    }
   1.132  	}
   1.133 -	if((strcmp(argv[i], "-d") == 0)) {
   1.134 -	    if(argv[i+1]) {
   1.135 -		dev_path = argv[i+1];
   1.136 +	else if((strcmp(argv[i], "-d") == 0)) {
   1.137 +	    if(argv[++i]) {
   1.138 +		dev_path = argv[i];
   1.139  	    }
   1.140  	    else {
   1.141  		fprintf(stderr, "Invalid device file.\n");
   1.142 -		exit(1);
   1.143 +		return -1;
   1.144  	    }
   1.145  	}
   1.146 +	else {
   1.147 +	    fprintf(stderr, "Unknown argument: %s\n", argv[i]);
   1.148 +	    return -1;
   1.149 +	}
   1.150      }
   1.151      return 0;
   1.152  }
   1.153 @@ -149,25 +178,16 @@
   1.154      printf("./dtms -d /dev/usb/hiddev0 -u eleni -p /usr/bin/mpv\n");
   1.155  }
   1.156  
   1.157 -static void check_device(char *device_path)
   1.158 +static int check_device(char *device_path)
   1.159  {
   1.160      struct stat sb;
   1.161      if(stat(dev_path, &sb) == -1) {
   1.162  	perror("stat");
   1.163 -	exit(0);
   1.164 +	return -1;
   1.165      }
   1.166      if(((sb.st_mode & S_IFMT) != S_IFBLK) && ((sb.st_mode & S_IFMT) != S_IFCHR)) {
   1.167 -	fprintf(stderr, "Invalid device file.\n");
   1.168 -	exit(0);
   1.169 +	fprintf(stderr, "%s is not a device file.\n", device_path);
   1.170 +	return -1;
   1.171      }
   1.172 +    return 0;
   1.173  }
   1.174 -
   1.175 -static char *concatenate(char *mp_path, char *data_path)
   1.176 -{
   1.177 -    char *res = malloc(strlen(mp_path) + 1 + strlen(data_path) + 1);
   1.178 -    strcpy(res, mp_path);
   1.179 -    strcat(res, " ");
   1.180 -    strcat(res, data_path);
   1.181 -
   1.182 -    return res;
   1.183 -}