diff options
-rw-r--r-- | runtime/libgcry_common.c | 129 | ||||
-rw-r--r-- | tools/rscryutil.c | 9 |
2 files changed, 137 insertions, 1 deletions
diff --git a/runtime/libgcry_common.c b/runtime/libgcry_common.c index 49a0e669..63b5e5d5 100644 --- a/runtime/libgcry_common.c +++ b/runtime/libgcry_common.c @@ -75,3 +75,132 @@ gcryGetKeyFromFile(char *fn, char **key, unsigned *keylen) r = 0; done: return r; } + + +/* execute the child process (must be called in child context + * after fork). + */ + +static void +execKeyScript(char *cmd, int pipefd[]) +{ + char *newargv[] = { NULL }; + char *newenviron[] = { NULL }; + + dup2(pipefd[0], STDIN_FILENO); + dup2(pipefd[1], STDOUT_FILENO); + + /* finally exec child */ +fprintf(stderr, "pre execve: %s\n", cmd); + execve(cmd, newargv, newenviron); + /* switch to? + execlp((char*)program, (char*) program, (char*)arg, NULL); + */ + + /* we should never reach this point, but if we do, we terminate */ +done: return; +} + + +static int +openPipe(char *cmd, int *fd) +{ + int pipefd[2]; + pid_t cpid; + int r; + + if(pipe(pipefd) == -1) { + r = 1; goto done; + } + + cpid = fork(); + if(cpid == -1) { + r = 1; goto done; + } + + if(cpid == 0) { + /* we are the child */ + execKeyScript(cmd, pipefd); + exit(1); + } + + close(pipefd[1]); + *fd = pipefd[0]; + r = 0; +done: return r; +} + + +/* Read a character from the program's output. */ +// TODO: highly unoptimized version, should be used in buffered +// mode +static int +readProgChar(int fd, char *c) +{ + int r; + if(read(fd, c, 1) != 1) { + r = 1; goto done; + } + r = 0; +done: return r; +} + +/* Read a line from the script. Line is terminated by LF, which + * is NOT put into the buffer. + * buf must be 64KiB + */ +static int +readProgLine(int fd, char *buf) +{ + char c; + int r; + unsigned i; + + for(i = 0 ; i < 64*1024 ; ++i) { + if((r = readProgChar(fd, &c)) != 0) goto done; + if(c == '\n') + break; + buf[i] = c; + }; + if(i >= 64*1024) { + r = 1; goto done; + } + buf[i] = '\0'; + r = 0; +done: return r; +} +static int +readProgKey(int fd, char *buf, unsigned keylen) +{ + char c; + int r; + unsigned i; + + for(i = 0 ; i < keylen ; ++i) { + if((r = readProgChar(fd, &c)) != 0) goto done; + buf[i] = c; + }; + r = 0; +done: return r; +} + +int +gcryGetKeyFromProg(char *cmd, char **key, unsigned *keylen) +{ + int r; + int fd; + char rcvBuf[64*1024]; + + if((r = openPipe(cmd, &fd)) != 0) goto done; + if((r = readProgLine(fd, rcvBuf)) != 0) goto done; + if(strcmp(rcvBuf, "RSYSLOG-KEY-PROVIDER:0")) { + r = 2; goto done; + } + if((r = readProgLine(fd, rcvBuf)) != 0) goto done; + *keylen = atoi(rcvBuf); + if((*key = malloc(*keylen)) == NULL) { + r = -1; goto done; + } + if((r = readProgKey(fd, *key, *keylen)) != 0) goto done; +done: return r; +} diff --git a/tools/rscryutil.c b/tools/rscryutil.c index be14cde9..2591b2cc 100644 --- a/tools/rscryutil.c +++ b/tools/rscryutil.c @@ -44,6 +44,7 @@ static gcry_cipher_hd_t gcry_chd; static size_t blkLength; static char *keyfile = NULL; +static char *keyprog = NULL; static int randomKeyLen = -1; static char *cry_key = NULL; static unsigned cry_keylen = 0; @@ -387,6 +388,8 @@ setKey() getRandomKey(); else if(keyfile != NULL) getKeyFromFile(keyfile); + else if(keyprog != NULL) + gcryGetKeyFromProg(keyprog, &cry_key, &cry_keylen); if(cry_key == NULL) { fprintf(stderr, "ERROR: key must be set via some method\n"); exit(1); @@ -403,6 +406,7 @@ static struct option long_options[] = {"key", required_argument, NULL, 'K'}, {"generate-random-key", required_argument, NULL, 'r'}, {"keyfile", required_argument, NULL, 'k'}, + {"key-program", required_argument, NULL, 'p'}, {"algo", required_argument, NULL, 'a'}, {"mode", required_argument, NULL, 'm'}, {NULL, 0, NULL, 0} @@ -417,7 +421,7 @@ main(int argc, char *argv[]) char *newKeyFile = NULL; while(1) { - opt = getopt_long(argc, argv, "a:dfk:K:m:r:vVW:", long_options, NULL); + opt = getopt_long(argc, argv, "a:dfk:K:m:p:r:vVW:", long_options, NULL); if(opt == -1) break; switch(opt) { @@ -431,6 +435,9 @@ main(int argc, char *argv[]) case 'k': keyfile = optarg; break; + case 'p': + keyprog = optarg; + break; case 'f': optionForce = 1; break; |