aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlendi <slendi@socopon.com>2023-05-10 16:34:28 +0300
committerSlendi <slendi@socopon.com>2023-05-10 16:35:26 +0300
commitd8d42221f1d1c570b33946dbc1d7ca4581ad944a (patch)
tree98b2826beece9ffced5a39345d0efe2ea3162ee8
parent3d3d237c2791899a4b19d72ebc286216442f9fd9 (diff)
Re-write program and add support for /etc/sus.
Signed-off-by: Slendi <slendi@socopon.com>
-rw-r--r--Makefile2
-rw-r--r--sus.c436
2 files changed, 177 insertions, 261 deletions
diff --git a/Makefile b/Makefile
index 69ddaa3..e986ce0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
build:
- cc -Wall -lcrypt -I. sus.c -o sus
+ tcc -lcrypt sus.c -o sus
all: build install
diff --git a/sus.c b/sus.c
index df3512c..35eff58 100644
--- a/sus.c
+++ b/sus.c
@@ -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';
-}