27#define G_LOG_DOMAIN "libgvm util"
43log_gpgme (GLogLevelFlags level, gpg_error_t err,
const char *fmt, ...)
48 va_start (arg_ptr, fmt);
49 msg = g_strdup_vprintf (fmt, arg_ptr);
51 if (err && gpg_err_source (err) != GPG_ERR_SOURCE_ANY && gpg_err_source (err))
52 g_log (
G_LOG_DOMAIN, level,
"%s: %s <%s>", msg, gpg_strerror (err),
55 g_log (
G_LOG_DOMAIN, level,
"%s: %s", msg, gpg_strerror (err));
88 gpgme_engine_info_t info;
90 if (!gpgme_check_version (NULL))
92 g_critical (
"gpgme library could not be initialized.");
95 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
97 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
101 g_message (
"Setting GnuPG dir to '%s'", dir);
104 if (access (dir, F_OK))
106 err = gpg_error_from_syserror ();
110 if (mkdir (dir, 0700) == 0)
113 g_message (
"Created GnuPG dir '%s'", dir);
120 err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, dir);
124 log_gpgme (G_LOG_LEVEL_WARNING, err,
"Setting GnuPG dir failed");
129 if (!gpgme_get_engine_info (&info))
131 while (info && info->protocol != GPGME_PROTOCOL_OpenPGP)
137 g_message (
"Using OpenPGP engine version '%s'",
138 info && info->version ? info->version :
"[?]");
147 err = gpgme_new (&ctx);
149 log_gpgme (G_LOG_LEVEL_WARNING, err,
"Creating GPGME context failed");
167 ssize_t key_len, GArray *key_types)
169 gpgme_data_t key_data;
171 gpgme_data_type_t given_key_type;
172 gpgme_import_result_t import_result;
175 gpgme_data_new_from_mem (
176 &key_data, key_str, (key_len >= 0 ? key_len : (ssize_t) strlen (key_str)),
179 given_key_type = gpgme_data_identify (key_data, 0);
181 if (given_key_type == GPGME_DATA_TYPE_INVALID)
184 g_warning (
"%s: key_str is invalid", __func__);
189 for (index = 0; index < key_types->len; index++)
191 if (g_array_index (key_types, gpgme_data_type_t, index)
196 if (index >= key_types->len)
199 GString *expected_buffer = g_string_new (
"");
200 for (index = 0; index < key_types->len; index++)
203 g_string_append (expected_buffer,
" or ");
204 g_string_append_printf (
205 expected_buffer,
"%d",
206 g_array_index (key_types, gpgme_data_type_t, index));
208 g_warning (
"%s: key_str is not the expected type: "
209 " expected: %s, got %d",
210 __func__, expected_buffer->str, given_key_type);
211 g_string_free (expected_buffer, TRUE);
217 gpgme_data_release (key_data);
221 err = gpgme_op_import (ctx, key_data);
222 gpgme_data_release (key_data);
225 g_warning (
"%s: Import failed: %s", __func__, gpgme_strerror (err));
229 import_result = gpgme_op_import_result (ctx);
230 g_debug (
"%s: %d imported, %d not imported", __func__,
231 import_result->imported, import_result->not_imported);
233 gpgme_import_status_t status;
234 status = import_result->imports;
237 if (status->result != GPG_ERR_NO_ERROR)
238 g_warning (
"%s: '%s' could not be imported: %s", __func__, status->fpr,
239 gpgme_strerror (status->result));
241 g_debug (
"%s: Imported '%s'", __func__, status->fpr);
243 status = status->next;
246 if (import_result->not_imported)
265 ssize_t key_len, gpgme_data_type_t key_type)
269 g_array_sized_new (FALSE, FALSE,
sizeof (gpgme_data_type_t), 1);
270 g_array_insert_val (key_types, 0, key_type);
273 g_array_free (key_types, TRUE);
288 gchar *bracket_email;
289 gpgme_key_t key, found_key;
292 if (uid_email == NULL)
295 bracket_email = g_strdup_printf (
"<%s>", uid_email);
297 err = gpgme_op_keylist_start (ctx, NULL, 0);
300 g_free (bracket_email);
301 g_warning (
"gpgme_op_keylist_start failed: %s", gpgme_strerror (err));
305 gpgme_op_keylist_next (ctx, &key);
308 g_free (bracket_email);
309 g_warning (
"gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
316 if (key->can_encrypt)
318 g_debug (
"%s: key '%s' OK for encryption", __func__,
323 while (uid && found_key == NULL)
325 g_debug (
"%s: UID email: %s", __func__, uid->email);
327 if (strcmp (uid->email, uid_email) == 0
328 || strstr (uid->email, bracket_email))
330 g_message (
"%s: Found matching UID for %s", __func__,
339 g_debug (
"%s: key '%s' cannot be used for encryption", __func__,
343 err = gpgme_op_keylist_next (ctx, &key);
344 if (err & GPG_ERR_EOF)
348 g_free (bracket_email);
349 g_warning (
"gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
354 if (found_key == NULL)
355 g_warning (
"%s: No suitable key found for %s", __func__, uid_email);
373 FILE *file = (FILE *) handle;
375 ret = fread (buffer, 1, size, file);
394 FILE *file = (FILE *) handle;
396 ret = fwrite (buffer, 1, size, file);
402#define CHECK_ERR(func) \
405 printf ("%s: %s failed: %s\n", __func__, func, gpgme_strerror (err)); \
426 gchar *trustlist_filename;
427 GString *trustlist_content;
432 gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_CANCEL);
434 trustlist_filename = g_build_filename (homedir,
"trustlist.txt", NULL);
436 trustlist_content = g_string_new (
"");
438 err = gpgme_op_keylist_start (ctx, NULL, 0);
440 gpgme_op_keylist_next (ctx, &key);
444 g_string_append_printf (trustlist_content,
"%s S\n", key->fpr);
445 err = gpgme_op_keylist_next (ctx, &key);
446 if (err & GPG_ERR_EOF)
452 if (g_file_set_contents (trustlist_filename, trustlist_content->str,
453 trustlist_content->len, &error)
456 g_warning (
"%s: Could not write trust list: %s", __func__,
458 g_free (trustlist_filename);
459 g_string_free (trustlist_content, TRUE);
463 g_free (trustlist_filename);
464 g_string_free (trustlist_content, TRUE);
470#define CHECK_ERR(func) \
473 printf ("%s: %s failed: %s\n", __func__, func, gpgme_strerror (err)); \
475 gpgme_data_release (plain_data); \
476 if (encrypted_data) \
477 gpgme_data_release (encrypted_data); \
479 gpgme_release (ctx); \
480 gvm_file_remove_recurse (gpg_temp_dir); \
501 const char *key_str, ssize_t key_len,
502 const char *uid_email, gpgme_protocol_t protocol,
505 char gpg_temp_dir[] =
"/tmp/gvmd-gpg-XXXXXX";
507 gpgme_data_t plain_data, encrypted_data;
509 gpgme_key_t keys[2] = {NULL, NULL};
511 gpgme_encrypt_flags_t encrypt_flags;
512 const char *key_type_str;
513 struct gpgme_data_cbs callbacks;
517 encrypted_data = NULL;
519 if (uid_email == NULL || strcmp (uid_email,
"") == 0)
521 g_warning (
"%s: No email address for user identification given",
526 if (gpgme_check_version (NULL) == NULL)
528 g_warning (
"%s: gpgme_check_version failed", __func__);
532 if (protocol == GPGME_PROTOCOL_CMS)
533 key_type_str =
"certificate";
535 key_type_str =
"public key";
538 if (mkdtemp (gpg_temp_dir) == NULL)
540 g_warning (
"%s: mkdtemp failed\n", __func__);
544 err = gpgme_new (&ctx);
547 if (protocol == GPGME_PROTOCOL_CMS)
548 gpgme_set_armor (ctx, 0);
550 gpgme_set_armor (ctx, 1);
552 err = gpgme_ctx_set_engine_info (ctx, protocol, NULL, gpg_temp_dir);
555 err = gpgme_set_protocol (ctx, protocol);
558 err = gpgme_set_keylist_mode (ctx, GPGME_KEYLIST_MODE_LOCAL);
561 gpgme_set_offline (ctx, 1);
563 encrypt_flags = GPGME_ENCRYPT_ALWAYS_TRUST | GPGME_ENCRYPT_NO_COMPRESS;
568 g_warning (
"%s: Import of %s failed", __func__, key_type_str);
578 g_warning (
"%s: Could not find %s for encryption", __func__,
587 err = gpgme_data_new_from_stream (&plain_data, plain_file);
588 CHECK_ERR (
"gpgme_data_new_from_stream for plain text")
594 memset (&callbacks, 0,
sizeof (callbacks));
597 err = gpgme_data_new_from_cbs (&encrypted_data, &callbacks, encrypted_file);
598 CHECK_ERR (
"gpgme_data_new_from_stream for encrypted text")
600 if (protocol == GPGME_PROTOCOL_CMS)
602 gpgme_data_set_encoding (encrypted_data, GPGME_DATA_ENCODING_BASE64);
606 gpgme_data_release (plain_data);
607 gpgme_data_release (encrypted_data);
615 err = gpgme_op_encrypt (ctx, keys, encrypt_flags, plain_data, encrypted_data);
618 gpgme_data_release (plain_data);
619 gpgme_data_release (encrypted_data);
641 const char *uid_email,
642 const char *public_key_str,
643 ssize_t public_key_len)
646 const gpgme_data_type_t types_ptr[1] = {GPGME_DATA_TYPE_PGP_KEY};
647 GArray *key_types = g_array_new (FALSE, FALSE,
sizeof (gpgme_data_type_t));
649 g_array_append_vals (key_types, types_ptr, 1);
651 public_key_len, uid_email,
652 GPGME_PROTOCOL_OpenPGP, key_types);
653 g_array_free (key_types, TRUE);
673 const char *uid_email,
const char *certificate_str,
674 ssize_t certificate_len)
677 const gpgme_data_type_t types_ptr[2] = {GPGME_DATA_TYPE_X509_CERT,
678 GPGME_DATA_TYPE_CMS_OTHER};
679 GArray *key_types = g_array_new (FALSE, FALSE,
sizeof (gpgme_data_type_t));
681 g_array_append_vals (key_types, types_ptr, 2);
683 certificate_len, uid_email, GPGME_PROTOCOL_CMS,
685 g_array_free (key_types, TRUE);
#define G_LOG_DOMAIN
GLib log domain.
static gboolean initialized
Flag whether the config file was read.
int gvm_file_remove_recurse(const gchar *pathname)
Recursively removes files and directories.
Protos for file utility functions.
static int create_all_certificates_trustlist(gpgme_ctx_t ctx, const char *homedir)
Adds a trust list of all current certificates to a GPG homedir.
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.
static ssize_t gvm_gpgme_fread(void *handle, void *buffer, size_t size)
Wrapper for fread for use as a GPGME callback.
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.
int gvm_gpg_import_many_types_from_string(gpgme_ctx_t ctx, const char *key_str, ssize_t key_len, GArray *key_types)
Import a key or certificate given by a string.
gpgme_ctx_t gvm_init_gpgme_ctx_from_dir(const gchar *dir)
Returns a new gpgme context.
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.
static ssize_t gvm_gpgme_fwrite(void *handle, const void *buffer, size_t size)
Wrapper for fread for use as a GPGME callback.
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.
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, GArray *key_types)
Encrypt a stream for a PGP public key, writing to another stream.
void log_gpgme(GLogLevelFlags level, gpg_error_t err, const char *fmt,...)
Log function with extra gpg-error style output.
Protos and data structures for GPGME utilities.