Remove execution functionality for possible security issues
This commit is contained in:
parent
2d0a0c2577
commit
93e7139290
142
lewdfingerd.c
142
lewdfingerd.c
|
@ -146,139 +146,7 @@ ssize_t writeall_str(int fd, const char *s) {
|
||||||
return writeall(fd, s, strlen(s));
|
return writeall(fd, s, strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute_finger_response(int sock, const char *finger_response_file) {
|
bool handle_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, ¤t_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) {
|
|
||||||
FILE *f = fopen(finger_response_file, "r");
|
FILE *f = fopen(finger_response_file, "r");
|
||||||
if(f == NULL) {
|
if(f == NULL) {
|
||||||
log_perror("fopen");
|
log_perror("fopen");
|
||||||
|
@ -314,14 +182,6 @@ bool read_finger_response(int sock, const char *finger_response_file) {
|
||||||
return true;
|
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) {
|
void handle_userlist(int sock, bool force_multiline) {
|
||||||
// Go over users' home dirs and see if .finger-response is present
|
// Go over users' home dirs and see if .finger-response is present
|
||||||
bool first_line = true;
|
bool first_line = true;
|
||||||
|
|
Loading…
Reference in New Issue