core: New gpgme_set_ctx_flag "request-origin".
authorWerner Koch <wk@gnupg.org>
Fri, 23 Mar 2018 14:27:32 +0000 (15:27 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 23 Mar 2018 14:27:32 +0000 (15:27 +0100)
* src/context.h (gpgme_context): Add 'request_origin'.
* src/gpgme.c (gpgme_release): Free that field.
(gpgme_set_ctx_flag, gpgme_get_ctx_flag): Add "request-origin".
* src/engine-backend.h (engine_ops): Add 'set_engine_ops' func ptr and
adjust all users.
* src/engine.c (_gpgme_engine_set_engine_flags): New.
* src/op-support.c (_gpgme_op_reset): Call that func.
* src/engine-gpg.c (struct engine_gpg): Add 'request_origin'.
(gpg_set_engine_flags): New.
(_gpgme_engine_ops_gpg): Hook it.
(build_argv): Use command line option --request-origin.
* src/engine-gpgsm.c (struct engine_gpgsm): Add 'request_origin'.
(gpgsm_set_engine_flags): New.
(_gpgme_engine_ops_gpgsm): Hook it.
(start): Send OPTION "request-origin".
* src/engine-assuan.c (struct engine_llass): Add 'request_origin'.
(gpgsm_set_engine_flags): New.
(_gpgme_engine_ops_assuan): Hook it.
(start): Send OPTION "pretend-request-origin".

Signed-off-by: Werner Koch <wk@gnupg.org>
15 files changed:
doc/gpgme.texi
src/context.h
src/engine-assuan.c
src/engine-backend.h
src/engine-g13.c
src/engine-gpg.c
src/engine-gpgconf.c
src/engine-gpgsm.c
src/engine-spawn.c
src/engine-uiserver.c
src/engine.c
src/engine.h
src/gpgme.c
src/op-support.c
tests/run-decrypt.c

index 37cf16a..ab554d8 100644 (file)
@@ -3065,6 +3065,11 @@ a message signed by a brand new key (which you naturally will not have
 on your local keyring), the operator can tell both your IP address and
 the time when you verified the signature.
 
+@item "request-origin"
+The string given in @var{value} is passed to the GnuPG engines to
+request restrictions based on the origin of the request.  Valid values
+are documented in the GnuPG manual and the gpg man page under the
+option ``--request-origin''.
 
 @end table
 
index 1e763d2..202cf16 100644 (file)
@@ -145,6 +145,9 @@ struct gpgme_context
   /* The gpg specific override session key or NULL. */
   char *override_session_key;
 
+  /* The optional request origin.  */
+  char *request_origin;
+
   /* The locale for the pinentry.  */
   char *lc_ctype;
   char *lc_messages;
index bb2290a..6e603d9 100644 (file)
@@ -96,6 +96,7 @@ struct engine_llass
     int gpg_agent:1;  /* Assume this is a gpg-agent connection.  */
   } opt;
 
+  char request_origin[10];  /* Copy from the CTX.  */
 };
 typedef struct engine_llass *engine_llass_t;
 
@@ -365,6 +366,24 @@ llass_new (void **engine, const char *file_name, const char *home_dir,
 }
 
 
+/* Copy flags from CTX into the engine object.  */
+static void
+llass_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
+{
+  engine_llass_t llass = engine;
+
+  if (ctx->request_origin)
+    {
+      if (strlen (ctx->request_origin) + 1 > sizeof llass->request_origin)
+        strcpy (llass->request_origin, "xxx"); /* Too long  - force error */
+      else
+        strcpy (llass->request_origin, ctx->request_origin);
+    }
+  else
+    *llass->request_origin = 0;
+}
+
+
 static gpgme_error_t
 llass_set_locale (void *engine, int category, const char *value)
 {
@@ -660,6 +679,21 @@ start (engine_llass_t llass, const char *command)
   int nfds;
   int i;
 
+  if (*llass->request_origin && llass->opt.gpg_agent)
+    {
+      char *cmd;
+
+      cmd = _gpgme_strconcat ("OPTION pretend-request-origin=",
+                              llass->request_origin, NULL);
+      if (!cmd)
+        return gpg_error_from_syserror ();
+      err = assuan_transact (llass->assuan_ctx, cmd, NULL, NULL, NULL,
+                             NULL, NULL, NULL);
+      free (cmd);
+      if (err && gpg_err_code (err) != GPG_ERR_UNKNOWN_OPTION)
+        return err;
+    }
+
   /* We need to know the fd used by assuan for reads.  We do this by
      using the assumption that the first returned fd from
      assuan_get_active_fds() is always this one.  */
@@ -775,6 +809,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
     NULL,               /* set_colon_line_handler */
     llass_set_locale,
     NULL,              /* set_protocol */
+    llass_set_engine_flags,
     NULL,               /* decrypt */
     NULL,               /* delete */
     NULL,              /* edit */
index 421eb16..97cf6a1 100644 (file)
@@ -61,6 +61,7 @@ struct engine_ops
                                           void *fnc_value);
   gpgme_error_t (*set_locale) (void *engine, int category, const char *value);
   gpgme_error_t (*set_protocol) (void *engine, gpgme_protocol_t protocol);
+  void (*set_engine_flags) (void *engine, gpgme_ctx_t ctx);
   gpgme_error_t (*decrypt) (void *engine,
                             gpgme_decrypt_flags_t flags,
                             gpgme_data_t ciph,
index f8f3178..ec2f7af 100644 (file)
@@ -790,6 +790,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
     NULL,               /* set_colon_line_handler */
     g13_set_locale,
     NULL,              /* set_protocol */
+    NULL,               /* set_engine_flags */
     NULL,               /* decrypt */
     NULL,               /* delete */
     NULL,              /* edit */
index bfe7d13..22d327e 100644 (file)
@@ -143,6 +143,7 @@ struct engine_gpg
 
   struct gpgme_io_cbs io_cbs;
   gpgme_pinentry_mode_t pinentry_mode;
+  char request_origin[10];
 
   /* NULL or the data object fed to --override_session_key-fd.  */
   gpgme_data_t override_session_key;
@@ -628,6 +629,24 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
 }
 
 
+/* Copy flags from CTX into the engine object.  */
+static void
+gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
+{
+  engine_gpg_t gpg = engine;
+
+  if (ctx->request_origin && have_gpg_version (gpg, "2.2.6"))
+    {
+      if (strlen (ctx->request_origin) + 1 > sizeof gpg->request_origin)
+        strcpy (gpg->request_origin, "xxx"); /* Too long  - force error */
+      else
+        strcpy (gpg->request_origin, ctx->request_origin);
+    }
+  else
+    *gpg->request_origin = 0;
+}
+
+
 static gpgme_error_t
 gpg_set_locale (void *engine, int category, const char *value)
 {
@@ -904,6 +923,20 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
       argc++;
     }
 
+  if (*gpg->request_origin)
+    {
+      argv[argc] = _gpgme_strconcat ("--request-origin=",
+                                     gpg->request_origin, NULL);
+      if (!argv[argc])
+       {
+          int saved_err = gpg_error_from_syserror ();
+         free (fd_data_map);
+         free_argv (argv);
+         return saved_err;
+        }
+      argc++;
+    }
+
   if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
     {
       const char *s = NULL;
@@ -3090,6 +3123,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
     gpg_set_colon_line_handler,
     gpg_set_locale,
     NULL,                              /* set_protocol */
+    gpg_set_engine_flags,               /* set_engine_flags */
     gpg_decrypt,
     gpg_delete,
     gpg_edit,
index 94ae67f..24867c7 100644 (file)
@@ -1287,6 +1287,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
     NULL,              /* set_colon_line_handler */
     NULL,              /* set_locale */
     NULL,              /* set_protocol */
+    NULL,               /* set_engine_flags */
     NULL,              /* decrypt */
     NULL,              /* delete */
     NULL,              /* edit */
index e337fed..b8e44e7 100644 (file)
@@ -107,6 +107,8 @@ struct engine_gpgsm
 
   gpgme_data_t inline_data;  /* Used to collect D lines.  */
 
+  char request_origin[10];
+
   struct gpgme_io_cbs io_cbs;
 };
 
@@ -521,6 +523,24 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
 }
 
 
+/* Copy flags from CTX into the engine object.  */
+static void
+gpgsm_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
+{
+  engine_gpgsm_t gpgsm = engine;
+
+  if (ctx->request_origin)
+    {
+      if (strlen (ctx->request_origin) + 1 > sizeof gpgsm->request_origin)
+        strcpy (gpgsm->request_origin, "xxx"); /* Too long  - force error */
+      else
+        strcpy (gpgsm->request_origin, ctx->request_origin);
+    }
+  else
+    *gpgsm->request_origin = 0;
+}
+
+
 static gpgme_error_t
 gpgsm_set_locale (void *engine, int category, const char *value)
 {
@@ -1058,6 +1078,20 @@ start (engine_gpgsm_t gpgsm, const char *command)
   int nfds;
   int i;
 
+  if (*gpgsm->request_origin)
+    {
+      char *cmd;
+
+      cmd = _gpgme_strconcat ("OPTION request-origin=",
+                              gpgsm->request_origin, NULL);
+      if (!cmd)
+        return gpg_error_from_syserror ();
+      err = gpgsm_assuan_simple_command (gpgsm, cmd, NULL, NULL);
+      free (cmd);
+      if (err && gpg_err_code (err) != GPG_ERR_UNKNOWN_OPTION)
+        return err;
+    }
+
   /* We need to know the fd used by assuan for reads.  We do this by
      using the assumption that the first returned fd from
      assuan_get_active_fds() is always this one.  */
@@ -2102,6 +2136,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
     gpgsm_set_colon_line_handler,
     gpgsm_set_locale,
     NULL,              /* set_protocol */
+    gpgsm_set_engine_flags,
     gpgsm_decrypt,
     gpgsm_delete,      /* decrypt_verify */
     NULL,              /* edit */
index 7f78bb5..7b7a9cd 100644 (file)
@@ -449,6 +449,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
     NULL,              /* set_colon_line_handler */
     NULL,              /* set_locale */
     NULL,              /* set_protocol */
+    NULL,               /* set_engine_flags */
     NULL,              /* decrypt */
     NULL,              /* delete */
     NULL,              /* edit */
index bc3f3fb..fd5ac17 100644 (file)
@@ -1368,6 +1368,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     uiserver_set_colon_line_handler,
     uiserver_set_locale,
     uiserver_set_protocol,
+    NULL,               /* set_engine_flags */
     uiserver_decrypt,
     NULL,              /* delete */
     NULL,              /* edit */
index 28ba9fd..e51384f 100644 (file)
@@ -651,6 +651,26 @@ _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
 }
 
 
+/* Pass information about the current context to the engine.  The
+ * engine may use this context to retrieve context specific flags.
+ * Important: The engine is required to immediately copy the required
+ * flags to its own context!
+ *
+ * This function will eventually be used to reduce the number of
+ * explicit passed flags.  */
+void
+_gpgme_engine_set_engine_flags (engine_t engine, gpgme_ctx_t ctx)
+{
+  if (!engine)
+    return;
+
+  if (!engine->ops->set_engine_flags)
+    return;
+
+  (*engine->ops->set_engine_flags) (engine->engine, ctx);
+}
+
+
 gpgme_error_t
 _gpgme_engine_op_decrypt (engine_t engine,
                           gpgme_decrypt_flags_t flags,
index 0bf1bb2..34bf8e9 100644 (file)
@@ -69,6 +69,7 @@ gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
                                        const char *value);
 gpgme_error_t _gpgme_engine_set_protocol (engine_t engine,
                                          gpgme_protocol_t protocol);
+void _gpgme_engine_set_engine_flags (engine_t engine, gpgme_ctx_t ctx);
 void _gpgme_engine_release (engine_t engine);
 void _gpgme_engine_set_status_cb (engine_t engine,
                                   gpgme_status_cb_t cb, void *cb_value);
index d0a5afe..9e65c50 100644 (file)
@@ -248,6 +248,7 @@ gpgme_release (gpgme_ctx_t ctx)
   free (ctx->lc_ctype);
   free (ctx->lc_messages);
   free (ctx->override_session_key);
+  free (ctx->request_origin);
   _gpgme_engine_info_release (ctx->engine_info);
   ctx->engine_info = NULL;
   DESTROY_LOCK (ctx->lock);
@@ -486,13 +487,8 @@ gpgme_get_armor (gpgme_ctx_t ctx)
 }
 
 
-/* Set the flag NAME for CTX to VALUE.  The supported flags are:
- *
- * - full-status :: With a value of "1" the status callback set by
- *                  gpgme_set_status_cb returns all status lines
- *                  except for PROGRESS lines.  With the default of
- *                  "0" the status callback is only called in certain
- *                  situations.
+/* Set the flag NAME for CTX to VALUE.  Please consult the manual for
+ * a description of the flags.
  */
 gpgme_error_t
 gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
@@ -535,6 +531,13 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
     {
       ctx->auto_key_retrieve = abool;
     }
+  else if (!strcmp (name, "request-origin"))
+    {
+      free (ctx->request_origin);
+      ctx->request_origin = strdup (value);
+      if (!ctx->request_origin)
+        err = gpg_error_from_syserror ();
+    }
   else
     err = gpg_error (GPG_ERR_UNKNOWN_NAME);
 
@@ -576,6 +579,10 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
     {
       return ctx->auto_key_retrieve? "1":"";
     }
+  else if (!strcmp (name, "request-origin"))
+    {
+      return ctx->request_origin? ctx->request_origin : "";
+    }
   else
     return NULL;
 }
index 817c569..43cb1c7 100644 (file)
@@ -141,6 +141,8 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
        err = 0;
 
+      _gpgme_engine_set_engine_flags (ctx->engine, ctx);
+
       if (!err)
         {
           err = _gpgme_engine_set_pinentry_mode (ctx->engine,
index e961293..f4c4754 100644 (file)
@@ -81,6 +81,7 @@ show_usage (int ex)
          "  --cms            use the CMS protocol\n"
          "  --export-session-key            show the session key\n"
          "  --override-session-key STRING   use STRING as session key\n"
+         "  --request-origin STRING         use STRING as request origin\n"
          "  --unwrap         remove only the encryption layer\n"
          , stderr);
   exit (ex);
@@ -102,6 +103,7 @@ main (int argc, char **argv)
   int print_status = 0;
   int export_session_key = 0;
   const char *override_session_key = NULL;
+  const char *request_origin = NULL;
   int raw_output = 0;
 
   if (argc)
@@ -150,6 +152,14 @@ main (int argc, char **argv)
           override_session_key = *argv;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--request-origin"))
+        {
+          argc--; argv++;
+          if (!argc)
+            show_usage (1);
+          request_origin = *argv;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--unwrap"))
         {
           flags |= GPGME_DECRYPT_UNWRAP;
@@ -199,7 +209,18 @@ main (int argc, char **argv)
                                 override_session_key);
       if (err)
         {
-          fprintf (stderr, PGM ": error overriding session key: %s\n",
+          fprintf (stderr, PGM ": error setting overriding session key: %s\n",
+                   gpgme_strerror (err));
+          exit (1);
+        }
+    }
+
+  if (request_origin)
+    {
+      err = gpgme_set_ctx_flag (ctx, "request-origin", request_origin);
+      if (err)
+        {
+          fprintf (stderr, PGM ": error setting request_origin: %s\n",
                    gpgme_strerror (err));
           exit (1);
         }