aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine-gpgsm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/engine-gpgsm.c104
1 files changed, 68 insertions, 36 deletions
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index 3a837577..476e9ef3 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -408,12 +408,10 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
int rc;
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (rc)
- {
- err = gpg_error_from_errno (rc);
- goto leave;
- }
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!rc)
{
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
{
@@ -564,7 +562,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
engine_status_handler_t status_fnc,
void *status_fnc_value)
{
- gpg_error_t err;
+ gpg_error_t err, cb_err;
char *line;
size_t linelen;
@@ -572,6 +570,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
if (err)
return err;
+ cb_err = 0;
do
{
err = assuan_read_line (ctx, &line, &linelen);
@@ -584,32 +583,45 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
if (linelen >= 2
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
- return 0;
+ return cb_err;
else if (linelen >= 4
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& line[3] == ' ')
- err = atoi (&line[4]);
+ {
+ /* We prefer a callback generated error because that one is
+ more related to gpgme and thus probably more important
+ than the error returned by the engine. */
+ err = cb_err? cb_err : atoi (&line[4]);
+ }
else if (linelen >= 2
&& line[0] == 'S' && line[1] == ' ')
{
- char *rest;
- gpgme_status_code_t r;
+ /* After an error from a status callback we skip all further
+ status lines. */
+ if (!cb_err)
+ {
+ char *rest;
+ gpgme_status_code_t r;
- rest = strchr (line + 2, ' ');
- if (!rest)
- rest = line + linelen; /* set to an empty string */
- else
- *(rest++) = 0;
+ rest = strchr (line + 2, ' ');
+ if (!rest)
+ rest = line + linelen; /* set to an empty string */
+ else
+ *(rest++) = 0;
- r = _gpgme_parse_status (line + 2);
+ r = _gpgme_parse_status (line + 2);
- if (r >= 0 && status_fnc)
- err = status_fnc (status_fnc_value, r, rest);
- else
- err = gpg_error (GPG_ERR_GENERAL);
+ if (r >= 0 && status_fnc)
+ cb_err = status_fnc (status_fnc_value, r, rest);
+ }
}
else
- err = gpg_error (GPG_ERR_GENERAL);
+ {
+ /* Invalid line or INQUIRY. We can't do anything else than
+ to stop. As with ERR we prefer a status callback
+ generated error code, though. */
+ err = cb_err ? cb_err : gpg_error (GPG_ERR_GENERAL);
+ }
}
while (!err);
@@ -1275,17 +1287,23 @@ gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- if (mode)
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
if (!pattern)
pattern = "";
- cmd = malloc (7 + strlen (pattern) + 1);
+ cmd = malloc (7 + 9 + 9 + strlen (pattern) + 1);
if (!cmd)
return gpg_error_from_syserror ();
+
strcpy (cmd, "EXPORT ");
- strcpy (&cmd[7], pattern);
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ strcat (cmd, "--secret ");
+ if ((mode & GPGME_EXPORT_MODE_RAW))
+ strcat (cmd, "--raw ");
+ else if ((mode & GPGME_EXPORT_MODE_PKCS12))
+ strcat (cmd, "--pkcs12 ");
+ }
+ strcat (cmd, pattern);
gpgsm->output_cb.data = keydata;
err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor"
@@ -1309,16 +1327,13 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err = 0;
char *line;
- /* Length is "EXPORT " + p + '\0'. */
- int length = 7 + 1;
+ /* Length is "EXPORT " + "--secret " + "--pkcs12 " + p + '\0'. */
+ int length = 7 + 9 + 9 + 1;
char *linep;
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- if (mode)
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
if (pattern && *pattern)
{
const char **pat = pattern;
@@ -1343,7 +1358,15 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
return gpg_error_from_syserror ();
strcpy (line, "EXPORT ");
- linep = &line[7];
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ strcat (line, "--secret ");
+ if ((mode & GPGME_EXPORT_MODE_RAW))
+ strcat (line, "--raw ");
+ else if ((mode & GPGME_EXPORT_MODE_PKCS12))
+ strcat (line, "--pkcs12 ");
+ }
+ linep = &line[strlen (line)];
if (pattern && *pattern)
{
@@ -1528,7 +1551,7 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
static gpgme_error_t
gpgsm_keylist (void *engine, const char *pattern, int secret_only,
- gpgme_keylist_mode_t mode)
+ gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpgsm_t gpgsm = engine;
char *line;
@@ -1585,6 +1608,11 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
+ "OPTION offline=1":
+ "OPTION offline=0" ,
+ NULL, NULL);
/* Length is "LISTSECRETKEYS " + p + '\0'. */
@@ -1615,7 +1643,7 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
static gpgme_error_t
gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
- int reserved, gpgme_keylist_mode_t mode)
+ int reserved, gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpgsm_t gpgsm = engine;
char *line;
@@ -1655,7 +1683,11 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
-
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
+ "OPTION offline=1":
+ "OPTION offline=0" ,
+ NULL, NULL);
if (pattern && *pattern)
{