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 -}