Remove execution functionality for possible security issues

This commit is contained in:
Juhani Krekelä 2018-09-08 16:16:33 +00:00
parent 2d0a0c2577
commit 93e7139290
1 changed files with 1 additions and 141 deletions

View File

@ -146,139 +146,7 @@ ssize_t writeall_str(int fd, const char *s) {
return writeall(fd, s, strlen(s));
}
bool execute_finger_response(int sock, const char *finger_response_file) {
int pipes[2];
if(pipe(pipes) != 0) {
log_perror("pipe");
return false;
}
pid_t child = fork();
if(child < 0) {
log_perror("fork");
return false;
}
if(child == 0) {
// Child
// Close unneeded fds
for(size_t i = 0; i < num_listens; i++) {
close(listens[num_listens].fd);
}
close(sock);
close(pipes[0]);
// Set up stdout
if(dup2(pipes[1], STDOUT_FILENO) < 0) {
log_perror("dup2");
_exit(1);
}
// execv's types require this cast
char *argv[] = {(char*) finger_response_file, NULL};
execv(finger_response_file, argv);
log_perror("execv");
_exit(1);
} else {
// Parent
// Close unneeded fds
close(pipes[1]);
struct timespec start_time;
// Doesn't seem this could fail in our configuration
clock_gettime(CLOCK_MONOTONIC, &start_time);
char iobuf[1024];
struct pollfd pipe_poll = {.fd = pipes[0], .events = POLLIN};
for(;;) {
// Check the child is still running
int status;
waitpid(child, &status, WNOHANG);
if(WIFEXITED(status) || WIFSIGNALED(status)) {
// Child quit
if(WIFSIGNALED(status)) {
log_error("Child died of signal %i\n", WTERMSIG(status));
} else if(WIFEXITED(status) && WEXITSTATUS(status) != 0) {
log_error("Child exited with nonzero return code %i\n", WEXITSTATUS(status));
}
break;
}
struct timespec current_time;
// See previous usage of this
clock_gettime(CLOCK_MONOTONIC, &current_time);
time_t secs_passed = current_time.tv_sec - start_time.tv_sec;
long ns_passed = current_time.tv_nsec - start_time.tv_nsec;
int ms_passed = secs_passed * 1000 + ns_passed / 1000;
// Timeout of 5s
int ms_remaining = 5000 - ms_passed;
if(ms_remaining <= 0) {
log_error("Child ran too long\n");
if(kill(child, SIGKILL)) {
log_perror("kill");
}
// Wait to get rid of the zombie
waitpid(child, NULL, 0);
if(writeall_str(sock, "Timeout\r\n") < 0) {
log_perror("writeall_str");
close(pipes[0]);
return false;
}
break;
}
int amount_ready = poll(&pipe_poll, 1, ms_remaining);
for(int i = 0; i < amount_ready; i++) {
if(pipe_poll.revents & POLLIN) {
ssize_t amount_read = read(pipes[0], iobuf, sizeof(iobuf));
if(amount_read < 0) {
log_perror("read");
break;
}
char *newline_location = memchr(iobuf, '\n', amount_read);
if(newline_location == NULL) {
// No newline, write entire buffer
if(writeall(sock, iobuf, amount_read) < 0) {
log_perror("writeall");
break;
}
} else {
// Newline found. Write stuff before it and \r\n
if(writeall(sock, iobuf, newline_location - iobuf) < 0 || writeall_str(sock, "\r\n") < 0) {
log_perror("writeall / writeall_str");
break;
}
// Write the part after it
char *part_after_nl = newline_location + 1;
size_t part_after_nl_length = amount_read - (part_after_nl - iobuf);
if(writeall(sock, part_after_nl, part_after_nl_length) < 0) {
log_perror("writeall");
break;
}
}
}
}
}
close(pipes[0]);
}
return true;
}
bool read_finger_response(int sock, const char *finger_response_file) {
bool handle_finger_response(int sock, const char *finger_response_file) {
FILE *f = fopen(finger_response_file, "r");
if(f == NULL) {
log_perror("fopen");
@ -314,14 +182,6 @@ bool read_finger_response(int sock, const char *finger_response_file) {
return true;
}
bool handle_finger_response(int sock, const char *finger_response_file) {
if(access(finger_response_file, X_OK) == 0) {
return execute_finger_response(sock, finger_response_file);
} else {
return read_finger_response(sock, finger_response_file);
}
}
void handle_userlist(int sock, bool force_multiline) {
// Go over users' home dirs and see if .finger-response is present
bool first_line = true;