aboutsummaryrefslogtreecommitdiffstats
path: root/key2root.c
diff options
context:
space:
mode:
Diffstat (limited to 'key2root.c')
-rw-r--r--key2root.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/key2root.c b/key2root.c
index 5a152ab..3ad97de 100644
--- a/key2root.c
+++ b/key2root.c
@@ -1,5 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
@@ -85,6 +87,61 @@ usage(void)
}
+static int
+forward(char *data, size_t len)
+{
+ int fds[2];
+ size_t off;
+ ssize_t r;
+
+ /* We are using sockets because they cannot be hijacked via /proc/<pid>/fd/ */
+
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds)) {
+ fprintf(stderr, "%s: socketpair PF_LOCAL SOCK_STREAM 0: %s\n", argv0, strerror(errno));
+ return -1;
+ }
+ if (shutdown(fds[0], SHUT_WR)) {
+ fprintf(stderr, "%s: shutdown <socket> SHUT_WR: %s\n", argv0, strerror(errno));
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+ if (shutdown(fds[1], SHUT_RD)) {
+ fprintf(stderr, "%s: shutdown <socket> SHUT_RD: %s\n", argv0, strerror(errno));
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+
+ switch (fork()) {
+ case -1:
+ fprintf(stderr, "%s: fork: %s\n", argv0, strerror(errno));
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ case 0:
+ close(fds[0]);
+ break;
+ default:
+ close(fds[1]);
+ return fds[0];
+ }
+
+ for (off = 0; off < len; off += (size_t)r) {
+ r = write(fds[1], &data[off], len - off);
+ if (r < 0) {
+ fprintf(stderr, "%s: write <socket>: %s\n", argv0, strerror(errno));
+ close(fds[1]);
+ _exit(1);
+ }
+ explicit_bzero(&data[off], (size_t)r);
+ }
+
+ close(fds[1]);
+ _exit(0);
+}
+
+
static char **
set_environ(void)
{
@@ -172,6 +229,7 @@ main(int argc, char *argv[])
size_t key_len = 0;
size_t key_size = 0;
ssize_t r;
+ int fd;
ARGBEGIN {
case 'e':
@@ -219,7 +277,12 @@ main(int argc, char *argv[])
}
/* TODO authenticate */
- /* TODO forward */
+
+ fd = forward(key, key_len);
+ if (fd < 0) {
+ explicit_bzero(key, key_len);
+ exit(EXIT_ERROR);
+ }
explicit_bzero(key, key_len);
@@ -235,6 +298,14 @@ main(int argc, char *argv[])
exit(EXIT_ERROR);
}
+ if (fd != STDIN_FILENO) {
+ if (dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
+ fprintf(stderr, "%s: dup2 <socket> <stdin>: %s\n", argv0, strerror(errno));
+ exit(EXIT_ERROR);
+ }
+ close(fd);
+ }
+
if (new_environ)
environ = new_environ;
execvp(argv[0], argv);