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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (show annotations)
Thu Nov 3 17:55:18 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26017 byte(s)
Fix crash in the GPG preference dialog.
Allow to have an empty secret keyring.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26