diff options
Diffstat (limited to '')
| -rw-r--r-- | NEWS | 11 | ||||
| -rw-r--r-- | doc/gpgme.texi | 77 | ||||
| -rw-r--r-- | src/encrypt-sign.c | 111 | ||||
| -rw-r--r-- | src/encrypt.c | 106 | ||||
| -rw-r--r-- | src/engine-backend.h | 2 | ||||
| -rw-r--r-- | src/engine-gpg.c | 70 | ||||
| -rw-r--r-- | src/engine-gpgsm.c | 58 | ||||
| -rw-r--r-- | src/engine-uiserver.c | 59 | ||||
| -rw-r--r-- | src/engine.c | 10 | ||||
| -rw-r--r-- | src/engine.h | 2 | ||||
| -rw-r--r-- | src/gpgme-json.c | 74 | ||||
| -rw-r--r-- | src/gpgme.def | 5 | ||||
| -rw-r--r-- | src/gpgme.h.in | 30 | ||||
| -rw-r--r-- | src/libgpgme.vers | 9 | ||||
| -rw-r--r-- | tests/run-encrypt.c | 40 | 
15 files changed, 519 insertions, 145 deletions
| @@ -5,11 +5,16 @@ Noteworthy changes in version 1.10.1 (unreleased)   * Interface changes relative to the 1.10.0 release:   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gpgme_import_result_t       EXTENDED: New field 'skipped_v3_keys' - cpp: Key::locate                     NEW. - cpp: Data::toString                  NEW. + gpgme_op_encrypt_ext             NEW. + gpgme_op_encrypt_ext_start       NEW. + gpgme_op_encrypt_sign_ext        NEW. + gpgme_op_encrypt_sign_ext_start  NEW. + gpgme_import_result_t            EXTENDED: New field 'skipped_v3_keys'. + cpp: Key::locate                 NEW. + cpp: Data::toString              NEW.   cpp: ImportResult::numV3KeysSkipped  NEW. +  Noteworthy changes in version 1.10.0 (2017-12-12)  ------------------------------------------------- diff --git a/doc/gpgme.texi b/doc/gpgme.texi index cbb0e649..1df9c46e 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -6154,6 +6154,45 @@ pointer, and @code{GPG_ERR_UNUSABLE_PUBKEY} if @var{rset} does not  contain any valid recipients.  @end deftypefun +@deftypefun gpgme_error_t gpgme_op_encrypt_ext @ +            (@w{gpgme_ctx_t @var{ctx}}, @ +             @w{gpgme_key_t @var{recp}[]}, @ +             @w{const char *@var{recpstring}}, @ +             @w{gpgme_encrypt_flags_t @var{flags}}, @ +             @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) + +@since{1.11.0} + +This is an extended version of @code{gpgme_op_encrypt} with +@var{recpstring} as additional parameter.  If @var{recp} is NULL and +@var{recpstring} is not NULL, the latter is expected to be a linefeed +delimited string with the set of key specifications.  In contrast to +@var{recp} the keys are given directly as strings and there is no need +to first create key objects.  The keys are passed verbatim to the +backend engine. + +@end deftypefun + + +@deftypefun gpgme_error_t gpgme_op_encrypt_ext_start @ +            (@w{gpgme_ctx_t @var{ctx}}, @ +             @w{gpgme_key_t @var{recp}[]}, @ +             @w{const char *@var{recpstring}}, @ +             @w{gpgme_encrypt_flags_t @var{flags}}, @ +             @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) + +@since{1.11.0} + +This is an extended version of @code{gpgme_op_encrypt_start} with +@var{recpstring} as additional parameter.  If @var{recp} is NULL and +@var{recpstring} is not NULL, the latter is expected to be a linefeed +delimited string with the set of key specifications.  In contrast to +@var{recp} the keys are given directly as strings and there is no need +to first create key objects.  The keys are passed verbatim to the +backend engine. + +@end deftypefun +  @deftp {Data type} {gpgme_encrypt_result_t}  This is a pointer to a structure used to store the result of a  @code{gpgme_op_encrypt} operation.  After successfully encrypting @@ -6203,6 +6242,44 @@ if @var{ctx}, @var{rset}, @var{plain} or @var{cipher} is not a valid  pointer.  @end deftypefun +@deftypefun gpgme_error_t gpgme_op_encrypt_sign_ext @ +            (@w{gpgme_ctx_t @var{ctx}}, @ +             @w{gpgme_key_t @var{recp}[]}, @ +             @w{const char *@var{recpstring}}, @ +             @w{gpgme_encrypt_flags_t @var{flags}}, @ +             @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) + +@since{1.11.0} + +This is an extended version of @code{gpgme_op_encrypt_sign} with +@var{recpstring} as additional parameter.  If @var{recp} is NULL and +@var{recpstring} is not NULL, the latter is expected to be a linefeed +delimited string with the set of key specifications.  In contrast to +@var{recp} the keys are given directly as strings and there is no need +to first create the key objects.  The keys are passed verbatim to the +backend engine. + +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_encrypt_sign_ext_start @ +            (@w{gpgme_ctx_t @var{ctx}}, @ +             @w{gpgme_key_t @var{recp}[]}, @ +             @w{const char *@var{recpstring}}, @ +             @w{gpgme_encrypt_flags_t @var{flags}}, @ +             @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) + +@since{1.11.0} + +This is an extended version of @code{gpgme_op_encrypt_sign_start} with +@var{recpstring} as additional parameter.  If @var{recp} is NULL and +@var{recpstring} is not NULL, the latter is expected to be a linefeed +delimited string with the set of key specifications.  In contrast to +@var{recp} the keys are given directly as strings and there is no need +to first create the key objects.  The keys are passed verbatim to the +backend engine. + +@end deftypefun +  @node Miscellaneous  @section Miscellaneous operations diff --git a/src/encrypt-sign.c b/src/encrypt-sign.c index af6de63e..4db46e25 100644 --- a/src/encrypt-sign.c +++ b/src/encrypt-sign.c @@ -62,6 +62,7 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)  static gpgme_error_t  encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], +                    const char *recpstring,  		    gpgme_encrypt_flags_t flags,  		    gpgme_data_t plain, gpgme_data_t cipher)  { @@ -72,7 +73,7 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],    if (err)      return err; -  symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC); +  symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);    if (!plain)      return gpg_error (GPG_ERR_NO_DATA); @@ -103,43 +104,75 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],                                      : encrypt_sign_status_handler,  				    ctx); -  return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, flags, plain, +  return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, recpstring, +                                        flags, plain,  					cipher, ctx->use_armor,  					ctx /* FIXME */);  } -/* Encrypt plaintext PLAIN within CTX for the recipients RECP and -   store the resulting ciphertext in CIPHER.  Also sign the ciphertext -   with the signers in CTX.  */ +/* Old version of gpgme_op_encrypt_sign_ext_start w/o RECPSTRING.  */  gpgme_error_t  gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],  			     gpgme_encrypt_flags_t flags,  			     gpgme_data_t plain, gpgme_data_t cipher)  { +  return gpgme_op_encrypt_sign_ext_start (ctx, recp, NULL, +                                          flags, plain, cipher); +} + + +/* Old version of gpgme_op_encrypt_sign_ext w/o RECPSTRING.  */ +gpgme_error_t +gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], +		       gpgme_encrypt_flags_t flags, +		       gpgme_data_t plain, gpgme_data_t cipher) +{ +  return gpgme_op_encrypt_sign_ext (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + * store the resulting ciphertext in CIPHER.  Also sign the ciphertext + * with the signers in CTX.  */ +gpgme_error_t +gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], +                           const char *recpstring, +                           gpgme_encrypt_flags_t flags, +                           gpgme_data_t plain, gpgme_data_t cipher) +{    gpgme_error_t err; -  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx, +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign", ctx,  	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);    if (!ctx)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); -  if (_gpgme_debug_trace () && recp) +  if (_gpgme_debug_trace () && (recp || recpstring))      { -      int i = 0; - -      while (recp[i]) -	{ -	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], -		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? -		      recp[i]->subkeys->fpr : "invalid"); -	  i++; -	} +      if (recp) +        { +          int i = 0; + +          while (recp[i]) +            { +              TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], +                          (recp[i]->subkeys && recp[i]->subkeys->fpr) ? +                          recp[i]->subkeys->fpr : "invalid"); +              i++; +            } +        } +      else +        { +          TRACE_LOG1 ("recipients = '%s'", recpstring); +        }      } -  err = encrypt_sign_start (ctx, 0, recp, flags, plain, cipher); -  return err; +  err = encrypt_sign_start (ctx, 1, recp, recpstring, flags, plain, cipher); +  if (!err) +    err = _gpgme_wait_one (ctx); +  return TRACE_ERR (err);  } @@ -147,33 +180,39 @@ gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],     store the resulting ciphertext in CIPHER.  Also sign the ciphertext     with the signers in CTX.  */  gpgme_error_t -gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], -		       gpgme_encrypt_flags_t flags, -		       gpgme_data_t plain, gpgme_data_t cipher) +gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], +                                 const char *recpstring, +                                 gpgme_encrypt_flags_t flags, +                                 gpgme_data_t plain, gpgme_data_t cipher)  {    gpgme_error_t err; -  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign", ctx, +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx,  	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);    if (!ctx)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); -  if (_gpgme_debug_trace () && recp) +  if (_gpgme_debug_trace () && (recp || recpstring))      { -      int i = 0; - -      while (recp[i]) -	{ -	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], -		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? -		      recp[i]->subkeys->fpr : "invalid"); -	  i++; -	} +      if (recp) +        { +          int i = 0; + +          while (recp[i]) +            { +              TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], +                          (recp[i]->subkeys && recp[i]->subkeys->fpr) ? +                          recp[i]->subkeys->fpr : "invalid"); +              i++; +            } +        } +      else +        { +          TRACE_LOG1 ("recipients = '%s'", recpstring); +        }      } -  err = encrypt_sign_start (ctx, 1, recp, flags, plain, cipher); -  if (!err) -    err = _gpgme_wait_one (ctx); -  return TRACE_ERR (err); +  err = encrypt_sign_start (ctx, 0, recp, recpstring, flags, plain, cipher); +  return err;  } diff --git a/src/encrypt.c b/src/encrypt.c index 40236544..2318497e 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -214,6 +214,7 @@ _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)  static gpgme_error_t  encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], +               const char *recpstring,  	       gpgme_encrypt_flags_t flags,  	       gpgme_data_t plain, gpgme_data_t cipher)  { @@ -228,13 +229,13 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],    if (err)      return err; -  symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC); +  symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);    if (!plain)      return gpg_error (GPG_ERR_NO_DATA);    if (!cipher)      return gpg_error (GPG_ERR_INV_VALUE); -  if (recp && ! *recp) +  if (recp && !*recp)      return gpg_error (GPG_ERR_INV_VALUE);    if (symmetric && ctx->passphrase_cb) @@ -252,72 +253,111 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],  				    : encrypt_status_handler,  				    ctx); -  return _gpgme_engine_op_encrypt (ctx->engine, recp, flags, plain, cipher, -				   ctx->use_armor); +  return _gpgme_engine_op_encrypt (ctx->engine, recp, recpstring, +                                   flags, plain, cipher, ctx->use_armor);  } +/* Old version of gpgme_op_encrypt_ext without RECPSTRING.  */ +gpgme_error_t +gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], +		  gpgme_encrypt_flags_t flags, +		  gpgme_data_t plain, gpgme_data_t cipher) +{ +  return gpgme_op_encrypt_ext (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Old version of gpgme_op_encrypt_ext_start without RECPSTRING.  */  gpgme_error_t  gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],  			gpgme_encrypt_flags_t flags,  			gpgme_data_t plain, gpgme_data_t cipher)  { +  return gpgme_op_encrypt_ext_start (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + * store the resulting ciphertext in CIPHER.  RECPSTRING can be used + * instead of the RECP array to directly specify recipients as LF + * delimited strings; these may be any kind of recipient specification + * patterns as supported by the backend.  */ +gpgme_error_t +gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], +                      const char *recpstring, +                      gpgme_encrypt_flags_t flags, +                      gpgme_data_t plain, gpgme_data_t cipher) +{    gpgme_error_t err; -  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx, +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt", ctx,  	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);    if (!ctx)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); -  if (_gpgme_debug_trace () && recp) +  if (_gpgme_debug_trace () && (recp || recpstring))      { -      int i = 0; +      if (recp) +        { +          int i = 0; -      while (recp[i]) -	{ -	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], +          while (recp[i]) +            { +              TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],  		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? -		      recp[i]->subkeys->fpr : "invalid"); -	  i++; -	} +                          recp[i]->subkeys->fpr : "invalid"); +              i++; +            } +        } +      else +        { +          TRACE_LOG1 ("recipients = '%s'", recpstring); +        }      } -  err = encrypt_start (ctx, 0, recp, flags, plain, cipher); +  err = encrypt_start (ctx, 1, recp, recpstring, flags, plain, cipher); +  if (!err) +    err = _gpgme_wait_one (ctx);    return TRACE_ERR (err);  } -/* Encrypt plaintext PLAIN within CTX for the recipients RECP and -   store the resulting ciphertext in CIPHER.  */  gpgme_error_t -gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], -		  gpgme_encrypt_flags_t flags, -		  gpgme_data_t plain, gpgme_data_t cipher) +gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], +                            const char *recpstring, +                            gpgme_encrypt_flags_t flags, +                            gpgme_data_t plain, gpgme_data_t cipher)  {    gpgme_error_t err; -  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt", ctx, +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx,  	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);    if (!ctx)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); -  if (_gpgme_debug_trace () && recp) +  if (_gpgme_debug_trace () && (recp || recpstring))      { -      int i = 0; - -      while (recp[i]) -	{ -	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], -		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? -		      recp[i]->subkeys->fpr : "invalid"); -	  i++; -	} +      if (recp) +        { +          int i = 0; + +          while (recp[i]) +            { +              TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], +                          (recp[i]->subkeys && recp[i]->subkeys->fpr) ? +                          recp[i]->subkeys->fpr : "invalid"); +              i++; +            } +        } +      else +        { +          TRACE_LOG1 ("recipients = '%s'", recpstring); +        }      } -  err = encrypt_start (ctx, 1, recp, flags, plain, cipher); -  if (!err) -    err = _gpgme_wait_one (ctx); +  err = encrypt_start (ctx, 0, recp, recpstring, flags, plain, cipher);    return TRACE_ERR (err);  } diff --git a/src/engine-backend.h b/src/engine-backend.h index 97cf6a10..f6926662 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -72,10 +72,12 @@ struct engine_ops    gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key,  			 gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */);    gpgme_error_t (*encrypt) (void *engine, gpgme_key_t recp[], +                            const char *recpstring,  			    gpgme_encrypt_flags_t flags,  			    gpgme_data_t plain, gpgme_data_t ciph,  			    int use_armor);    gpgme_error_t (*encrypt_sign) (void *engine, gpgme_key_t recp[], +                                 const char *recpstring,  				 gpgme_encrypt_flags_t flags,  				 gpgme_data_t plain, gpgme_data_t ciph,  				 int use_armor, gpgme_ctx_t ctx /* FIXME */); diff --git a/src/engine-gpg.c b/src/engine-gpg.c index a37d1f7b..809806c4 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1914,17 +1914,64 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])  } +/* Take recipients from the LF delimited STRING and add -r args.  */ +static gpg_error_t +append_args_from_recipients_string (engine_gpg_t gpg, const char *string) +{ +  gpg_error_t err = 0; +  int any = 0; +  const char *s; +  int n; + +  do +    { +      /* Skip leading white space */ +      while (*string == ' ' || *string == '\t') +        string++; +      if (!*string) +        break; + +      /* Look for the LF. */ +      s = strchr (string, '\n'); +      if (s) +        n = s - string; +      else +        n = strlen (string); +      while (n && (string[n-1] == ' ' || string[n-1] == '\t')) +        n--; + +      /* Add arg if it is not empty.  */ +      if (n) +        { +          err = add_arg (gpg, "-r"); +          if (!err) +            err = add_arg_len (gpg, NULL, string, n); +          if (!err) +            any = 1; +        } + +      string += n + !!s; +    } +  while (!err); + +  if (!err && !any) +    err = gpg_error (GPG_ERR_MISSING_KEY); +  return err; +} + +  static gpgme_error_t -gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, +             gpgme_encrypt_flags_t flags,  	     gpgme_data_t plain, gpgme_data_t ciph, int use_armor)  {    engine_gpg_t gpg = engine;    gpgme_error_t err = 0; -  if (recp) +  if (recp || recpstring)      err = add_arg (gpg, "--encrypt"); -  if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) +  if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))      err = add_arg (gpg, "--symmetric");    if (!err && use_armor) @@ -1951,7 +1998,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,        && have_gpg_version (gpg, "2.1.14"))      err = add_arg (gpg, "--mimemode"); -  if (recp) +  if (recp || recpstring)      {        /* If we know that all recipients are valid (full or ultimate trust)  	 we can suppress further checks.  */ @@ -1961,7 +2008,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,        if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))  	err = add_arg (gpg, "--no-encrypt-to"); -      if (!err) +      if (!err && !recp && recpstring) +	err = append_args_from_recipients_string (gpg, recpstring); +      else if (!err)  	err = append_args_from_recipients (gpg, recp);      } @@ -1995,6 +2044,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,  static gpgme_error_t  gpg_encrypt_sign (void *engine, gpgme_key_t recp[], +                  const char *recpstring,  		  gpgme_encrypt_flags_t flags, gpgme_data_t plain,  		  gpgme_data_t ciph, int use_armor,  		  gpgme_ctx_t ctx /* FIXME */) @@ -2002,10 +2052,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],    engine_gpg_t gpg = engine;    gpgme_error_t err = 0; -  if (recp) +  if (recp || recpstring)      err = add_arg (gpg, "--encrypt"); -  if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) +  if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))      err = add_arg (gpg, "--symmetric");    if (!err) @@ -2023,7 +2073,7 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],        && have_gpg_version (gpg, "2.1.14"))      err = add_arg (gpg, "--mimemode"); -  if (recp) +  if (recp || recpstring)      {        /* If we know that all recipients are valid (full or ultimate trust)  	 we can suppress further checks.  */ @@ -2033,7 +2083,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],        if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))  	err = add_arg (gpg, "--no-encrypt-to"); -      if (!err) +      if (!err && !recp && recpstring) +	err = append_args_from_recipients_string (gpg, recpstring); +      else if (!err)  	err = append_args_from_recipients (gpg, recp);      } diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index b8e44e7c..da7e524f 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1327,8 +1327,57 @@ set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])  } +/* Take recipients from the LF delimited STRING and send RECIPIENT + * commands to gpgsm.  */  static gpgme_error_t -gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +set_recipients_from_string (engine_gpgsm_t gpgsm, const char *string) +{ +  gpg_error_t err = 0; +  char *line = NULL; +  int no_pubkey = 0; +  const char *s; +  int n; + +  for (;;) +    { +      while (*string == ' ' || *string == '\t') +        string++; +      if (!*string) +        break; + +      s = strchr (string, '\n'); +      if (s) +        n = s - string; +      else +        n = strlen (string); +      while (n && (string[n-1] == ' ' || string[n-1] == '\t')) +        n--; + +      gpgrt_free (line); +      if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0) +        { +          err = gpg_error_from_syserror (); +          break; +        } +      string += n + !!s; + +      err = gpgsm_assuan_simple_command (gpgsm, line, gpgsm->status.fnc, +					 gpgsm->status.fnc_value); + +      /* Fixme: Improve error reporting.  */ +      if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) +	no_pubkey++; +      else if (err) +        break; +    } +  gpgrt_free (line); +  return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0; +} + + +static gpgme_error_t +gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, +               gpgme_encrypt_flags_t flags,  	       gpgme_data_t plain, gpgme_data_t ciph, int use_armor)  {    engine_gpgsm_t gpgsm = engine; @@ -1339,7 +1388,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,    if (!recp)      return gpg_error (GPG_ERR_NOT_IMPLEMENTED); -  if (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO) +  if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))      {        err = gpgsm_assuan_simple_command (gpgsm,  					 "OPTION no-encrypt-to", NULL, NULL); @@ -1359,7 +1408,10 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,    gpgsm_clear_fd (gpgsm, MESSAGE_FD);    gpgsm->inline_data = NULL; -  err = set_recipients (gpgsm, recp); +  if (!recp && recpstring) +    err = set_recipients_from_string (gpgsm, recpstring); +  else +    err = set_recipients (gpgsm, recp);    if (!err)      err = start (gpgsm, "ENCRYPT"); diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index fd5ac174..d8f4fce3 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1075,8 +1075,58 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])  } +/* Take recipients from the LF delimited STRING and send RECIPIENT + * commands to gpgsm.  */  static gpgme_error_t -uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +set_recipients_from_string (engine_uiserver_t uiserver, const char *string) +{ +  gpg_error_t err = 0; +  char *line = NULL; +  int no_pubkey = 0; +  const char *s; +  int n; + +  for (;;) +    { +      while (*string == ' ' || *string == '\t') +        string++; +      if (!*string) +        break; + +      s = strchr (string, '\n'); +      if (s) +        n = s - string; +      else +        n = strlen (string); +      while (n && (string[n-1] == ' ' || string[n-1] == '\t')) +        n--; + +      gpgrt_free (line); +      if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0) +        { +          err = gpg_error_from_syserror (); +          break; +        } +      string += n + !!s; + +      err = uiserver_assuan_simple_command (uiserver, line, +                                            uiserver->status.fnc, +                                            uiserver->status.fnc_value); + +      /* Fixme: Improve error reporting.  */ +      if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) +	no_pubkey++; +      else if (err) +        break; +    } +  gpgrt_free (line); +  return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0; +} + + +static gpgme_error_t +uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, +                  gpgme_encrypt_flags_t flags,  		  gpgme_data_t plain, gpgme_data_t ciph, int use_armor)  {    engine_uiserver_t uiserver = engine; @@ -1140,9 +1190,12 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,    uiserver->inline_data = NULL; -  if (recp) +  if (recp || recpstring)      { -      err = set_recipients (uiserver, recp); +      if (recp) +        err = set_recipients (uiserver, recp); +      else +        err = set_recipients_from_string (uiserver, recpstring);        if (err)  	{  	  gpgrt_free (cmd); diff --git a/src/engine.c b/src/engine.c index e51384f0..b716ca24 100644 --- a/src/engine.c +++ b/src/engine.c @@ -721,6 +721,7 @@ _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,  gpgme_error_t  _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[], +                          const char *recpstring,  			  gpgme_encrypt_flags_t flags,  			  gpgme_data_t plain, gpgme_data_t ciph, int use_armor)  { @@ -730,13 +731,14 @@ _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],    if (!engine->ops->encrypt)      return gpg_error (GPG_ERR_NOT_IMPLEMENTED); -  return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph, -				  use_armor); +  return (*engine->ops->encrypt) (engine->engine, recp, recpstring, +                                  flags, plain, ciph, use_armor);  }  gpgme_error_t  _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], +                               const char *recpstring,  			       gpgme_encrypt_flags_t flags,  			       gpgme_data_t plain, gpgme_data_t ciph,  			       int use_armor, gpgme_ctx_t ctx /* FIXME */) @@ -747,8 +749,8 @@ _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],    if (!engine->ops->encrypt_sign)      return gpg_error (GPG_ERR_NOT_IMPLEMENTED); -  return (*engine->ops->encrypt_sign) (engine->engine, recp, flags, -				       plain, ciph, use_armor, ctx); +  return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring, +                                       flags, plain, ciph, use_armor, ctx);  } diff --git a/src/engine.h b/src/engine.h index 34bf8e90..8b692f2e 100644 --- a/src/engine.h +++ b/src/engine.h @@ -98,11 +98,13 @@ gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type,  				     gpgme_ctx_t ctx /* FIXME */);  gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine,  					gpgme_key_t recp[], +                                        const char *recpstring,  					gpgme_encrypt_flags_t flags,  					gpgme_data_t plain, gpgme_data_t ciph,  					int use_armor);  gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine,  					     gpgme_key_t recp[], +                                             const char *recpstring,  					     gpgme_encrypt_flags_t flags,  					     gpgme_data_t plain,  					     gpgme_data_t ciph, diff --git a/src/gpgme-json.c b/src/gpgme-json.c index b54d9a8a..4b1cd5b8 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -354,18 +354,19 @@ get_protocol (cjson_t json, gpgme_protocol_t *r_protocol)  } -/* Extract the keys from the KEYS array in the JSON object.  CTX is a - * GPGME context object.  On success an array with the keys is stored - * at R_KEYS.  In failure an error code is returned.  */ +/* Extract the keys from the "keys" array in the JSON object.  On + * success a string with the keys identifiers is stored at R_KEYS. + * The keys in that string are LF delimited.  On failure an error code + * is returned.  */  static gpg_error_t -get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys) +get_keys (cjson_t json, char **r_keystring)  { -  gpg_error_t err;    cjson_t j_keys, j_item;    int i, nkeys; -  gpgme_key_t *keys; +  char *p; +  size_t length; -  *r_keys = NULL; +  *r_keystring = NULL;    j_keys = cJSON_GetObjectItem (json, "keys");    if (!j_keys) @@ -373,8 +374,15 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys)    if (!cjson_is_array (j_keys) && !cjson_is_string (j_keys))      return gpg_error (GPG_ERR_INV_VALUE); +  /* Fixme: We should better use a membuf like thing.  */ +  length = 1; /* For the EOS.  */    if (cjson_is_string (j_keys)) -    nkeys = 1; +    { +      nkeys = 1; +      length += strlen (j_keys->valuestring); +      if (strchr (j_keys->valuestring, '\n')) +        return gpg_error (GPG_ERR_INV_USER_ID); +    }    else      {        nkeys = cJSON_GetArraySize (j_keys); @@ -385,43 +393,37 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys)            j_item = cJSON_GetArrayItem (j_keys, i);            if (!j_item || !cjson_is_string (j_item))              return gpg_error (GPG_ERR_INV_VALUE); +          if (i) +            length++; /* Space for delimiter. */ +          length += strlen (j_item->valuestring); +          if (strchr (j_item->valuestring, '\n')) +            return gpg_error (GPG_ERR_INV_USER_ID);          }      } -  /* Now allocate an array to store the gpgme key objects.  */ -  keys = xcalloc (nkeys + 1, sizeof *keys); +  p = *r_keystring = xtrymalloc (length); +  if (!p) +    return gpg_error_from_syserror ();    if (cjson_is_string (j_keys))      { -      err = gpgme_get_key (ctx, j_keys->valuestring, &keys[0], 0); -      if (err) -        goto leave; +      strcpy (p, j_keys->valuestring);      }    else      {        for (i=0; i < nkeys; i++)          {            j_item = cJSON_GetArrayItem (j_keys, i); -          err = gpgme_get_key (ctx, j_item->valuestring, &keys[i], 0); -          if (err) -            goto leave; +          if (i) +            *p++ = '\n'; /* Add delimiter.  */ +          p = stpcpy (p, j_item->valuestring);          }      } -  err = 0; -  *r_keys = keys; -  keys = NULL; - - leave: -  if (keys) -    { -      for (i=0; keys[i]; i++) -        gpgme_key_unref (keys[i]); -      xfree (keys); -    } -  return err; +  return 0;  } +  /*   *  GPGME support functions. @@ -582,11 +584,11 @@ op_encrypt (cjson_t request, cjson_t result)    gpgme_ctx_t ctx = NULL;    gpgme_protocol_t protocol;    int opt_base64; -  gpgme_key_t *keys = NULL; +  char *keystring = NULL;    cjson_t j_input;    gpgme_data_t input = NULL;    gpgme_data_t output = NULL; -  int abool, i; +  int abool;    gpgme_encrypt_flags_t encrypt_flags = 0;    if ((err = get_protocol (request, &protocol))) @@ -622,7 +624,7 @@ op_encrypt (cjson_t request, cjson_t result)    /* Get the keys.  */ -  err = get_keys (ctx, request, &keys); +  err = get_keys (request, &keystring);    if (err)      {        /* Provide a custom error response.  */ @@ -674,7 +676,8 @@ op_encrypt (cjson_t request, cjson_t result)      }    /* Encrypt.  */ -  err = gpgme_op_encrypt (ctx, keys, encrypt_flags, input, output); +  err = gpgme_op_encrypt_ext (ctx, NULL, keystring, encrypt_flags, +                              input, output);    /* encrypt_result = gpgme_op_encrypt_result (ctx); */    if (err)      { @@ -713,12 +716,7 @@ op_encrypt (cjson_t request, cjson_t result)      }   leave: -  if (keys) -    { -      for (i=0; keys[i]; i++) -        gpgme_key_unref (keys[i]); -      xfree (keys); -    } +  xfree (keystring);    release_context (ctx);    gpgme_data_release (input);    return err; diff --git a/src/gpgme.def b/src/gpgme.def index cad30f6c..a01d89a2 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -267,5 +267,10 @@ EXPORTS      gpgme_op_conf_dir			  @199 +    gpgme_op_encrypt_ext                  @200 +    gpgme_op_encrypt_ext_start            @201 +    gpgme_op_encrypt_sign_ext             @202 +    gpgme_op_encrypt_sign_ext_start       @203 +  ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index e3198798..8aba5baa 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1274,10 +1274,22 @@ gpgme_encrypt_flags_t;     store the resulting ciphertext in CIPHER.  */  gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],  				      gpgme_encrypt_flags_t flags, -				      gpgme_data_t plain, gpgme_data_t cipher); +				      gpgme_data_t plain, +                                      gpgme_data_t cipher);  gpgme_error_t gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],  				gpgme_encrypt_flags_t flags, -				gpgme_data_t plain, gpgme_data_t cipher); +				gpgme_data_t plain, +                                gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], +                                          const char *recpstring, +                                          gpgme_encrypt_flags_t flags, +                                          gpgme_data_t plain, +                                          gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], +                                    const char *recpstring, +                                    gpgme_encrypt_flags_t flags, +                                    gpgme_data_t plain, +                                    gpgme_data_t cipher);  /* Encrypt plaintext PLAIN within CTX for the recipients RECP and     store the resulting ciphertext in CIPHER.  Also sign the ciphertext @@ -1289,7 +1301,19 @@ gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx,  					   gpgme_data_t cipher);  gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],  				     gpgme_encrypt_flags_t flags, -				     gpgme_data_t plain, gpgme_data_t cipher); +				     gpgme_data_t plain, +                                     gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, +                                               gpgme_key_t recp[], +                                               const char *recpstring, +                                               gpgme_encrypt_flags_t flags, +                                               gpgme_data_t plain, +                                               gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], +                                         const char *recpstring, +                                         gpgme_encrypt_flags_t flags, +                                         gpgme_data_t plain, +                                         gpgme_data_t cipher);  /* diff --git a/src/libgpgme.vers b/src/libgpgme.vers index a95befba..b49c86d9 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -215,10 +215,15 @@ GPGME_1.0 {      gpgme_op_edit;      gpgme_op_edit_start;      gpgme_op_encrypt; -    gpgme_op_encrypt_result; +    gpgme_op_encrypt_start; +    gpgme_op_encrypt_ext; +    gpgme_op_encrypt_ext_start;      gpgme_op_encrypt_sign; +    gpgme_op_encrypt_sign_ext;      gpgme_op_encrypt_sign_start; -    gpgme_op_encrypt_start; +    gpgme_op_encrypt_sign_ext_start; +    gpgme_op_encrypt_result; +      gpgme_op_export;      gpgme_op_export_ext;      gpgme_op_export_ext_start; diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c index 51e2d60f..94084694 100644 --- a/tests/run-encrypt.c +++ b/tests/run-encrypt.c @@ -37,6 +37,19 @@  static int verbose; +static char * +xstrdup (const char *string) +{ +  char *p = strdup (string); +  if (!p) +    { +      fprintf (stderr, "strdup failed\n"); +      exit (2); +    } +  return p; +} + +  static gpg_error_t  status_cb (void *opaque, const char *keyword, const char *value)  { @@ -88,6 +101,7 @@ show_usage (int ex)           "  --uiserver         use the UI server\n"           "  --loopback         use a loopback pinentry\n"           "  --key NAME         encrypt to key NAME\n" +         "  --keystring NAMES  encrypt to ';' delimited NAMES\n"           "  --throw-keyids     use this option\n"           "  --no-symkey-cache  disable the use of that cache\n"           "  --wrap             assume input is valid OpenPGP message\n" @@ -103,7 +117,6 @@ main (int argc, char **argv)    int last_argc = -1;    gpgme_error_t err;    gpgme_ctx_t ctx; -  const char *key_string = NULL;    gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;    gpgme_data_t in, out;    gpgme_encrypt_result_t result; @@ -113,6 +126,7 @@ main (int argc, char **argv)    char *keyargs[10];    gpgme_key_t keys[10+1];    int keycount = 0; +  char *keystring = NULL;    int i;    gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;    gpgme_off_t offset; @@ -174,6 +188,17 @@ main (int argc, char **argv)            keyargs[keycount++] = *argv;            argc--; argv++;          } +      else if (!strcmp (*argv, "--keystring")) +        { +          argc--; argv++; +          if (!argc) +            show_usage (1); +          keystring = xstrdup (*argv); +          for (i=0; keystring[i]; i++) +            if (keystring[i] == ';') +              keystring[i] = '\n'; +          argc--; argv++; +        }        else if (!strcmp (*argv, "--throw-keyids"))          {            flags |= GPGME_ENCRYPT_THROW_KEYIDS; @@ -207,15 +232,6 @@ main (int argc, char **argv)    if (argc != 1)      show_usage (1); -  if (key_string && protocol == GPGME_PROTOCOL_UISERVER) -    { -      fprintf (stderr, PGM ": ignoring --key in UI-server mode\n"); -      key_string = NULL; -    } - -  if (!key_string) -    key_string = "test"; -    init_gpgme (protocol);    err = gpgme_new (&ctx); @@ -298,7 +314,8 @@ main (int argc, char **argv)    err = gpgme_data_new (&out);    fail_if_err (err); -  err = gpgme_op_encrypt (ctx, keycount ? keys : NULL, flags, in, out); +  err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring, +                              flags, in, out);    result = gpgme_op_encrypt_result (ctx);    if (result)      print_result (result); @@ -318,5 +335,6 @@ main (int argc, char **argv)    for (i=0; i < keycount; i++)      gpgme_key_unref (keys[i]);    gpgme_release (ctx); +  free (keystring);    return 0;  } | 
