[Rpm-maint] [PATCH v9 13/13] Add support for prompting the user for the password using pinentry
Fionnuala Gunter
fionnuala.gunter at gmail.com
Tue Jul 21 17:00:47 UTC 2015
From: Mimi Zohar <zohar at us.ibm.com>
Call pinentry to prompt for the password. On failure revert back
to prompting the user directly.
---
lib/rpmsignfiles.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/rpmsignfiles.h | 1 +
rpmsign.c | 4 +-
3 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
index 4336f8c..cd93fc6 100644
--- a/lib/rpmsignfiles.c
+++ b/lib/rpmsignfiles.c
@@ -7,7 +7,10 @@
#include "system.h"
#include "imaevm.h"
+#include <unistd.h>
#include <termios.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <rpm/rpmlog.h> /* rpmlog */
#include <rpm/rpmstring.h> /* rnibble */
@@ -32,6 +35,23 @@ static const char *hash_algo_name[] = {
[PGPHASHALGO_SHA224] = "sha224",
};
+#define debug 0
+
+#define PARENT_WRITE_PIPE 0
+#define PARENT_READ_PIPE 1
+
+#define NUM_PIPES 2
+int pipes[NUM_PIPES][2];
+
+#define READ_FD 0
+#define WRITE_FD 1
+
+#define PARENT_READ_FD ( pipes[PARENT_READ_PIPE][READ_FD] )
+#define PARENT_WRITE_FD ( pipes[PARENT_WRITE_PIPE][WRITE_FD] )
+
+#define CHILD_READ_FD ( pipes[PARENT_WRITE_PIPE][READ_FD] )
+#define CHILD_WRITE_FD ( pipes[PARENT_READ_PIPE][WRITE_FD] )
+
char *get_fskpass(void)
{
struct termios flags, tmp_flags;
@@ -65,6 +85,116 @@ char *get_fskpass(void)
return pwd;
}
+static void send(int pipe, char *command)
+{
+ if (debug)
+ printf("send: %s", command);
+ write(PARENT_WRITE_FD, command, strlen(command));
+}
+
+static void recv(int pipe)
+{
+ char buffer[100];
+ int count;
+
+ do {
+ count = read(PARENT_READ_FD, buffer, sizeof buffer - 1);
+ if (count <= 0)
+ break;
+ if (strncmp(buffer, "OK", 2) != 0) {
+ if (debug)
+ printf("count %d: %s\n", count, buffer);
+ break;
+ } else if (debug)
+ printf("count %d: %s\n", count, buffer);
+ } while (0);
+}
+
+static char *recv_password(int pipe)
+{
+ long count;
+ size_t buflen = 100;
+ char *buffer = malloc(buflen);
+
+ if (!buffer)
+ return NULL;
+
+ do {
+ memset(buffer, '\0', buflen);
+ count = read(PARENT_READ_FD, buffer, buflen);
+
+ if (count > 0 && buffer[0] == 'D') {
+ char *password;
+ int len = strlen(buffer);
+
+ if (buffer[len - 1] == '\n')
+ buffer[len - 1] = '\0';
+ password = strdup(buffer + 2);
+ memset(buffer, '\0', buflen);
+ return password;
+ } else if (count > 0 && strncmp(buffer, "ERR", 3) == 0)
+ return NULL;
+ else if (count > 0 && strncmp(buffer, "OK", 2) == 0)
+ return NULL;
+ } while (0);
+
+ return NULL;
+}
+
+char *get_pinentry_fskpass()
+{
+ char *command, *password = NULL;
+ pid_t child;
+
+ if (pipe(pipes[PARENT_READ_PIPE]) || pipe(pipes[PARENT_WRITE_PIPE])) {
+ fprintf(stderr, "Pipe failed\n");
+ return NULL;
+ }
+
+ child = fork();
+ if (child == (pid_t) 0) {
+ dup2(CHILD_READ_FD, STDIN_FILENO);
+ dup2(CHILD_WRITE_FD, STDOUT_FILENO);
+
+ close(CHILD_READ_FD);
+ close(CHILD_WRITE_FD);
+ close(PARENT_READ_FD);
+ close(PARENT_WRITE_FD);
+
+ execlp("pinentry", "pinentry", NULL);
+ } else if (child < (pid_t) 0) {
+ fprintf(stderr, "Fork failed\n");
+ return NULL;
+ } else {
+ /* close fds not required by parent */
+ close(CHILD_READ_FD);
+ close(CHILD_WRITE_FD);
+
+ command = "SETDESC PEM password\n";
+ send(PARENT_WRITE_FD, command);
+ recv(PARENT_READ_FD);
+
+ command = "OPTION display PEM\n";
+ send(PARENT_WRITE_FD, command);
+ recv(PARENT_READ_FD);
+
+ command = "OPTION ttyname ttyname(0)\n";
+ send(PARENT_WRITE_FD, command);
+ recv(PARENT_READ_FD);
+
+ command = "GETPIN\n";
+ send(PARENT_WRITE_FD, command);
+ password = recv_password(PARENT_READ_FD);
+
+ command = "BYE\n";
+ send(PARENT_WRITE_FD, command);
+ recv(PARENT_READ_FD);
+
+ waitpid(child, NULL, 0);
+ }
+ return password;
+}
+
static char *signFile(const char *algo, const char *fdigest, int diglen,
const char *key, char *keypass)
{
diff --git a/lib/rpmsignfiles.h b/lib/rpmsignfiles.h
index 52e2482..b00703d 100644
--- a/lib/rpmsignfiles.h
+++ b/lib/rpmsignfiles.h
@@ -15,6 +15,7 @@ extern "C" {
rpmRC rpmSignFiles(Header h, const char *key, char *keypass);
char *get_fskpass(void); /* get file signing key password */
+char *get_pinentry_fskpass(void); /* call pinentry to get password */
#ifdef _cplusplus
}
diff --git a/rpmsign.c b/rpmsign.c
index 7f48d98..0cfbc92 100644
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -81,7 +81,9 @@ static int doSign(poptContext optCon)
#ifndef WITH_IMAEVM
argerror(_("--fskpass may only be specified when signing files"));
#else
- fileSigningKeyPassword = get_fskpass();
+ fileSigningKeyPassword = get_pinentry_fskpass();
+ if (!fileSigningKeyPassword)
+ fileSigningKeyPassword = get_fskpass();
#endif
}
--
2.4.3
More information about the Rpm-maint
mailing list