aboutsummaryrefslogtreecommitdiffstats
path: root/agent/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/query.c')
-rw-r--r--agent/query.c97
1 files changed, 64 insertions, 33 deletions
diff --git a/agent/query.c b/agent/query.c
index 7a20b1498..af513b819 100644
--- a/agent/query.c
+++ b/agent/query.c
@@ -27,6 +27,9 @@
#include <assert.h>
#include <unistd.h>
#include <sys/stat.h>
+#ifdef USE_GNU_PTH
+# include <pth.h>
+#endif
#include "agent.h"
#include "../assuan/assuan.h"
@@ -38,6 +41,9 @@
#endif
static ASSUAN_CONTEXT entry_ctx = NULL;
+#ifdef USE_GNU_PTH
+static pth_mutex_t entry_lock = PTH_MUTEX_INIT;
+#endif
/* data to be passed to our callbacks */
struct entry_parm_s {
@@ -49,7 +55,24 @@ struct entry_parm_s {
-/* Fork off the pin entry if this has not already been done */
+static int
+unlock_pinentry (int rc)
+{
+#ifdef USE_GNU_PTH
+ if (!pth_mutex_release (&entry_lock))
+ {
+ log_error ("failed to release the entry lock\n");
+ if (!rc)
+ rc = GNUPG_Internal_Error;
+ }
+#endif
+ return rc;
+}
+
+/* Fork off the pin entry if this has not already been done. Note,
+ that this function must always be used to aquire the lock for the
+ pinentry - we will serialize _all_ pinentry calls.
+ */
static int
start_pinentry (void)
{
@@ -58,10 +81,16 @@ start_pinentry (void)
ASSUAN_CONTEXT ctx;
const char *argv[5];
+#ifdef USE_GNU_PTH
+ if (!pth_mutex_acquire (&entry_lock, 0, NULL))
+ {
+ log_error ("failed to acquire the entry lock\n");
+ return GNUPG_Internal_Error;
+ }
+#endif
+
if (entry_ctx)
- return 0; /* No need to serialize things becuase the agent is
- expected to tun as a single-thread (or may be in
- future using libpth) */
+ return 0;
if (opt.verbose)
log_info ("no running PIN Entry - starting it\n");
@@ -69,7 +98,7 @@ start_pinentry (void)
if (fflush (NULL))
{
log_error ("error flushing pending output: %s\n", strerror (errno));
- return seterr (Write_Error);
+ return unlock_pinentry (seterr (Write_Error));
}
/* FIXME: change the default location of the program */
@@ -80,6 +109,7 @@ start_pinentry (void)
else
pgmname++;
+ /* FIXME: We must do this thread specific */
argv[0] = pgmname;
if (opt.display)
{
@@ -96,7 +126,7 @@ start_pinentry (void)
{
log_error ("can't connect to the PIN entry module: %s\n",
assuan_strerror (rc));
- return seterr (No_PIN_Entry);
+ return unlock_pinentry (seterr (No_PIN_Entry));
}
entry_ctx = ctx;
@@ -107,47 +137,47 @@ start_pinentry (void)
opt.no_grab? "OPTION no-grab":"OPTION grab",
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
if (opt.ttyname)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
- return GNUPG_Out_Of_Core;
+ return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
free (optstr);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
if (opt.ttytype)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
- return GNUPG_Out_Of_Core;
+ return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
if (opt.lc_ctype)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
- return GNUPG_Out_Of_Core;
+ return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
if (opt.lc_messages)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
- return GNUPG_Out_Of_Core;
+ return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
return 0;
}
@@ -213,14 +243,14 @@ agent_askpin (const char *desc_text, const char *start_err_text,
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
rc = assuan_transact (entry_ctx,
pininfo->min_digits? "SETPROMPT PIN:"
: "SETPROMPT Passphrase:",
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
{
@@ -242,7 +272,7 @@ agent_askpin (const char *desc_text, const char *start_err_text,
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
errtext = NULL;
}
@@ -251,9 +281,9 @@ agent_askpin (const char *desc_text, const char *start_err_text,
errtext = pininfo->min_digits? trans ("PIN too long")
: trans ("Passphrase too long");
else if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
if (!errtext && !pininfo->min_digits)
- return 0; /* okay, got a passphrase */
+ return unlock_pinentry (0); /* okay, got a passphrase */
if (!errtext && !all_digitsp (pininfo->pin))
errtext = trans ("Invalid characters in PIN");
if (!errtext && pininfo->max_digits
@@ -264,10 +294,11 @@ agent_askpin (const char *desc_text, const char *start_err_text,
errtext = trans ("PIN too short");
if (!errtext)
- return 0; /* okay, got a PIN */
+ return unlock_pinentry (0); /* okay, got a PIN */
}
- return pininfo->min_digits? GNUPG_Bad_PIN : GNUPG_Bad_Passphrase;
+ return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN
+ : GNUPG_Bad_Passphrase);
}
@@ -301,13 +332,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt? prompt : "Passphrase");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
if (errtext)
{
@@ -315,28 +346,28 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
memset (&parm, 0, sizeof parm);
parm.size = ASSUAN_LINELENGTH/2 - 5;
parm.buffer = gcry_malloc_secure (parm.size+10);
if (!parm.buffer)
- return seterr (Out_Of_Core);
+ return unlock_pinentry (seterr (Out_Of_Core));
assuan_begin_confidential (entry_ctx);
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
if (rc)
{
xfree (parm.buffer);
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1);
if (!hexstring)
{
xfree (parm.buffer);
- return seterr (Out_Of_Core);
+ return unlock_pinentry (seterr (Out_Of_Core));
}
for (i=0, p=parm.buffer; *p; p++, i += 2)
@@ -344,7 +375,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
xfree (parm.buffer);
*retpass = hexstring;
- return 0;
+ return unlock_pinentry (0);
}
@@ -370,7 +401,7 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
if (ok)
{
@@ -378,7 +409,7 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
if (cancel)
{
@@ -386,11 +417,11 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
+ return unlock_pinentry (map_assuan_err (rc));
}