204 lines
4.8 KiB
C
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;
|
|
} |