Merge branch 'master' into javascript-binding
This commit is contained in:
commit
e38b8beb20
7
NEWS
7
NEWS
@ -1,6 +1,13 @@
|
||||
Noteworthy changes in version 1.11.2 (unreleased)
|
||||
-------------------------------------------------
|
||||
|
||||
* Even for old versions of gpg a missing MDC will now lead to a
|
||||
decryption failure.
|
||||
|
||||
* Interface changes relative to the 1.11.1 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
cpp: DecryptionResult::sessionKey NEW.
|
||||
cpp: DecryptionResult::symkeyAlgo NEW.
|
||||
|
||||
Noteworthy changes in version 1.11.1 (2018-04-20)
|
||||
-------------------------------------------------
|
||||
|
@ -5408,7 +5408,7 @@ or @code{gpgme_get_ctx_flag (ctx, "export-session-key")} returns true
|
||||
@since{1.11.0}
|
||||
|
||||
A string with the symmetric encryption algorithm and mode using the
|
||||
format "<algo>.<mode>". Note that old non-MDC encryption mode of
|
||||
format "<algo>.<mode>". Note that the deprecated non-MDC encryption mode of
|
||||
OpenPGP is given as "PGPCFB".
|
||||
|
||||
@end table
|
||||
|
@ -155,6 +155,16 @@ std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipie
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *GpgME::DecryptionResult::sessionKey() const
|
||||
{
|
||||
return d ? d->res.session_key : nullptr;
|
||||
}
|
||||
|
||||
const char *GpgME::DecryptionResult::symkeyAlgo() const
|
||||
{
|
||||
return d ? d->res.symkey_algo : nullptr;
|
||||
}
|
||||
|
||||
class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient
|
||||
{
|
||||
public:
|
||||
@ -231,6 +241,7 @@ std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result
|
||||
<< "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm())
|
||||
<< "\n isWrongKeyUsage: " << result.isWrongKeyUsage()
|
||||
<< "\n isDeVs " << result.isDeVs()
|
||||
<< "\n symkeyAlgo: " << protect(result.symkeyAlgo())
|
||||
<< "\n recipients:\n";
|
||||
const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
|
||||
std::copy(recipients.begin(), recipients.end(),
|
||||
|
@ -77,6 +77,10 @@ public:
|
||||
|
||||
const char *fileName() const;
|
||||
|
||||
const char *sessionKey() const;
|
||||
|
||||
const char *symkeyAlgo() const;
|
||||
|
||||
class Recipient;
|
||||
|
||||
unsigned int numRecipients() const;
|
||||
|
@ -14,7 +14,7 @@
|
||||
:CUSTOM_ID: intro
|
||||
:END:
|
||||
|
||||
| Version: | 0.1.0 |
|
||||
| Version: | 0.1.1 |
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
| Language: | Australian English, British English |
|
||||
@ -673,10 +673,17 @@
|
||||
newfile = input("Enter path and filename of file to save decrypted data to: ")
|
||||
|
||||
with open(ciphertext, "rb") as cfile:
|
||||
plaintext, result, verify_result = gpg.Context().decrypt(cfile)
|
||||
try:
|
||||
plaintext, result, verify_result = gpg.Context().decrypt(cfile)
|
||||
except gpg.errors.GPGMEError as e:
|
||||
plaintext = None
|
||||
print(e)
|
||||
|
||||
with open(newfile, "wb") as nfile:
|
||||
nfile.write(plaintext)
|
||||
if plaintext is not None:
|
||||
with open(newfile, "wb") as nfile:
|
||||
nfile.write(plaintext)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
|
||||
The data available in =plaintext= in this example is the decrypted
|
||||
|
@ -38,7 +38,14 @@ else:
|
||||
newfile = input("Enter path and filename of file to save decrypted data to: ")
|
||||
|
||||
with open(ciphertext, "rb") as cfile:
|
||||
plaintext, result, verify_result = gpg.Context().decrypt(cfile)
|
||||
try:
|
||||
plaintext, result, verify_result = gpg.Context().decrypt(cfile)
|
||||
except gpg.errors.GPGMEError as e:
|
||||
plaintext = None
|
||||
print(e)
|
||||
|
||||
with open(newfile, "wb") as nfile:
|
||||
nfile.write(plaintext)
|
||||
if plaintext is not None:
|
||||
with open(newfile, "wb") as nfile:
|
||||
nfile.write(plaintext)
|
||||
else:
|
||||
pass
|
||||
|
@ -56,6 +56,11 @@ typedef struct
|
||||
* message that the general DECRYPTION_FAILED. */
|
||||
int any_no_seckey;
|
||||
|
||||
/* If the engine emits a DECRYPTION_INFO status and that does not
|
||||
* indicate that an integrity proetction mode is active, this flag
|
||||
* is set. */
|
||||
int not_integrity_protected;
|
||||
|
||||
/* A pointer to the next pointer of the last recipient in the list.
|
||||
This makes appending new invalid signers painless while
|
||||
preserving the order. */
|
||||
@ -280,7 +285,7 @@ parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
|
||||
char *field[3];
|
||||
int nfields;
|
||||
char *args2;
|
||||
int mdc, mode;
|
||||
int mdc, aead_algo;
|
||||
const char *algostr, *modestr;
|
||||
|
||||
if (!args)
|
||||
@ -296,19 +301,22 @@ parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
|
||||
|
||||
mdc = atoi (field[0]);
|
||||
algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
|
||||
mode = nfields < 3? 0 : atoi (field[2]);
|
||||
modestr = _gpgme_cipher_mode_name (mode, protocol);
|
||||
aead_algo = nfields < 3? 0 : atoi (field[2]);
|
||||
modestr = _gpgme_cipher_mode_name (aead_algo, protocol);
|
||||
|
||||
free (args2);
|
||||
|
||||
free (opd->result.symkey_algo);
|
||||
if (!mode && mdc != 2)
|
||||
if (!aead_algo && mdc != 2)
|
||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
|
||||
else
|
||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
|
||||
if (!opd->result.symkey_algo)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
if (!mdc && !aead_algo)
|
||||
opd->not_integrity_protected = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -338,13 +346,18 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_EOF:
|
||||
/* FIXME: These error values should probably be attributed to
|
||||
the underlying crypto engine (as error source). */
|
||||
/* We force an encryption failure if we know that integrity
|
||||
* protection is missing. For modern version of gpg using
|
||||
* modern cipher algorithms this is not required because gpg
|
||||
* will issue a failure anyway. However older gpg versions emit
|
||||
* only a warning.
|
||||
* Fixme: These error values should probably be attributed to
|
||||
* the underlying crypto engine (as error source). */
|
||||
if (opd->failed && opd->pkdecrypt_failed)
|
||||
return opd->pkdecrypt_failed;
|
||||
else if (opd->failed && opd->any_no_seckey)
|
||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
||||
else if (opd->failed)
|
||||
else if (opd->failed || opd->not_integrity_protected)
|
||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||
else if (!opd->okay)
|
||||
return gpg_error (GPG_ERR_NO_DATA);
|
||||
|
395
src/gpgme-json.c
395
src/gpgme-json.c
@ -147,6 +147,16 @@ xjson_CreateObject (void)
|
||||
return json;
|
||||
}
|
||||
|
||||
/* Call cJSON_CreateArray but terminate in case of an error. */
|
||||
static cjson_t
|
||||
xjson_CreateArray (void)
|
||||
{
|
||||
cjson_t json = cJSON_CreateArray ();
|
||||
if (!json)
|
||||
xoutofcore ("cJSON_CreateArray");
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper around cJSON_AddStringToObject which returns an gpg-error
|
||||
* code instead of the NULL or the new object. */
|
||||
@ -490,7 +500,7 @@ _create_new_context (gpgme_protocol_t proto)
|
||||
|
||||
|
||||
/* Return a context object for protocol PROTO. This is currently a
|
||||
* statuically allocated context initialized for PROTO. Termnates
|
||||
* statically allocated context initialized for PROTO. Terminates
|
||||
* process on failure. */
|
||||
static gpgme_ctx_t
|
||||
get_context (gpgme_protocol_t proto)
|
||||
@ -590,6 +600,187 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json)
|
||||
}
|
||||
|
||||
|
||||
/* Helper for summary formatting */
|
||||
static void
|
||||
add_summary_to_object (cjson_t result, gpgme_sigsum_t summary)
|
||||
{
|
||||
cjson_t response = xjson_CreateArray ();
|
||||
if ( (summary & GPGME_SIGSUM_VALID ))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("valid"));
|
||||
if ( (summary & GPGME_SIGSUM_GREEN ))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("green"));
|
||||
if ( (summary & GPGME_SIGSUM_RED ))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("red"));
|
||||
if ( (summary & GPGME_SIGSUM_KEY_REVOKED))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("revoked"));
|
||||
if ( (summary & GPGME_SIGSUM_KEY_EXPIRED))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("key-expired"));
|
||||
if ( (summary & GPGME_SIGSUM_SIG_EXPIRED))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("sig-expired"));
|
||||
if ( (summary & GPGME_SIGSUM_KEY_MISSING))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("key-missing"));
|
||||
if ( (summary & GPGME_SIGSUM_CRL_MISSING))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("crl-missing"));
|
||||
if ( (summary & GPGME_SIGSUM_CRL_TOO_OLD))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("crl-too-old"));
|
||||
if ( (summary & GPGME_SIGSUM_BAD_POLICY ))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("bad-policy"));
|
||||
if ( (summary & GPGME_SIGSUM_SYS_ERROR ))
|
||||
cJSON_AddItemToArray (response,
|
||||
cJSON_CreateString ("sys-error"));
|
||||
|
||||
cJSON_AddItemToObject (result, "summary", response);
|
||||
}
|
||||
|
||||
|
||||
/* Helper for summary formatting */
|
||||
static const char *
|
||||
validity_to_string (gpgme_validity_t val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case GPGME_VALIDITY_UNDEFINED:return "undefined";
|
||||
case GPGME_VALIDITY_NEVER: return "never";
|
||||
case GPGME_VALIDITY_MARGINAL: return "marginal";
|
||||
case GPGME_VALIDITY_FULL: return "full";
|
||||
case GPGME_VALIDITY_ULTIMATE: return "ultimate";
|
||||
case GPGME_VALIDITY_UNKNOWN:
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Add a single signature to a result */
|
||||
static gpg_error_t
|
||||
add_signature_to_object (cjson_t result, gpgme_signature_t sig)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
|
||||
if (!cJSON_AddStringToObject (result, "status", gpgme_strerror (sig->status)))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!cJSON_AddNumberToObject (result, "code", sig->status))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
add_summary_to_object (result, sig->summary);
|
||||
|
||||
if (!cJSON_AddStringToObject (result, "fingerprint", sig->fpr))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!cJSON_AddNumberToObject (result, "created", sig->timestamp))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!cJSON_AddNumberToObject (result, "expired", sig->exp_timestamp))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!cJSON_AddStringToObject (result, "validity",
|
||||
validity_to_string (sig->validity)))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
leave:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Add multiple signatures as an array to a result */
|
||||
static gpg_error_t
|
||||
add_signatures_to_object (cjson_t result, gpgme_signature_t signatures)
|
||||
{
|
||||
cjson_t response = xjson_CreateArray ();
|
||||
gpg_error_t err = 0;
|
||||
gpgme_signature_t sig;
|
||||
|
||||
for (sig = signatures; sig; sig = sig->next)
|
||||
{
|
||||
cjson_t sig_obj = xjson_CreateObject ();
|
||||
err = add_signature_to_object (sig_obj, sig);
|
||||
if (err)
|
||||
{
|
||||
cJSON_Delete (sig_obj);
|
||||
sig_obj = NULL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray (response, sig_obj);
|
||||
}
|
||||
|
||||
if (!cJSON_AddItemToObject (result, "signatures", response))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
cJSON_Delete (response);
|
||||
response = NULL;
|
||||
return err;
|
||||
}
|
||||
response = NULL;
|
||||
|
||||
leave:
|
||||
if (err && response)
|
||||
{
|
||||
cJSON_Delete (response);
|
||||
response = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Add an array of signature informations under the name "name". */
|
||||
static gpg_error_t
|
||||
add_signatures_object (cjson_t result, const char *name,
|
||||
gpgme_verify_result_t verify_result)
|
||||
{
|
||||
cjson_t response = xjson_CreateObject ();
|
||||
gpg_error_t err = 0;
|
||||
|
||||
err = add_signatures_to_object (response, verify_result->signatures);
|
||||
|
||||
if (err)
|
||||
{
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!cJSON_AddItemToObject (result, name, response))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
leave:
|
||||
if (err)
|
||||
{
|
||||
cJSON_Delete (response);
|
||||
response = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of the commands.
|
||||
@ -597,11 +788,11 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json)
|
||||
|
||||
|
||||
/* Create a "data" object and the "type", "base64" and "more" flags
|
||||
* from DATA and append them to RESULT. Ownership if DATA is
|
||||
* from DATA and append them to RESULT. Ownership of DATA is
|
||||
* transferred to this function. TYPE must be a fixed string.
|
||||
* CHUNKSIZE is the chunksize requested from the caller. If BASE64 is
|
||||
* -1 the need for base64 encoding is determined by the content of
|
||||
* DATA, all other values are take as rtue or false. Note that
|
||||
* DATA, all other values are taken as true or false. Note that
|
||||
* op_getmore has similar code but works on PENDING_DATA which is set
|
||||
* here. */
|
||||
static gpg_error_t
|
||||
@ -884,6 +1075,7 @@ op_decrypt (cjson_t request, cjson_t result)
|
||||
gpgme_data_t input = NULL;
|
||||
gpgme_data_t output = NULL;
|
||||
gpgme_decrypt_result_t decrypt_result;
|
||||
gpgme_verify_result_t verify_result;
|
||||
|
||||
if ((err = get_protocol (request, &protocol)))
|
||||
goto leave;
|
||||
@ -952,9 +1144,27 @@ op_decrypt (cjson_t request, cjson_t result)
|
||||
if (decrypt_result->is_mime)
|
||||
xjson_AddBoolToObject (result, "mime", 1);
|
||||
|
||||
verify_result = gpgme_op_verify_result (ctx);
|
||||
if (verify_result && verify_result->signatures)
|
||||
{
|
||||
err = add_signatures_object (result, "info", verify_result);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Info output failed: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = make_data_object (result, output, chunksize, "plaintext", -1);
|
||||
output = NULL;
|
||||
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Plaintext output failed: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
leave:
|
||||
release_context (ctx);
|
||||
gpgme_data_release (input);
|
||||
@ -963,6 +1173,182 @@ op_decrypt (cjson_t request, cjson_t result)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_sign[] =
|
||||
"op: \"sign\"\n"
|
||||
"keys: Array of strings with the fingerprints of the signing key.\n"
|
||||
" For a single key a String may be used instead of an array.\n"
|
||||
"data: Input data. \n"
|
||||
"\n"
|
||||
"Optional parameters:\n"
|
||||
"protocol: Either \"openpgp\" (default) or \"cms\".\n"
|
||||
"chunksize: Max number of bytes in the resulting \"data\".\n"
|
||||
"sender: The mail address of the sender.\n"
|
||||
"mode: A string with the signing mode can be:\n"
|
||||
" detached (default)\n"
|
||||
" opaque\n"
|
||||
" clearsign\n"
|
||||
"\n"
|
||||
"Optional boolean flags (default is false):\n"
|
||||
"base64: Input data is base64 encoded.\n"
|
||||
"armor: Request output in armored format.\n"
|
||||
"\n"
|
||||
"Response on success:\n"
|
||||
"type: \"signature\"\n"
|
||||
"data: Unless armor mode is used a Base64 encoded binary\n"
|
||||
" signature. In armor mode a string with an armored\n"
|
||||
" OpenPGP or a PEM message.\n"
|
||||
"base64: Boolean indicating whether data is base64 encoded.\n"
|
||||
"more: Optional boolean indicating that \"getmore\" is required.";
|
||||
static gpg_error_t
|
||||
op_sign (cjson_t request, cjson_t result)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gpgme_ctx_t ctx = NULL;
|
||||
gpgme_protocol_t protocol;
|
||||
size_t chunksize;
|
||||
int opt_base64;
|
||||
char *keystring = NULL;
|
||||
cjson_t j_input;
|
||||
gpgme_data_t input = NULL;
|
||||
gpgme_data_t output = NULL;
|
||||
int abool;
|
||||
cjson_t j_tmp;
|
||||
gpgme_sig_mode_t mode = GPGME_SIG_MODE_DETACH;
|
||||
gpgme_ctx_t keylist_ctx = NULL;
|
||||
gpgme_key_t key = NULL;
|
||||
|
||||
if ((err = get_protocol (request, &protocol)))
|
||||
goto leave;
|
||||
ctx = get_context (protocol);
|
||||
if ((err = get_chunksize (request, &chunksize)))
|
||||
goto leave;
|
||||
|
||||
if ((err = get_boolean_flag (request, "base64", 0, &opt_base64)))
|
||||
goto leave;
|
||||
|
||||
if ((err = get_boolean_flag (request, "armor", 0, &abool)))
|
||||
goto leave;
|
||||
gpgme_set_armor (ctx, abool);
|
||||
|
||||
j_tmp = cJSON_GetObjectItem (request, "mode");
|
||||
if (j_tmp && cjson_is_string (j_tmp))
|
||||
{
|
||||
if (!strcmp (j_tmp->valuestring, "opaque"))
|
||||
{
|
||||
mode = GPGME_SIG_MODE_NORMAL;
|
||||
}
|
||||
else if (!strcmp (j_tmp->valuestring, "clearsign"))
|
||||
{
|
||||
mode = GPGME_SIG_MODE_CLEAR;
|
||||
}
|
||||
}
|
||||
|
||||
j_tmp = cJSON_GetObjectItem (request, "sender");
|
||||
if (j_tmp && cjson_is_string (j_tmp))
|
||||
{
|
||||
gpgme_set_sender (ctx, j_tmp->valuestring);
|
||||
}
|
||||
|
||||
/* Get the keys. */
|
||||
err = get_keys (request, &keystring);
|
||||
if (err)
|
||||
{
|
||||
/* Provide a custom error response. */
|
||||
error_object (result, "Error getting keys: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Do a keylisting and add the keys */
|
||||
if ((err = gpgme_new (&keylist_ctx)))
|
||||
goto leave;
|
||||
gpgme_set_protocol (keylist_ctx, protocol);
|
||||
gpgme_set_keylist_mode (keylist_ctx, GPGME_KEYLIST_MODE_LOCAL);
|
||||
|
||||
err = gpgme_op_keylist_start (ctx, keystring, 1);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error listing keys: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
while (!(err = gpgme_op_keylist_next (ctx, &key)))
|
||||
{
|
||||
if ((err = gpgme_signers_add (ctx, key)))
|
||||
{
|
||||
error_object (result, "Error adding signer: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
gpgme_key_unref (key);
|
||||
}
|
||||
|
||||
/* Get the data. Note that INPUT is a shallow data object with the
|
||||
* storage hold in REQUEST. */
|
||||
j_input = cJSON_GetObjectItem (request, "data");
|
||||
if (!j_input)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
goto leave;
|
||||
}
|
||||
if (!cjson_is_string (j_input))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
if (opt_base64)
|
||||
{
|
||||
err = data_from_base64_string (&input, j_input);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error decoding Base-64 encoded 'data': %s",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gpgme_data_new_from_mem (&input, j_input->valuestring,
|
||||
strlen (j_input->valuestring), 0);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error getting 'data': %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create an output data object. */
|
||||
err = gpgme_data_new (&output);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error creating output data object: %s",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Sign. */
|
||||
err = gpgme_op_sign (ctx, input, output, mode);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Signing failed: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
gpgme_data_release (input);
|
||||
input = NULL;
|
||||
|
||||
/* We need to base64 if armoring has not been requested. */
|
||||
err = make_data_object (result, output, chunksize,
|
||||
"ciphertext", !gpgme_get_armor (ctx));
|
||||
output = NULL;
|
||||
|
||||
leave:
|
||||
xfree (keystring);
|
||||
release_context (ctx);
|
||||
release_context (keylist_ctx);
|
||||
gpgme_data_release (input);
|
||||
gpgme_data_release (output);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static const char hlp_getmore[] =
|
||||
"op: \"getmore\"\n"
|
||||
@ -1058,6 +1444,8 @@ static const char hlp_help[] =
|
||||
"returned. To list all operations it is allowed to leave out \"op\" in\n"
|
||||
"help mode. Supported values for \"op\" are:\n\n"
|
||||
" encrypt Encrypt data.\n"
|
||||
" decrypt Decrypt data.\n"
|
||||
" sign Sign data.\n"
|
||||
" getmore Retrieve remaining data.\n"
|
||||
" help Help overview.";
|
||||
static gpg_error_t
|
||||
@ -1098,6 +1486,7 @@ process_request (const char *request)
|
||||
} optbl[] = {
|
||||
{ "encrypt", op_encrypt, hlp_encrypt },
|
||||
{ "decrypt", op_decrypt, hlp_decrypt },
|
||||
{ "sign", op_sign, hlp_sign },
|
||||
{ "getmore", op_getmore, hlp_getmore },
|
||||
{ "help", op_help, hlp_help },
|
||||
{ NULL }
|
||||
|
@ -72,6 +72,17 @@
|
||||
# define F_OK 0
|
||||
#endif
|
||||
|
||||
/* The Registry key used by GNUPG. */
|
||||
#ifdef _WIN64
|
||||
# define GNUPG_REGKEY_2 "Software\\Wow6432Node\\GNU\\GnuPG"
|
||||
#else
|
||||
# define GNUPG_REGKEY_2 "Software\\GNU\\GnuPG"
|
||||
#endif
|
||||
#ifdef _WIN64
|
||||
# define GNUPG_REGKEY_3 "Software\\Wow6432Node\\GnuPG"
|
||||
#else
|
||||
# define GNUPG_REGKEY_3 "Software\\GnuPG"
|
||||
#endif
|
||||
|
||||
DEFINE_STATIC_LOCK (get_path_lock);
|
||||
|
||||
@ -513,7 +524,7 @@ _gpgme_get_gpg_path (void)
|
||||
char *dir;
|
||||
|
||||
dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
|
||||
"Software\\GNU\\GnuPG",
|
||||
GNUPG_REGKEY_2,
|
||||
"Install Directory");
|
||||
if (dir)
|
||||
{
|
||||
@ -568,12 +579,12 @@ _gpgme_get_gpgconf_path (void)
|
||||
char *dir;
|
||||
|
||||
dir = read_w32_registry_string (NULL,
|
||||
"Software\\GNU\\GnuPG",
|
||||
GNUPG_REGKEY_2,
|
||||
"Install Directory");
|
||||
if (!dir)
|
||||
{
|
||||
char *tmp = read_w32_registry_string (NULL,
|
||||
"Software\\GnuPG",
|
||||
GNUPG_REGKEY_3,
|
||||
"Install Directory");
|
||||
if (tmp)
|
||||
{
|
||||
@ -596,6 +607,14 @@ _gpgme_get_gpgconf_path (void)
|
||||
gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
|
||||
}
|
||||
|
||||
/* 5. Try to find gpgconf.exe relative to us. */
|
||||
if (!gpgconf && inst_dir)
|
||||
{
|
||||
char *dir = _gpgme_strconcat (inst_dir, "\\..\\..\\GnuPG\\bin");
|
||||
gpgconf = find_program_in_dir (dir, name);
|
||||
free (dir);
|
||||
}
|
||||
|
||||
/* 5. Print a debug message if not found. */
|
||||
if (!gpgconf)
|
||||
_gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",name);
|
||||
|
Loading…
Reference in New Issue
Block a user