From 08d5c233b345b79326b8e1da9c4bed39e90a899d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 20 Jan 2020 21:22:33 +0000 Subject: [PATCH] Pageant: introduce an API for passphrase prompts. This begins to head towards the goal of storing a key file encrypted in Pageant, and decrypting it on demand via a GUI prompt the first time a client requests a signature from it. That won't be a facility available in all situations, so we have to be able to return failure from the prompt. More precisely, there are two versions of this API, one in PageantClient and one in PageantListenerClient: the stream implementation of PageantClient implements the former API and hands it off to the latter. Windows Pageant has to directly implement both (but they will end up funnelling to the same function within winpgnt.c). NFC: for the moment, the new API functions are never called, and every implementation of them returns failure. --- pageant.c | 10 ++++++++++ pageant.h | 18 ++++++++++++++++++ unix/uxpgnt.c | 8 ++++++++ windows/winpgnt.c | 16 ++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/pageant.c b/pageant.c index ee386c7a8..f82abe5ff 100644 --- a/pageant.c +++ b/pageant.c @@ -1037,9 +1037,19 @@ static void pageant_conn_got_response( } } +static bool pageant_conn_ask_passphrase( + PageantClient *pc, PageantClientDialogId *dlgid, const char *msg) +{ + struct pageant_conn_state *pcs = + container_of(pc, struct pageant_conn_state, pc); + return pageant_listener_client_ask_passphrase(pcs->plc, dlgid, msg); +} + + static const struct PageantClientVtable pageant_connection_clientvt = { pageant_conn_log, pageant_conn_got_response, + pageant_conn_ask_passphrase, }; static void pageant_conn_receive( diff --git a/pageant.h b/pageant.h index e80ef44d6..3d58df33b 100644 --- a/pageant.h +++ b/pageant.h @@ -15,6 +15,7 @@ typedef struct PageantClientVtable PageantClientVtable; typedef struct PageantClient PageantClient; typedef struct PageantClientInfo PageantClientInfo; typedef struct PageantClientRequestId PageantClientRequestId; +typedef struct PageantClientDialogId PageantClientDialogId; struct PageantClient { const struct PageantClientVtable *vt; PageantClientInfo *info; /* used by the central Pageant code */ @@ -32,6 +33,8 @@ struct PageantClientVtable { const char *fmt, va_list ap); void (*got_response)(PageantClient *pc, PageantClientRequestId *reqid, ptrlen response); + bool (*ask_passphrase)(PageantClient *pc, PageantClientDialogId *dlgid, + const char *msg); }; static inline void pageant_client_log_v( @@ -54,6 +57,9 @@ static inline PRINTF_LIKE(3, 4) void pageant_client_log( static inline void pageant_client_got_response( PageantClient *pc, PageantClientRequestId *reqid, ptrlen response) { pc->vt->got_response(pc, reqid, response); } +static inline bool pageant_client_ask_passphrase( + PageantClient *pc, PageantClientDialogId *dlgid, const char *msg) +{ return pc->vt->ask_passphrase(pc, dlgid, msg); } /* PageantClientRequestId is used to match up responses to the agent * requests they refer to. A client may allocate one of these for each @@ -91,6 +97,13 @@ void pageant_unregister_client(PageantClient *pc); void pageant_handle_msg(PageantClient *pc, PageantClientRequestId *reqid, ptrlen msg); +/* + * Send the core Pageant code a response to a passphrase request. + */ +void pageant_passphrase_request_success(PageantClientDialogId *dlgid, + ptrlen passphrase); +void pageant_passphrase_request_refused(PageantClientDialogId *dlgid); + /* * Construct a list of public keys, just as the two LIST_IDENTITIES * requests would have returned them. @@ -145,6 +158,8 @@ struct PageantListenerClient { }; struct PageantListenerClientVtable { void (*log)(PageantListenerClient *, const char *fmt, va_list ap); + bool (*ask_passphrase)(PageantListenerClient *pc, + PageantClientDialogId *dlgid, const char *msg); }; static inline void pageant_listener_client_log_v( @@ -163,6 +178,9 @@ static inline PRINTF_LIKE(2, 3) void pageant_listener_client_log( va_end(ap); } } +static inline bool pageant_listener_client_ask_passphrase( + PageantListenerClient *plc, PageantClientDialogId *dlgid, const char *msg) +{ return plc->vt->ask_passphrase(plc, dlgid, msg); } struct pageant_listen_state; struct pageant_listen_state *pageant_listener_new( diff --git a/unix/uxpgnt.c b/unix/uxpgnt.c index 594fd7168..0f4027e4a 100644 --- a/unix/uxpgnt.c +++ b/unix/uxpgnt.c @@ -44,8 +44,16 @@ static void uxpgnt_log(PageantListenerClient *plc, const char *fmt, va_list ap) fprintf(pageant_logfp, "\n"); } +static bool uxpgnt_ask_passphrase( + PageantListenerClient *plc, PageantClientDialogId *dlgid, const char *msg) +{ + /* FIXME: we don't yet support dialog boxes */ + return false; +} + static const PageantListenerClientVtable uxpgnt_vtable = { uxpgnt_log, + uxpgnt_ask_passphrase, }; /* diff --git a/windows/winpgnt.c b/windows/winpgnt.c index d8c951096..345cfbe31 100644 --- a/windows/winpgnt.c +++ b/windows/winpgnt.c @@ -792,9 +792,17 @@ static void wm_copydata_got_response( SetEvent(wmct.ev_reply_ready); } +static bool wm_copydata_ask_passphrase( + PageantClient *pc, PageantClientDialogId *dlgid, const char *msg) +{ + /* FIXME: we don't yet support dialog boxes */ + return false; +} + static const PageantClientVtable wmcpc_vtable = { NULL, /* no logging in this client */ wm_copydata_got_response, + wm_copydata_ask_passphrase, }; static char *answer_filemapping_message(const char *mapname) @@ -1176,11 +1184,19 @@ void cleanup_exit(int code) exit(code); } +static bool winpgnt_listener_ask_passphrase( + PageantListenerClient *plc, PageantClientDialogId *dlgid, const char *msg) +{ + /* FIXME: we don't yet support dialog boxes */ + return false; +} + struct winpgnt_client { PageantListenerClient plc; }; static const PageantListenerClientVtable winpgnt_vtable = { NULL, /* no logging */ + winpgnt_listener_ask_passphrase, }; static struct winpgnt_client wpc[1];