30 #include <gpg-error.h> 41 #define G_LOG_DOMAIN "util gpgme" 57 log_gpgme (GLogLevelFlags level, gpg_error_t err,
const char *fmt, ...)
62 va_start (arg_ptr, fmt);
63 msg = g_strdup_vprintf (fmt, arg_ptr);
65 if (err && gpg_err_source (err) != GPG_ERR_SOURCE_ANY && gpg_err_source (err))
66 g_log (
G_LOG_DOMAIN, level,
"%s: %s <%s>", msg, gpg_strerror (err),
69 g_log (
G_LOG_DOMAIN, level,
"%s: %s", msg, gpg_strerror (err));
102 gpgme_engine_info_t info;
104 if (!gpgme_check_version (NULL))
106 g_critical (
"gpgme library could not be initialized.");
109 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
111 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
115 g_message (
"Setting GnuPG dir to '%s'", dir);
118 if (access (dir, F_OK))
120 err = gpg_error_from_syserror ();
124 if (mkdir (dir, 0700) == 0)
127 g_message (
"Created GnuPG dir '%s'", dir);
134 err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, dir);
138 log_gpgme (G_LOG_LEVEL_WARNING, err,
"Setting GnuPG dir failed");
143 if (!gpgme_get_engine_info (&info))
145 while (info && info->protocol != GPGME_PROTOCOL_OpenPGP)
151 g_message (
"Using OpenPGP engine version '%s'",
152 info && info->version ? info->version :
"[?]");
161 err = gpgme_new (&ctx);
163 log_gpgme (G_LOG_LEVEL_WARNING, err,
"Creating GPGME context failed");
181 ssize_t key_len, gpgme_data_type_t key_type)
183 gpgme_data_t key_data;
185 gpgme_data_type_t given_key_type;
186 gpgme_import_result_t import_result;
188 gpgme_data_new_from_mem (
189 &key_data, key_str, (key_len >= 0 ? key_len : (ssize_t) strlen (key_str)),
192 given_key_type = gpgme_data_identify (key_data, 0);
193 if (given_key_type != key_type)
196 if (given_key_type == GPGME_DATA_TYPE_INVALID)
199 g_warning (
"%s: key_str is invalid", __FUNCTION__);
204 g_warning (
"%s: key_str is not the expected type: " 205 " expected: %d, got %d",
206 __FUNCTION__, key_type, given_key_type);
208 gpgme_data_release (key_data);
212 err = gpgme_op_import (ctx, key_data);
213 gpgme_data_release (key_data);
216 g_warning (
"%s: Import failed: %s", __FUNCTION__, gpgme_strerror (err));
220 import_result = gpgme_op_import_result (ctx);
221 g_debug (
"%s: %d imported, %d not imported", __FUNCTION__,
222 import_result->imported, import_result->not_imported);
224 gpgme_import_status_t status;
225 status = import_result->imports;
228 if (status->result != GPG_ERR_NO_ERROR)
229 g_warning (
"%s: '%s' could not be imported: %s", __FUNCTION__,
230 status->fpr, gpgme_strerror (status->result));
232 g_debug (
"%s: Imported '%s'", __FUNCTION__, status->fpr);
234 status = status->next;
237 if (import_result->not_imported)
254 gchar *bracket_email;
256 gboolean recipient_found = FALSE;
258 if (uid_email == NULL)
261 bracket_email = g_strdup_printf (
"<%s>", uid_email);
263 gpgme_op_keylist_start (ctx, NULL, 0);
264 gpgme_op_keylist_next (ctx, &key);
265 while (key && recipient_found == FALSE)
267 if (key->can_encrypt)
269 g_debug (
"%s: key '%s' OK for encryption", __FUNCTION__,
274 while (uid && recipient_found == FALSE)
276 g_debug (
"%s: UID email: %s", __FUNCTION__, uid->email);
278 if (strcmp (uid->email, uid_email) == 0
279 || strstr (uid->email, bracket_email))
281 g_message (
"%s: Found matching UID for %s", __FUNCTION__,
283 recipient_found = TRUE;
290 g_debug (
"%s: key '%s' cannot be used for encryption", __FUNCTION__,
294 if (recipient_found == FALSE)
295 gpgme_op_keylist_next (ctx, &key);
302 g_warning (
"%s: No suitable key found for %s", __FUNCTION__, uid_email);
324 const char *key_str, ssize_t key_len,
325 const char *uid_email, gpgme_protocol_t protocol,
326 gpgme_data_type_t data_type)
328 char gpg_temp_dir[] =
"/tmp/gvmd-gpg-XXXXXX";
330 gpgme_data_t plain_data, encrypted_data;
332 gpgme_key_t keys[2] = {NULL, NULL};
334 gpgme_encrypt_flags_t encrypt_flags;
335 const char *key_type_str;
337 if (uid_email == NULL || strcmp (uid_email,
"") == 0)
339 g_warning (
"%s: No email address for user identification given",
344 if (protocol == GPGME_PROTOCOL_CMS)
345 key_type_str =
"certificate";
347 key_type_str =
"public key";
350 if (mkdtemp (gpg_temp_dir) == NULL)
352 g_warning (
"%s: mkdtemp failed\n", __FUNCTION__);
358 if (protocol == GPGME_PROTOCOL_CMS)
359 gpgme_set_armor (ctx, 0);
361 gpgme_set_armor (ctx, 1);
363 gpgme_ctx_set_engine_info (ctx, protocol, NULL, gpg_temp_dir);
364 gpgme_set_protocol (ctx, protocol);
365 encrypt_flags = GPGME_ENCRYPT_ALWAYS_TRUST | GPGME_ENCRYPT_NO_COMPRESS;
370 g_warning (
"%s: Import of %s failed", __FUNCTION__, key_type_str);
380 g_warning (
"%s: Could not find %s for encryption", __FUNCTION__,
389 gpgme_data_new_from_stream (&plain_data, plain_file);
390 gpgme_data_new_from_stream (&encrypted_data, encrypted_file);
392 if (protocol == GPGME_PROTOCOL_CMS)
393 gpgme_data_set_encoding (encrypted_data, GPGME_DATA_ENCODING_BASE64);
396 err = gpgme_op_encrypt (ctx, keys, encrypt_flags, plain_data, encrypted_data);
400 g_warning (
"%s: Encryption failed: %s", __FUNCTION__,
401 gpgme_strerror (err));
402 gpgme_data_release (plain_data);
403 gpgme_data_release (encrypted_data);
409 gpgme_data_release (plain_data);
410 gpgme_data_release (encrypted_data);
432 const char *uid_email,
433 const char *public_key_str,
434 ssize_t public_key_len)
437 plain_file, encrypted_file, public_key_str, public_key_len, uid_email,
438 GPGME_PROTOCOL_OpenPGP, GPGME_DATA_TYPE_PGP_KEY);
456 const char *uid_email,
const char *certificate_str,
457 ssize_t certificate_len)
460 plain_file, encrypted_file, certificate_str, certificate_len, uid_email,
461 GPGME_PROTOCOL_CMS, GPGME_DATA_TYPE_CMS_OTHER);
static int encrypt_stream_internal(FILE *plain_file, FILE *encrypted_file, const char *key_str, ssize_t key_len, const char *uid_email, gpgme_protocol_t protocol, gpgme_data_type_t data_type)
Encrypt a stream for a PGP public key, writing to another stream.
int gvm_gpg_import_from_string(gpgme_ctx_t ctx, const char *key_str, ssize_t key_len, gpgme_data_type_t key_type)
Import a key or certificate given by a string.
int gvm_pgp_pubkey_encrypt_stream(FILE *plain_file, FILE *encrypted_file, const char *uid_email, const char *public_key_str, ssize_t public_key_len)
Encrypt a stream for a PGP public key, writing to another stream.
Protos and data structures for GPGME utilities.
#define G_LOG_DOMAIN
GLib log domain.
int gvm_file_remove_recurse(const gchar *pathname)
Recursively removes files and directories.
gpgme_ctx_t gvm_init_gpgme_ctx_from_dir(const gchar *dir)
Returns a new gpgme context.
int gvm_smime_encrypt_stream(FILE *plain_file, FILE *encrypted_file, const char *uid_email, const char *certificate_str, ssize_t certificate_len)
Encrypt a stream for a S/MIME certificate, writing to another stream.
static gboolean initialized
Flag whether the config file was read.
static gpgme_key_t find_email_encryption_key(gpgme_ctx_t ctx, const char *uid_email)
Find a key that can be used to encrypt for an email recipient.
Protos for file utility functions.
void log_gpgme(GLogLevelFlags level, gpg_error_t err, const char *fmt,...)
Log function with extra gpg-error style output.