summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/libgcry_common.c129
-rw-r--r--tools/rscryutil.c9
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;