#define _BSD_SOURCE #include #include #include #include #include #include #include #include int main(int argc, char **argv) { if(argc < 3) { fprintf(stderr, "Usage: %s username[:group] command [arguments]\n", argv[0]); return 1; } char *username_group = strdup(argv[1]); if(username_group == NULL) { perror("strdup"); return 1; } char *colon_position, *username, *group; if((colon_position = strchr(username_group, ':')) != NULL) { *colon_position = 0; username = username_group; group = colon_position + 1; } else { username = username_group; group = NULL; } errno = 0; struct passwd *passwd_entry = getpwnam(username); if(passwd_entry == NULL) { perror("getpwnam"); return 1; } uid_t ruid = passwd_entry->pw_uid; uid_t rgid; if(group != NULL) { errno = 0; struct group *group_entry = getgrnam(group); if(group_entry == NULL) { perror("getgrnam"); return 1; } rgid = group_entry->gr_gid; } else { rgid = passwd_entry->pw_gid; } free(username_group); if(setreuid(ruid, -1) != 0) { perror("setreuid"); return 1; } if(setregid(rgid, -1) != 0) { perror("setregid"); return 1; } char **daemon_argv = &argv[2]; const char *daemon_command = daemon_argv[0]; execvp(daemon_command, daemon_argv); perror("execvp"); return 1; }