comparison mcabber/mcabber/pgp.c @ 2196:8811fe9d6ef0

Improve support for GnuPG v2+ If the gnupg engine detected is not 1.x, do not check the environment variable GPG_AGENT_INFO and do not set up a password callback.
author Mikael Berthe <mikael@lilotux.net>
date Wed, 07 Oct 2015 21:58:38 +0200
parents 40ddaebeb81e
children fec172dbacc7
comparison
equal deleted inserted replaced
2195:40ddaebeb81e 2196:8811fe9d6ef0
36 36
37 #define MIN_GPGME_VERSION "1.0.0" 37 #define MIN_GPGME_VERSION "1.0.0"
38 38
39 static struct gpg_struct 39 static struct gpg_struct
40 { 40 {
41 int enabled; 41 int enabled;
42 int version1;
42 char *private_key; 43 char *private_key;
43 char *passphrase; 44 char *passphrase;
44 } gpg; 45 } gpg;
45 46
46 47
51 // if not it returns the gpgme error code. 52 // if not it returns the gpgme error code.
52 int gpg_init(const char *priv_key, const char *passphrase) 53 int gpg_init(const char *priv_key, const char *passphrase)
53 { 54 {
54 gpgme_error_t err; 55 gpgme_error_t err;
55 56
57 gpgme_ctx_t ctx;
58 gpgme_engine_info_t info;
59
56 // Check for version and OpenPGP protocol support. 60 // Check for version and OpenPGP protocol support.
57 if (!gpgme_check_version(MIN_GPGME_VERSION)) { 61 if (!gpgme_check_version(MIN_GPGME_VERSION)) {
58 scr_LogPrint(LPRINT_LOGNORM, 62 scr_LogPrint(LPRINT_LOGNORM,
59 "GPGME initialization error: Bad library version"); 63 "GPGME initialization error: Bad library version");
60 return -1; 64 return -1;
73 77
74 // Store private data. 78 // Store private data.
75 gpg_set_private_key(priv_key); 79 gpg_set_private_key(priv_key);
76 gpg_set_passphrase(passphrase); 80 gpg_set_passphrase(passphrase);
77 81
82 err = gpgme_new(&ctx);
83 if (err) return -1;
84
85 // Check OpenPGP engine version; with version 2+ the agent is mandatory
86 // and we do not manage the passphrase.
87 gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
88 if (err) return -1;
89
90 err = gpgme_get_engine_info (&info);
91 if (!err) {
92 while (info && info->protocol != gpgme_get_protocol (ctx))
93 info = info->next;
94
95 if (info && info->version) {
96 if (!strncmp(info->version, "1.", 2))
97 gpg.version1 = TRUE;
98 scr_log_print(LPRINT_DEBUG, "GPGME: Engine version is '%s'.",
99 info->version);
100 }
101 }
102
78 gpg.enabled = 1; 103 gpg.enabled = 1;
79 return 0; 104 return 0;
105 }
106
107 // gpg_is_version1()
108 // Return TRUE if the GnuPG OpenPGP engine version is 1.x
109 int gpg_is_version1(void)
110 {
111 return gpg.version1;
80 } 112 }
81 113
82 // gpg_terminate() 114 // gpg_terminate()
83 // Destroy data and free memory. 115 // Destroy data and free memory.
84 void gpg_terminate(void) 116 void gpg_terminate(void)
262 // The returned string must be freed with g_free() after use. 294 // The returned string must be freed with g_free() after use.
263 char *gpg_sign(const char *gpg_data) 295 char *gpg_sign(const char *gpg_data)
264 { 296 {
265 gpgme_ctx_t ctx; 297 gpgme_ctx_t ctx;
266 gpgme_data_t in, out; 298 gpgme_data_t in, out;
267 char *p;
268 char *signed_data = NULL; 299 char *signed_data = NULL;
269 size_t nread; 300 size_t nread;
270 gpgme_key_t key; 301 gpgme_key_t key;
271 gpgme_error_t err; 302 gpgme_error_t err;
272 303
282 313
283 gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP); 314 gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
284 gpgme_set_textmode(ctx, 0); 315 gpgme_set_textmode(ctx, 0);
285 gpgme_set_armor(ctx, 1); 316 gpgme_set_armor(ctx, 1);
286 317
287 p = getenv("GPG_AGENT_INFO"); 318 if (gpg.version1) {
288 if (!(p && strchr(p, ':'))) 319 // GPG_AGENT_INFO isn't used by GnuPG version 2+
289 gpgme_set_passphrase_cb(ctx, passphrase_cb, 0); 320 char *p = getenv("GPG_AGENT_INFO");
321 if (!(p && strchr(p, ':')))
322 gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
323 }
290 324
291 err = gpgme_get_key(ctx, gpg.private_key, &key, 1); 325 err = gpgme_get_key(ctx, gpg.private_key, &key, 1);
292 if (err || !key) { 326 if (err || !key) {
293 scr_LogPrint(LPRINT_LOGNORM, "GPGME error: private key not found"); 327 scr_LogPrint(LPRINT_LOGNORM, "GPGME error: private key not found");
294 gpgme_release(ctx); 328 gpgme_release(ctx);
330 // The returned string must be freed with g_free() after use. 364 // The returned string must be freed with g_free() after use.
331 char *gpg_decrypt(const char *gpg_data) 365 char *gpg_decrypt(const char *gpg_data)
332 { 366 {
333 gpgme_ctx_t ctx; 367 gpgme_ctx_t ctx;
334 gpgme_data_t in, out; 368 gpgme_data_t in, out;
335 char *p, *data; 369 char *data;
336 char *decrypted_data = NULL; 370 char *decrypted_data = NULL;
337 size_t nread; 371 size_t nread;
338 gpgme_error_t err; 372 gpgme_error_t err;
339 const char prefix[] = "-----BEGIN PGP MESSAGE-----\n\n"; 373 const char prefix[] = "-----BEGIN PGP MESSAGE-----\n\n";
340 const char suffix[] = "\n-----END PGP MESSAGE-----\n"; 374 const char suffix[] = "\n-----END PGP MESSAGE-----\n";
349 return NULL; 383 return NULL;
350 } 384 }
351 385
352 gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP); 386 gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
353 387
354 p = getenv("GPG_AGENT_INFO"); 388 if (gpg.version1) {
355 if (!(p && strchr(p, ':'))) 389 // GPG_AGENT_INFO isn't used by GnuPG version 2+
356 gpgme_set_passphrase_cb(ctx, passphrase_cb, 0); 390 char *p = getenv("GPG_AGENT_INFO");
391 if (!(p && strchr(p, ':')))
392 gpgme_set_passphrase_cb(ctx, passphrase_cb, 0);
393 }
357 394
358 // Surround the given data with the prefix & suffix 395 // Surround the given data with the prefix & suffix
359 data = g_new(char, sizeof(prefix) + sizeof(suffix) + strlen(gpg_data)); 396 data = g_new(char, sizeof(prefix) + sizeof(suffix) + strlen(gpg_data));
360 strcpy(data, prefix); 397 strcpy(data, prefix);
361 strcat(data, gpg_data); 398 strcat(data, gpg_data);