boru/source/utils.c
2024-09-29 11:19:31 +03:00

204 lines
4.8 KiB
C

#include "common.h"
void genconf(const char *path) {
FILE *fp = fopen(path, "w");
if (!fp)
errx(1, "Could not create %s", path);
fprintf(fp, "group=wheel\n");
fprintf(fp, "wrong_pw_sleep=1000\n");
fprintf(fp, "session_ttl=5\n");
fprintf(fp, "nopass=1\n");
if (fclose(fp) != 0)
errx(1, "Error closing the file %s", path);
}
void getconf(FILE *fp, const char *entry, char *result, size_t len_result) {
char *token;
char line[256];
fseek(fp, 0, SEEK_SET);
while (fgets(line, sizeof(line), fp) != NULL) {
if (strncmp(entry, line, strlen(entry)) == 0) {
token = strchr(line, '=');
if (token) {
strncpy(result, token + 1, len_result - 1);
result[len_result - 1] = '\0';
result[strcspn(result, "\n")] = '\0';
return;
}
}
}
errx(1, "Could not get '%s' entry in config", entry);
}
void runprog(char **program_argv) {
if (setuid(0) < 0 || setgid(0) < 0)
err(1, "Could not setuid/setgid");
if (putenv("HOME=/root") != 0)
err(1, "Could not set HOME");
execvp(program_argv[0], program_argv);
err(1, "execvp");
}
int ensuredir(void) {
struct stat st;
if (stat("/run/boru", &st) == -1) {
if (mkdir("/run/boru", 0700) == -1)
err(1, "Could not create /run/boru");
if (stat("/run/boru", &st) == -1)
err(1, "Could not open /run/boru");
}
if (!S_ISDIR(st.st_mode) || st.st_uid != 0)
err(1, "Could not fstat /run/boru");
return 0;
}
int getpstartts(int pid, unsigned long long *startts) {
char path[256], fc[4096];
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
int fd = open(path, O_RDONLY);
if (fd < 0)
err(1, "Could not open %s", path);
int bytes_read = read(fd, fc, sizeof(fc) - 1);
close(fd);
if (bytes_read < 0)
err(1, "Could not read %s", path);
fc[bytes_read] = '\0';
char *ptr = strrchr(fc, ')');
if (!ptr)
return -1;
ptr++;
int field = 0;
char *token = strtok(ptr, " ");
while (token) {
if (++field == 21) {
unsigned long long temp_ts = strtoull(token, NULL, 10);
if (temp_ts == 0 || temp_ts == ULLONG_MAX)
return -1;
*startts = temp_ts;
return 0;
}
token = strtok(NULL, " ");
}
return -1;
}
void setsession(int pid, unsigned int ts_ttl, int ruid) {
char ts_str[32], path[1024];
unsigned long long startts;
if (ts_ttl == 0)
return;
if (ensuredir() < 0 || getpstartts(pid, &startts) < 0)
return;
snprintf(path, sizeof(path), "/run/boru/%d-%d-%llu", ruid, pid, startts);
int fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0700);
if (fd < 0) {
if (errno == EEXIST)
return;
err(1, "Could not open %s", path);
}
snprintf(ts_str, sizeof(ts_str), "%llu", (unsigned long long)time(NULL));
if (write(fd, ts_str, strlen(ts_str)) < 0) {
close(fd);
err(1, "Could not write to %s", path);
}
close(fd);
}
int getsession(int pid, unsigned int ts_ttl, int ruid) {
char ts_str[32], path[1024];
unsigned long long startts;
if (ts_ttl == 0)
return -1;
if (ensuredir() < 0 || getpstartts(pid, &startts) < 0)
return -1;
snprintf(path, sizeof(path), "/run/boru/%d-%d-%llu", ruid, pid, startts);
int fd = open(path, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return -1;
err(1, "Could not open %s", path);
}
ssize_t bytes_read = read(fd, ts_str, sizeof(ts_str) - 1);
if (bytes_read < 0) {
close(fd);
err(1, "Could not read %s", path);
}
ts_str[bytes_read] = '\0';
close(fd);
unsigned long long file_ts = strtoull(ts_str, NULL, 10);
unsigned long long current_ts = time(NULL);
if (current_ts - file_ts > ts_ttl) {
unlink(path);
return -1;
}
return 0;
}
char *readpassphrase(const char *prompt, char *buf, size_t bufsz) {
int ttyfd;
struct termios oldterm, newterm;
ttyfd = open("/dev/tty", O_RDWR);
if (ttyfd < 0)
return NULL;
if (tcgetattr(ttyfd, &oldterm) < 0) {
close(ttyfd);
return NULL;
}
newterm = oldterm;
newterm.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if (tcsetattr(ttyfd, TCSAFLUSH, &newterm) < 0) {
close(ttyfd);
return NULL;
}
if (write(ttyfd, prompt, strlen(prompt)) < 0) {
close(ttyfd);
return NULL;
}
ssize_t n = read(ttyfd, buf, bufsz);
if (n < 0) {
close(ttyfd);
return NULL;
}
buf[n > 0 ? n - 1 : 0] = '\0';
tcsetattr(ttyfd, TCSANOW, &oldterm);
close(ttyfd);
return buf;
}