diff options
author | Slendi <slendi@socopon.com> | 2023-05-10 16:34:28 +0300 |
---|---|---|
committer | Slendi <slendi@socopon.com> | 2023-05-10 16:35:26 +0300 |
commit | d8d42221f1d1c570b33946dbc1d7ca4581ad944a (patch) | |
tree | 98b2826beece9ffced5a39345d0efe2ea3162ee8 | |
parent | 3d3d237c2791899a4b19d72ebc286216442f9fd9 (diff) |
Re-write program and add support for /etc/sus.
Signed-off-by: Slendi <slendi@socopon.com>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | sus.c | 436 |
2 files changed, 177 insertions, 261 deletions
@@ -1,5 +1,5 @@ build: - cc -Wall -lcrypt -I. sus.c -o sus + tcc -lcrypt sus.c -o sus all: build install @@ -1,286 +1,202 @@ #define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <termios.h> - -#include <signal.h> - -#include <string.h> - +#include <crypt.h> #include <fcntl.h> #include <grp.h> #include <pwd.h> #include <shadow.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> #include <sys/types.h> +#include <termios.h> +#include <unistd.h> -#include <errno.h> - -#define MAX_PASSWORD 3 - -void get_password(char* password); - -void cats(char** str, const char* str2); - -int CheckIfInGroup(const char* string); - -int GetUID(const char* username, uid_t* uid); -void PrintHelp(); -void CreatePasswordMessage(); - -int CheckPassword(char* password); -int AskPassword(); - -uid_t uid = 0; - -int command_start = 1; - -char* command_name; - -struct termios old_terminal; - -void getln(int, char*, size_t); - -struct passwd* pw; - -void intHandler(int dummy) -{ - tcsetattr(STDIN_FILENO, TCSANOW, &old_terminal); - puts("Cancelled."); - exit(0); -} - -int main(int argc, char** argv, char** envp) -{ - uid = getuid(); - pw = getpwuid(uid); - - if (CheckIfInGroup("wheel") != 1) { - puts("ERROR: Not in the wheel group."); - return 0; - } - - struct sigaction savealrm, saveint, savehup, savequit, saveterm; - struct sigaction savetstp, savettin, savettou, savepipe; - - struct sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = intHandler; - - sigaction(SIGALRM, &sa, &savealrm); - sigaction(SIGHUP, &sa, &savehup); - sigaction(SIGINT, &sa, &saveint); - sigaction(SIGPIPE, &sa, &savepipe); - sigaction(SIGQUIT, &sa, &savequit); - sigaction(SIGTERM, &sa, &saveterm); - sigaction(SIGTSTP, &sa, &savetstp); - sigaction(SIGTTIN, &sa, &savettin); - sigaction(SIGTTOU, &sa, &savettou); - - command_name = malloc((1 + strlen(argv[0])) * sizeof(char)); - strcpy(command_name, argv[0]); - - if (argc < 2) { - PrintHelp(); - return 0; - } - - if (AskPassword() != 1) { - puts("ERROR: Too many attempts."); - return 1; - } - - char username[32]; - username[0] = '\0'; - - if (argv[1][0] == '-') { - // - specified. Check if user is in next argument or - // in the same argument as the switch. - if (strlen(argv[1]) > 1) { - if (strlen(argv[1]) > 34) { - puts("ERROR: Username limit reached!"); - return 1; - } - strcpy(username, argv[1]); - command_start = 2; - } else { - if (strlen(argv[2]) > 33) { - puts("ERROR: Username limit reached!"); - return 1; - } - strcpy(username, argv[2]); - command_start = 3; - } - - if (username[0] == '-') - memmove(username, username + 1, strlen(username)); - } - - if (username[0] == '\0') - uid = 0; - else if (GetUID(username, &uid) == -1) { - printf("ERROR: Could not find username: %s", username); - return 1; - } - - sigaction(SIGALRM, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - sigaction(SIGQUIT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGTSTP, &sa, NULL); - sigaction(SIGTTIN, &sa, NULL); - sigaction(SIGTTOU, &sa, NULL); - - - argv += command_start; - setuid(uid); - execvpe(argv[0], argv, envp); - - return 0; -} +#define MAX_IDS 100 +long long ids[MAX_IDS] = { 0 }; +size_t ids_len = 0; -int GetUID(const char* username, uid_t* uid) +read_ids() { - pw = getpwnam(username); - if (pw != NULL) { - *uid = pw->pw_uid; - return 1; - } - - return -1; + FILE *f = fopen("/etc/sus", "r"); + if (!f) return 0; + while (!feof(f)) + fscanf(f, "%lld", &ids[ids_len++]); + if (ids_len == 0) return 0; + return 1; } -int CheckIfInGroup(const char* string) +check_password(pass_buf) +char *pass_buf; { - int groups = getgroups(0, NULL); - - gid_t list[groups]; - - int ngroups = getgroups(groups, list); - - if (ngroups < 0) - return -1; - - for (int i = 0; i < groups; i++) { - struct group* grp; - grp = getgrgid(list[i]); - if (grp == NULL) - return -1; - if (strcmp(grp->gr_name, "wheel") == 0) - return 1; - } - - return -1; + struct spwd* shadow_entry; + struct passwd* pa; + char *p, *correct, *supplied, *salt; + pa = getpwuid(getuid()); + + shadow_entry = getspnam(pa->pw_name); + if (shadow_entry == NULL) + return 2; + + supplied = crypt(pass_buf, shadow_entry->sp_pwdp); + if (supplied == NULL) + return 6; + return !!strcmp(supplied, shadow_entry->sp_pwdp); } -void PrintHelp() { printf("Usage: %s [- user] command\n", command_name); } - -int AskPassword() +int getting_pass = 0; +ask_password() { - for (int i = 0; i < MAX_PASSWORD; i++) { - char password[BUFSIZ]; - get_password(password); - - int res = CheckPassword(password); - if (res == 0) - return 1; - else - CreatePasswordMessage(); - sleep(1); - } - - return 0; + getting_pass = 1; + int i = 3; + while (i--) { + char *pass_buf = getpass("Password: "); + if (!pass_buf || *pass_buf == '\0') { + i++; + continue; + } + int res = check_password(pass_buf); + memset(pass_buf, 0, strlen(pass_buf)-1); + if (res == 0) { + getting_pass = 0; + return 1; + } else + fputs("Wrong password!\n", stderr); + sleep(1); + } + getting_pass = 0; + return 0; } -int CheckPassword(char* password) +int_handler() { - struct spwd* shadow_entry; - struct passwd* pa = getpwuid(getuid()); - char *p, *correct, *supplied, *salt; - shadow_entry = getspnam(pa->pw_name); - if (shadow_entry == NULL) - return 2; - correct = shadow_entry->sp_pwdp; - salt = strdup(correct); - if (salt == NULL) - return 3; - p = strchr(salt + 1, '$'); - if (p == NULL) - return 4; - p = strchr(p + 1, '$'); - if (p == NULL) - return 5; - p[1] = 0; - - supplied = crypt(password, salt); - if (supplied == NULL) - return 6; - return !!strcmp(supplied, correct); + if (getting_pass) + return; + fputs("Cancelled.\n", stderr); + exit(0); } -void CreatePasswordMessage() { puts("Incorrect password! Try again."); } - -void cats(char** str, const char* str2) +is_valid() { - char* tmp = NULL; - - // Reset *str - if (*str != NULL && str2 == NULL) { - free(*str); - *str = NULL; - return; - } - - // Initial copy - if (*str == NULL) { - *str = calloc(strlen(str2) + 1, sizeof(char)); - memcpy(*str, str2, strlen(str2)); - } else { // Append - tmp = calloc(strlen(*str) + 1, sizeof(char)); - memcpy(tmp, *str, strlen(*str)); - *str = calloc(strlen(*str) + strlen(str2) + 1, sizeof(char)); - memcpy(*str, tmp, strlen(tmp)); - memcpy(*str + strlen(*str), str2, strlen(str2)); - free(tmp); - } + int i, j, groups = getgroups(0, NULL); + gid_t list[groups]; + int ngroups = getgroups(groups, list); + + if (ngroups < 0) + return -1; + + for (i = 0; i < groups; i++) { + struct group* grp; + grp = getgrgid(list[i]); + if (grp == NULL) + return 0; + + for (j = 0; j < ids_len; j++) + if (grp->gr_gid == ids[j]) + return 1; + } + return 0; } -void get_password(char* password) +main(argc, argv, envp, cstart, uid) +char **argv; char **envp; +uid_t uid; { - static struct termios new_terminal; - - int ttyfd = open("/dev/tty", O_RDWR); - - tcgetattr(ttyfd, &old_terminal); - - new_terminal = old_terminal; - new_terminal.c_lflag &= ~(ECHO); - - tcsetattr(ttyfd, TCSAFLUSH, &new_terminal); - - write(ttyfd, "Password: ", 11); - - getln(ttyfd, password, sizeof(password)); - - tcsetattr(ttyfd, TCSAFLUSH, &old_terminal); - - close(ttyfd); - - putchar('\n'); + cstart = 1; + uid = 0; + struct sigaction savealrm, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou, savepipe; + + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = int_handler; + + sigaction(SIGALRM, &sa, &savealrm); + sigaction(SIGHUP, &sa, &savehup); + sigaction(SIGINT, &sa, &saveint); + sigaction(SIGPIPE, &sa, &savepipe); + sigaction(SIGQUIT, &sa, &savequit); + sigaction(SIGTERM, &sa, &saveterm); + sigaction(SIGTSTP, &sa, &savetstp); + sigaction(SIGTTIN, &sa, &savettin); + sigaction(SIGTTOU, &sa, &savettou); + + if (argc < 2) { + fprintf(stderr, "Usage: %s [- user] -- command\n", argv[0]); + return 0; + } + + if (strcmp(*(argv + cstart), "-") == 0) { + if (argc < 4) { + fprintf(stderr, "No command or user specified.\n"); + return -1; + } + + struct passwd *p = getpwnam(argv[2]); + if (!p) { + fprintf(stderr, "Invalid user specified.\n"); + return -1; + } + + uid = p->pw_uid; + char **envp2 = envp; + while (*envp2 != NULL) { + if (strncmp(*envp2, "USER=", 5) == 0) { + char *new_user_string = malloc(strlen(p->pw_name) + 6); + sprintf(new_user_string, "USER=%s", p->pw_name); + strcpy(*envp2, new_user_string); + free(new_user_string); + break; + } + envp2++; + } + cstart += 2; + } + + if (strcmp(*(argv + cstart), "--") == 0) { + struct passwd *p = getpwuid(uid); + if (!p) { + fprintf(stderr, "UID not found, this should not happen.\n"); + return -1; + } + + chdir(p->pw_dir); + cstart++; + if (argc - cstart < 1) { + fprintf(stderr, "Command not found.\n"); + return -1; + } + } + + if (!read_ids()) { + fputs("Failed to read ids file /etc/sus.\n", stderr); + return -1; + } + + if (!is_valid()) { + fputs("Not in the susers file, this incident won't be reported.\n", stderr); + return -1; + } + + if (ask_password() != 1) { + fputs("Too many attempts.\n", stderr); + return -1; + } + + sigaction(SIGALRM, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGTSTP, &sa, NULL); + sigaction(SIGTTIN, &sa, NULL); + sigaction(SIGTTOU, &sa, NULL); + + argv += cstart; + setuid(uid); + execvpe(argv[0], argv, envp); + + return 0; } -void getln(int fd, char* buf, size_t bufsiz) -{ - ssize_t nr = -1; - char ch; - while ((nr = read(fd, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { - if (buf < buf + bufsiz - 1) { - *buf++ = ch; - } - } - *buf = '\0'; -} |