/[winpt]/trunk/Src/wptGPG.cpp
ViewVC logotype

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 407 - (show annotations)
Mon Feb 6 19:26:03 2012 UTC (13 years ago) by twoaday
File size: 26784 byte(s)
2012-02-06  Timo Schulz  <twoaday@gmx.net>

        * wptNLS.cpp (gettext_free_current_domain): Replace free()
	        with safe_free():
        * WinPT.cpp: Use log_debug to improve bug tracking capabilities.


1 /* wptGPG.cpp - GnuPG configuration
2 * Copyright (C) 2001-2009 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <windows.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <shlobj.h>
24 #include <ctype.h>
25 #include <io.h>
26 #include <time.h>
27
28 #include "wptGPG.h"
29 #include "wptGPGME.h"
30 #include "wptGPGCmds.h"
31 #include "wptTypes.h"
32 #include "wptNLS.h"
33 #include "wptRegistry.h"
34 #include "wptErrors.h"
35 #include "wptW32API.h"
36 #include "wptCrypto.h"
37
38 #define GPG_CONF "gpg.conf"
39 #define GPG_REG_EXE "gpgProgram" /* registry name for the binary. */
40 #define GPG_REG_HOME "HomeDir" /* registry name of the home dir. */
41
42 /* Context to monitor GPG file changes. */
43 struct gpg_monitor_s {
44 FILETIME last_access; /* last write access. */
45 FILETIME access;
46 char *object; /* name of the object. */
47 char *fpath_object; /* full path to the object. */
48 int modified; /* 1 = modified. */
49 };
50 typedef struct gpg_monitor_s *gpg_monitor_t;
51
52 static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
53 static gpg_monitor_s gpg_table[3];
54 static int gpg_table_count = DIM (gpg_table);
55
56 int idea_available = 0; /* if the IDEA extension is available. */
57
58
59 static int check_keyring (char ** r_path);
60
61
62 /* Return the application data folder of the current user. */
63 char*
64 multi_gnupg_path (int strict)
65 {
66 static char buf[MAX_PATH+64];
67
68 /* MSDN: buf must be at least MAX_PATH=256 bytes */
69 memset (buf, 0, sizeof (buf));
70 if (!SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE)) {
71 log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed with: %d\r\n",
72 (int)GetLastError ());
73 return NULL;
74 }
75 strcat (buf, "\\gnupg");
76 if (strict && access (buf, 00))
77 return NULL;
78 return m_strdup (buf);
79 }
80
81
82 /* Return the full path to the GPG home directory. First the 'HomeDir' entry
83 from the registry is used. Then the default $APPDATA\gnupg path. */
84 char*
85 get_gnupg_path (void)
86 {
87 char *path = get_reg_entry_gpg (GPG_REG_HOME);
88 if (path && dir_exist_check (path) == 0)
89 return path;
90 free_if_alloc (path);
91 return multi_gnupg_path (1);
92 }
93
94
95 /* Return the full path of the gpg config file.
96 A value of NULL indicates an error. */
97 char*
98 get_gnupg_cfgfile (void)
99 {
100 char *path = get_gnupg_path ();
101 if (!path)
102 return NULL;
103 char *optfile = make_filename (path, GPG_CONF, NULL);
104 free_if_alloc (path);
105
106 return optfile;
107 }
108
109
110 static char*
111 get_keyring_from_conf (const char *fname, int pub)
112 {
113 config_file_t opt;
114 conf_option_t e;
115 char *kring = NULL;
116
117 if (parse_config (fname, &opt))
118 return NULL;
119 if (pub)
120 e = conf_find_option (opt, "keyring");
121 else
122 e = conf_find_option (opt, "secret-keyring");
123 if (e != NULL)
124 kring = m_strdup (e->val);
125 release_config (opt);
126
127 return kring;
128 }
129
130
131 /* Return the full path of the keyring. If @pub is 1, the public
132 keyring is return, otherwise the secret keyring. */
133 char*
134 get_gnupg_keyring (int pub, int strict)
135 {
136 char *optfile;
137 char *path;
138 char *keyring;
139
140 path = get_gnupg_path ();
141 if (!path)
142 return NULL;
143 keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
144 if (strict && !file_exist_check (keyring)) {
145 free_if_alloc (path);
146 return keyring;
147 }
148 else if (!strict) {
149 free_if_alloc (path);
150 return keyring;
151 }
152 if (file_exist_check (keyring) ||
153 (pub && get_file_size (keyring) == 0)) {
154 free_if_alloc (keyring);
155 optfile = make_filename (path, GPG_CONF, NULL);
156 keyring = get_keyring_from_conf (optfile, pub);
157 free_if_alloc (optfile);
158 }
159 free_if_alloc (path);
160
161 return keyring;
162 }
163
164
165 /* Return the full path (with the gpg exe name). First the registry is scanned
166 for the entry 'gpgProgram'. If it wasn't set, the default path is the
167 appended string 'gpg.exe' is used. */
168 char*
169 get_gnupg_prog (void)
170 {
171 char *path;
172 char *pgm;
173
174 pgm = get_reg_entry_gpg (GPG_REG_EXE);
175 if (pgm)
176 return pgm;
177 path = get_gnupg_path ();
178 if (!path)
179 return NULL;
180 pgm = make_filename (path, "gpg", "exe");
181 free_if_alloc (path);
182 return pgm;
183 }
184
185
186 /* Retrieve the first usable secret key from cache.
187 If no usable was found, @ret_no_useable is 1.
188 Return value: the keyid of the secret key. */
189 static char*
190 default_key_from_cache (int *ret_no_useable)
191 {
192 gpgme_key_t key, pk;
193 gpg_keycache_t sec, pub;
194 const char *s;
195 char *keyid = NULL;
196
197 sec = keycache_get_ctx (0);
198 pub = keycache_get_ctx (1);
199 gpg_keycache_rewind (sec);
200 while (!gpg_keycache_next_key (sec, 1, &key)) {
201 if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
202 s = key->subkeys->keyid;
203 if (s)
204 keyid = m_strdup (s+8);
205 break;
206 }
207 }
208 if (!keyid)
209 *ret_no_useable = 1;
210 return keyid;
211 }
212
213
214 /* Load the gpg.conf and search for some options
215 and store the result in the global preference context.
216 Return value: 0 on success. */
217 int
218 gnupg_load_config (void)
219 {
220 config_file_t opt;
221 char *conf;
222 int rc = 0;
223
224 conf = get_gnupg_cfgfile ();
225 if (!conf)
226 return -1;
227 if (parse_config (conf, &opt)) {
228 free_if_alloc (conf);
229 return -1;
230 }
231 free_if_alloc (conf);
232 if (conf_find_option (opt, "ask-cert-level"))
233 reg_prefs.gpg.ask_cert_level = 1;
234 if (conf_find_option (opt, "ask-cert-expire"))
235 reg_prefs.gpg.ask_cert_expire = 1;
236 /* The 'textmode' option for GPG is useful for text files
237 but it breaks the output of any binary data. Thus we return
238 a warning here to inform the user that binary output is broken. */
239 if (conf_find_option (opt, "textmode"))
240 rc = -2;
241 release_config (opt);
242
243 return rc;
244 }
245
246
247 /* handle the case the user added a '!' to force a subkey. */
248 static char*
249 extract_keyid (const char *val)
250 {
251 size_t len = strlen (val);
252
253 if (len > 1 && val[len-1] == '!')
254 return substr (val, 0, len-1);
255 return m_strdup (val);
256 }
257
258
259 /* Return the default key.
260 This can be either a substring or a key ID. */
261 char*
262 get_gnupg_default_key (void)
263 {
264 config_file_t opt = NULL;
265 conf_option_t e;
266 char *keyid = NULL, *optfile = NULL;
267 int no_usable=0;
268
269 optfile = get_gnupg_cfgfile ();
270 if (!optfile)
271 return default_key_from_cache (&no_usable);
272 if (parse_config (optfile, &opt)) {
273 free_if_alloc (optfile);
274 return default_key_from_cache (&no_usable);
275 }
276 /* First we search for config entries which specify a default key. */
277 e = conf_find_option (opt, "default-key");
278 if (!e)
279 e = conf_find_option (opt, "local-user");
280 if (e)
281 keyid = extract_keyid (e->val);
282
283 free_if_alloc (optfile);
284 release_config (opt);
285
286 /* If no entry in the config has been found, we get a key
287 from the key cache. */
288 if (!keyid)
289 keyid = default_key_from_cache (&no_usable);
290 return keyid;
291 }
292
293
294 /* Check if GPG4WIN is available and if so, use the
295 install path to figure out where the gpg.exe is. */
296 char*
297 check_for_gpg4win (void)
298 {
299 return get_reg_entry_gpg4win ("gpg.exe");
300 }
301
302
303 /* Check if the gpg application (exe file) is available. */
304 int
305 check_gnupg_prog (void)
306 {
307 char *gpgexe = NULL;
308 int rc = 0;
309
310 gpgexe = get_gnupg_prog ();
311 if (!gpgexe || file_exist_check (gpgexe)) {
312 free_if_alloc (gpgexe);
313 gpgexe = check_for_gpg4win ();
314 if (!gpgexe || file_exist_check (gpgexe))
315 rc = WPTERR_GPG_EXEFILE;
316 else
317 set_reg_entry_gpg (GPG_REG_EXE, gpgexe);
318 }
319 free_if_alloc (gpgexe);
320 return rc;
321 }
322
323
324 static int
325 parse_version_nr (const char *buf, int *major, int *minor, int *patch)
326 {
327 char *p;
328 char *tmp = m_strdup(buf);
329
330 int pos = 0;
331 while ((p = strsep(&tmp, ".")) != NULL) {
332 switch (++pos) {
333 case 1: *major = atoi (p); break;
334 case 2: *minor = atoi (p); break;
335 case 3: *patch = atoi (p); break;
336 }
337 }
338 delete[] tmp;
339 if (pos != 3)
340 return -1;
341 return 0;
342 }
343
344
345 /* Check if the gnupg engine fullfills the minimum requirement
346 version given in @r_major.@r_minor.@r_patch. On success these
347 variables contain the GPG version which is installed. */
348 int
349 check_gnupg_engine (const char *need_gpg_ver,
350 int *r_major, int *r_minor, int *r_patch)
351 {
352 gpgme_engine_info_t inf;
353 char *eng = NULL;
354 int major=0, minor=0, patch=0;
355 int need_major = 0, need_minor = 0, need_patch = 0;
356 int rc = 1;
357
358 /* Convert the needed GPG version to the integer format. */
359 if (parse_version_nr (need_gpg_ver,
360 &need_major, &need_minor, &need_patch))
361 return 1;
362
363 if (gpgme_get_engine_info (&inf))
364 return -1;
365
366 /* We need to exec GPG again to find out if IDEA is available. */
367 if (gpg_get_version (&eng))
368 return -1;
369 if (strstr (eng, "IDEA"))
370 idea_available = 1;
371 safe_free (eng);
372
373 if (parse_version_nr (inf->version, &major, &minor, &patch))
374 return 1;
375
376 if (major > need_major)
377 rc = 0;
378 else if (major == need_major && minor > need_minor)
379 rc = 0;
380 else if (major == need_major && minor == need_minor &&
381 patch >= need_patch)
382 rc = 0;
383
384 /* Return the current GPG version. */
385 *r_major = major;
386 *r_minor = minor;
387 *r_patch = patch;
388 return rc;
389 }
390
391
392 /* Count the keyring entries in the gpg.conf file.
393 Return value: 0 on success. */
394 static int
395 cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
396 {
397 config_file_t opt;
398 conf_option_t e;
399
400 *r_secrings = 0;
401 *r_pubrings = 0;
402
403 if (parse_config (fname, &opt))
404 return WPTERR_FILE_OPEN;
405 for (e = opt->list; e; e = e->next) {
406 if (!strcmp (e->name, "secret-keyring")) {
407 if (!file_exist_check (e->val))
408 r_secrings[0]++;
409 }
410 else if (!strcmp (e->name, "keyring")) {
411 if (!file_exist_check (e->val))
412 r_pubrings[0]++;
413 }
414 }
415 release_config (opt);
416 return 0;
417 }
418
419
420 /* Usually GPG creates the pubring.gpg, secring.gpg on
421 the first start, but to make sure they always exist
422 create them empty if needed. */
423 static void
424 create_empty_keyring (int _pub)
425 {
426 char *name = get_gnupg_keyring (_pub, 0);
427 if (name && file_exist_check (name) != 0) {
428 FILE *fp = fopen (name, "ab");
429 if (fp != NULL)
430 fclose (fp);
431 }
432 free_if_alloc (name);
433 }
434
435
436 /* Check if both keyrings are located in the gnupg home directory. */
437 int
438 gnupg_access_files (void)
439 {
440 int rc = 0;
441 int pubring_ok = 0, secring_ok = 0;
442 int secrings = 0, pubrings = 0;
443 char *optfile;
444
445 create_empty_keyring (1);
446 if (gnupg_access_keyring (1))
447 rc = WPTERR_GPG_KEYRINGS;
448 else
449 pubring_ok = 1;
450
451 create_empty_keyring (0);
452 if (gnupg_access_keyring (0))
453 rc = WPTERR_GPG_KEYRINGS;
454 else
455 secring_ok = 1;
456
457 if (!pubring_ok || !secring_ok) {
458 optfile = get_gnupg_cfgfile ();
459 if (!optfile)
460 return WPTERR_GPG_KEYRINGS;
461 rc = file_exist_check (optfile);
462 if (!rc && get_file_size (optfile) > 0) {
463 rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
464 if (!rc && secrings > 0 && pubrings > 0) {
465 free_if_alloc (optfile);
466 return 0; /* found two keyrings in the option file */
467 }
468 else if ((!rc && pubrings && secring_ok)
469 || (!rc && secrings && pubring_ok)) {
470 free_if_alloc (optfile);
471 return 0; /* found one keyring and one entry in the options file */
472 }
473 else
474 return WPTERR_GPG_OPT_KEYRINGS;
475 }
476 free_if_alloc (optfile);
477 rc = WPTERR_GPG_KEYRINGS;
478 }
479 return rc;
480 }
481
482
483
484 /* Return the contents of the options file as a char buf. */
485 char*
486 get_gnupg_config (void)
487 {
488 FILE *fp;
489 char *p = NULL, *optfile;
490 int fsize;
491
492 optfile = get_gnupg_cfgfile ();
493 if (!optfile)
494 return NULL;
495 fsize = get_file_size (optfile);
496 if (fsize < 1 || fsize > 100000)
497 goto leave; /* too large or does not exist */
498
499 fp = fopen (optfile, "rb");
500 if (!fp)
501 goto leave;
502 p = new char[fsize+1];
503 if (!p)
504 BUG (NULL);
505 fread (p, 1, fsize, fp);
506 fclose (fp);
507 p[fsize] = '\0';
508
509 leave:
510 free_if_alloc (optfile);
511 return p;
512 }
513
514
515 /* Set the default key in the gpg.conf.
516 If @key is NULL, the entry will be deleted. */
517 int
518 set_gnupg_default_key (const char *key)
519 {
520 config_file_t opt;
521 conf_option_t e;
522 char *optfile = NULL;
523 int rc = 0;
524
525 optfile = get_gnupg_cfgfile ();
526 if (!optfile)
527 return WPTERR_FILE_OPEN;
528 rc = parse_config (optfile, &opt);
529 if (rc) {
530 free_if_alloc (optfile);
531 return WPTERR_GENERAL;
532 }
533 e = conf_find_option (opt, "default-key");
534 if (e && !key)
535 e->used = 0;
536 else if (e) {
537 free_if_alloc (e->val);
538 e->val = m_strdup (key);
539 e->used = 1;
540 }
541 else if (key)
542 conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
543 rc = commit_config (optfile, opt);
544
545 free_if_alloc (optfile);
546 release_config (opt);
547 return rc;
548 }
549
550
551 /* Set the contents of the options file. */
552 int
553 set_gnupg_options (const char *buf, size_t buflen)
554 {
555 FILE *fp;
556 char *optfile;
557
558 optfile = get_gnupg_cfgfile ();
559 if (!optfile)
560 return WPTERR_FILE_CREAT;
561
562 fp = fopen (optfile, "wb");
563 if (!fp) {
564 free_if_alloc (optfile);
565 return WPTERR_FILE_CREAT;
566 }
567 fwrite (buf, 1, buflen, fp);
568 fclose (fp);
569 free_if_alloc (optfile);
570 return 0;
571 }
572
573
574 /* Check if the parameter for the option @buf is an existing file name.
575 Return value: 0 on success. */
576 static int
577 check_arg_file_exist (const char *buf)
578 {
579 const char *s = "load-extension ";
580
581 /* XXX: this is a bit of a kludge because we just
582 detect errors for 'load-extension'. */
583 if (!strncmp (buf, s, strlen (s)))
584 buf += strlen (s);
585 else
586 return 0;
587 return file_exist_check (buf);
588 }
589
590
591 /* Check if the line contains a valid GPG argument. */
592 static int
593 check_line (const char *buf)
594 {
595 int j, len;
596 int rc = 0;
597
598 if (*buf == '#' || *buf == '\r' || *buf == '\n')
599 return 1;
600 for (j = 0; valid_gpg_args[j]; j++) {
601 len = strlen (valid_gpg_args[j]);
602 if (!strncmp (valid_gpg_args[j], buf, len))
603 rc = 1;
604 }
605 return rc;
606 }
607
608
609 int
610 check_gnupg_options (const char *buf, int showerr)
611 {
612 char line[1024];
613 int nbytes = 0, lineno=0;
614 unsigned j;
615
616 for (j = 0; j < strlen (buf) && j < DIM (line); j++) {
617 line[nbytes++] = buf[j];
618 if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
619 line[nbytes] = '\0';
620 lineno++;
621 if (!check_line (line)) {
622 if (showerr)
623 log_box ("GPG Config File", MB_ERR,
624 "gpg.conf:%d: invalid keyword '%s'",
625 lineno, line);
626 return 1;
627 }
628 if (check_arg_file_exist (line))
629 return WPTERR_FILE_EXIST;
630 nbytes = 0;
631 }
632 }
633 return 0;
634 }
635
636
637 /* Store the last access of the file inside the watcher @ctx. */
638 static int
639 get_last_gnupg_access (gpg_monitor_t ctx)
640 {
641 HANDLE fd;
642
643 fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
644 NULL, OPEN_EXISTING, 0, NULL);
645 if (fd == INVALID_HANDLE_VALUE)
646 return WPTERR_FILE_OPEN;
647 GetFileTime (fd, NULL, NULL, &ctx->access);
648 CloseHandle (fd);
649 return 0;
650 }
651
652
653 /* Check if the file inside watcher @ctx was modified. */
654 static void
655 check_last_gnupg_access (gpg_monitor_t ctx)
656 {
657 ctx->modified = 0;
658
659 if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
660 ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
661 ctx->modified = 1;
662
663 if (ctx->last_access.dwLowDateTime == 0)
664 ctx->modified = 0;
665
666 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
667 ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
668 }
669
670
671 /* Init GPG monitor table for all monitored files. */
672 void
673 init_gnupg_table (void)
674 {
675 char *path;
676 int j;
677
678 path = get_gnupg_path ();
679 for (j = 0; j < gpg_table_count; j++) {
680 gpg_table[j].object = m_strdup (gpg_objs[j]);
681 gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
682 memset (&gpg_table[j].access, 0, sizeof (FILETIME));
683 memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
684 gpg_table[j].modified = 0;
685 }
686 free_if_alloc (path);
687 }
688
689
690 /* Release the GPG monitor table. */
691 void
692 free_gnupg_table (void)
693 {
694 for (int j=0; j < gpg_table_count; j++) {
695 free_if_alloc (gpg_table[j].object);
696 free_if_alloc (gpg_table[j].fpath_object);
697 }
698 }
699
700
701 /* Return the amount of files modified since the last call. */
702 int
703 keyring_check_last_access (void)
704 {
705 int nfiles;
706
707 nfiles = 0;
708 for (int pos = 0; pos < gpg_table_count; pos++) {
709 get_last_gnupg_access (&gpg_table[pos]);
710 check_last_gnupg_access (&gpg_table[pos]);
711 if (gpg_table[pos].modified)
712 nfiles++;
713 }
714
715 return nfiles;
716 }
717
718
719 const char*
720 gnupg_check_file_ext (const char *fname, int *r_type)
721 {
722 char file_ext[5];
723
724 if (r_type)
725 *r_type = PGP_NONE;
726 if (!strchr (fname, '.' ))
727 return "UNKNOWN";
728
729 strncpy (file_ext, fname + strlen (fname) - 4, 4);
730 file_ext[4] = '\0';
731 if (!stricmp (file_ext, ".asc"))
732 return "ARMORED";
733 else if (!stricmp (file_ext, ".sig")) {
734 if (r_type)
735 *r_type = PGP_SIG;
736 return "SIGNED";
737 }
738 else if (!stricmp (file_ext, ".gpg") ||
739 !stricmp (file_ext, ".pgp")) {
740 if (r_type)
741 *r_type = PGP_MESSAGE;
742 return "ENCRYPTED";
743 }
744 return "UNKNOWN";
745 }
746
747
748 /* Check if the device where file @fname is stored on, is write-protected. */
749 static int
750 check_file_access (const char *fname, int mode)
751 {
752 HANDLE hd;
753
754 if (!mode)
755 mode = FILE_SHARE_WRITE;
756 hd = CreateFile (fname, GENERIC_WRITE, mode,
757 NULL, OPEN_EXISTING, 0, NULL);
758 if (hd == INVALID_HANDLE_VALUE)
759 return -1;
760 CloseHandle (hd);
761 return 0;
762 }
763
764
765 /* Check the device where the file @fname is stored on, is either
766 write-protected or if the file is already opened by another process
767 exclusively. And as a result, we cannot use the file for output. */
768 int
769 gpg_check_file_permissions (const char *fname, int mode)
770 {
771 int api_mode;
772
773 switch (mode) {
774 case 0: api_mode = FILE_SHARE_READ; break;
775 case 1: api_mode = FILE_SHARE_WRITE; break;
776 case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
777 default: api_mode = FILE_SHARE_READ; break;
778 }
779
780 return check_file_access (fname, api_mode);
781 }
782
783
784 /* Check the file permissions of the public keyring.
785 If @showmsg is 1 output a message in case of errors.
786 Return value: 1 if read-only attribute
787 2 if file is opened by another process exclusively. */
788 int
789 gpg_check_permissions (int showmsg)
790 {
791 char *p = NULL;
792 char *name = NULL;
793 int failed = 0, ans=0, attrs=0;
794
795 p = get_gnupg_path ();
796 if (p && check_keyring (&p)) {
797 name = make_filename (p, "pubring", "gpg");
798 if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
799 ans = msg_box (NULL,
800 _("The selected keyring has the read-only file\n"
801 "attribute. In this state you do not have write\n"
802 "access. Do you want to remove the attribute?"),
803 _("GPG Information"), MB_YESNO);
804 if (ans == IDYES) {
805 attrs &= ~FILE_ATTRIBUTE_READONLY;
806 if (!SetFileAttributes (name, attrs)) {
807 msg_box (NULL, _("Could not reset read-only state."),
808 _("GPG Error"), MB_ERR);
809 failed = 1;
810 }
811 }
812 else if (ans == IDNO) {
813 /* All commands with write access will be disabled. */
814 failed = 1;
815 }
816 }
817 if (gpg_check_file_permissions (name, 1)) {
818 if (showmsg)
819 msg_box (NULL,
820 _("You do not have file access to modify the contents of\n"
821 "one or both of the selected keyrings.\n"
822 "\n"
823 "The keyrings are in a read-only state which is propably\n"
824 "caused by another program which already opened the files.\n"),
825 _("GPG Warning"), MB_WARN);
826 failed = 2;
827 }
828 }
829 free_if_alloc (p);
830 free_if_alloc (name);
831 return failed;
832 }
833
834
835 /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
836 then check for $APPDATA\gnupg. Create the dir if it does not exists. */
837 int
838 gnupg_check_homedir (void)
839 {
840 char *homedir;
841 int val;
842 int rc = 0;
843
844 homedir = get_reg_entry_gpg (GPG_REG_HOME);
845 if (!homedir)
846 homedir = multi_gnupg_path (0);
847 if (homedir) {
848 if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
849 val = log_box (_("Preferences"), MB_YESNO,
850 _("%s does not exit.\n"
851 "Do you want to create this directory?"), homedir);
852 if (val == IDYES) {
853 if (!CreateDirectory (homedir, NULL))
854 rc = WPTERR_DIR_CREAT;
855 }
856 else
857 rc = WPTERR_DIR_OPEN;
858 }
859 free_if_alloc (homedir);
860 }
861 return rc;
862 }
863
864
865 int
866 gnupg_import_keypair (void)
867 {
868 const char *file;
869 gpgme_error_t err;
870 GPGME gpgme;
871 HWND hwnd = GetDesktopWindow ();
872
873 file = get_fileopen_dlg (hwnd, _("Please choose your Key Pair"),
874 "GPG Key File (*.gpg)\0*.gpg\0"
875 "GPG Armored Key File (*.asc)\0*.asc\0\0",
876 NULL);
877 if (file == NULL)
878 return WPTERR_FILE_OPEN;
879 err = gpgme.importFromFile (file);
880 if (err)
881 msg_box (hwnd, gpgme_strerror (err), _("WinPT Error"), MB_ERR);
882 else
883 msg_box (hwnd, _("Key pair successfully imported."), "WinPT", MB_OK);
884 return 0;
885 }
886
887 int
888 gnupg_copy_keyrings (void)
889 {
890 const char *pring, *sring;
891 char *file = NULL, *path;
892 int id, rc = 0;
893 HWND hwnd;
894
895 path = get_gnupg_path ();
896 if (!path)
897 return WPTERR_GENERAL;
898 hwnd = GetDesktopWindow ();
899
900 pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
901 "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
902 if (!pring) {
903 msg_box (hwnd, _("No keyring was chosen. Exit."),
904 _("WinPT Error"), MB_ERR);
905 free_if_alloc (path);
906 return WPTERR_GENERAL;
907 }
908 file = make_filename (path, "pubring", "gpg");
909 if (file_exist_check (file) == 0) {
910 id = msg_box (hwnd, _("Overwrite old public keyring?"),
911 "WinPT", MB_INFO|MB_YESNO);
912 if (id == IDNO)
913 goto fail;
914 }
915 if (!CopyFile (pring, file, FALSE)) {
916 msg_box (hwnd, _("Could not copy public keyring."),
917 _("WinPT Error"), MB_ERR);
918 rc = WPTERR_FILE_READ;
919 goto fail;
920 }
921 free_if_alloc (file);
922
923 sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
924 "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
925 if (!sring) {
926 msg_box (NULL, _("No keyring was chosen. Exit."),
927 _("WinPT Error"), MB_ERR);
928 return WPTERR_GENERAL;
929 }
930 file = make_filename (path, "secring", "gpg");
931 if (file_exist_check (file) == 0) {
932 id = msg_box (hwnd, _("Overwrite old secret keyring?"),
933 "WinPT", MB_INFO|MB_YESNO);
934 if (id == IDNO)
935 goto fail;
936 }
937 if (!CopyFile (sring, file, FALSE)) {
938 msg_box (NULL, _("Could not copy secret keyring."), _("WinPT Error"), MB_ERR);
939 rc = WPTERR_FILE_READ;
940 }
941
942 fail:
943 free_if_alloc (file);
944 free_if_alloc (path);
945 return rc;
946 }
947
948
949 /* Backup the gpg.conf file. */
950 void
951 gnupg_backup_options (void)
952 {
953 char bak[MAX_PATH+32];
954
955 char *cfgfile = get_gnupg_cfgfile ();
956 if (!cfgfile)
957 return;
958 _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
959 CopyFile (cfgfile, bak, FALSE);
960 free_if_alloc (cfgfile);
961 }
962
963
964 static int
965 backup_one_file (const char *srcpath, const char *srcn,
966 const char *dstpath, const char *dstn)
967 {
968 char *src, *dst;
969 BOOL rc;
970
971 src = make_filename (srcpath, srcn, "gpg");
972 dst = make_filename (dstpath, dstn, "gpg");
973 rc = CopyFile (src, dst, FALSE);
974 free_if_alloc (src);
975 free_if_alloc (dst);
976 if (!rc) {
977 log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
978 return WPTERR_GENERAL;
979 }
980 return 0;
981 }
982
983
984 /* Figure out first public keyring which is not empty.
985 Return value: 1 on success. */
986 static int
987 check_keyring (char **r_path)
988 {
989 char *p;
990 char *opt;
991 char *name;
992
993 if (!*r_path)
994 return 0;
995 p = make_filename (*r_path, "pubring", "gpg");
996 if (get_file_size (p) <= 0)
997 return 0;
998
999 opt = get_gnupg_cfgfile ();
1000 if (!opt)
1001 BUG (0);
1002 name = get_keyring_from_conf (opt, 1);
1003 free_if_alloc (opt);
1004 free_if_alloc (p);
1005 if (!name)
1006 return 0;
1007 p = strrchr (name, '\\');
1008 if (!p) {
1009 free_if_alloc (name);
1010 return 0;
1011 }
1012 free_if_alloc (*r_path);
1013 *r_path = new char [strlen (name)+1];
1014 memset (*r_path, 0, strlen (name));
1015 strncpy (*r_path, name, (p-name));
1016 free_if_alloc (name);
1017 return 1;
1018 }
1019
1020
1021 /* Return a temp name based on the day of the week. */
1022 static char*
1023 get_backup_name (const char *templ)
1024 {
1025 struct tm *tm;
1026 const char *fmt;
1027 char *p;
1028 time_t t;
1029
1030 t = time (NULL);
1031 tm = localtime (&t);
1032 fmt = "%s-%d";
1033 p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1034 if (!p)
1035 BUG (0);
1036 sprintf (p, fmt, templ, tm->tm_wday % 3);
1037 return p;
1038 }
1039
1040
1041 /* Make backups of all keyrings. The public key ring is rotated like
1042 this pubring-%d.gpg.
1043 If @auto_backup is false, no action is performed.
1044 @include_secr indicated if the backup includes the secret keyring. */
1045 void
1046 gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1047 {
1048 char *srcpath, *dstpath;
1049 char *name;
1050 int rc;
1051
1052 if (!auto_backup)
1053 return;
1054 srcpath = get_gnupg_path ();
1055 check_keyring (&srcpath);
1056 if (backup_mode == 1) {
1057 /* If the backup mode uses the home directory the source
1058 and destination folder will be the same. */
1059 dstpath = get_gnupg_path ();
1060 check_keyring (&dstpath);
1061 }
1062 else if (backup_mode == 2) {
1063 char *tmpfile;
1064 FILE *fp;
1065
1066 dstpath = m_strdup (reg_prefs.backup.path);
1067 tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1068 fp = fopen (tmpfile, "wb");
1069 if (!fp)
1070 rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1071 _("The backup drive '%s' does not seems to be accessable.\n"
1072 "Please insert/check the drive to continue."), dstpath);
1073 else {
1074 rc = 0;
1075 fclose (fp);
1076 DeleteFile (tmpfile);
1077 }
1078 free_if_alloc (tmpfile);
1079 if (!fp || rc == IDCANCEL) {
1080 free_if_alloc (dstpath);
1081 free_if_alloc (srcpath);
1082 return;
1083 }
1084 }
1085 else {
1086 log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1087 free_if_alloc (srcpath);
1088 return;
1089 }
1090 name = get_backup_name ("pubring-bak");
1091 rc = backup_one_file (srcpath, "pubring", dstpath, name);
1092 if (!rc && include_secr)
1093 rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1094 free_if_alloc (name);
1095 free_if_alloc (srcpath);
1096 free_if_alloc (dstpath);
1097 }
1098
1099
1100 /* check that the requested GPG keyring exist and.
1101 Return value: 0 for success. */
1102 int
1103 gnupg_access_keyring (int _pub)
1104 {
1105 int rc = 0;
1106 char *name = get_gnupg_keyring (_pub, 1);
1107 if (!name || file_exist_check (name))
1108 rc = -1;
1109 free_if_alloc (name);
1110 return rc;
1111 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26