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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show annotations)
Sat Oct 8 10:43:08 2005 UTC (19 years, 4 months ago) by twoaday
File size: 25655 byte(s)
Bug fixes to correct some problems introduced by
the MyGPGME to GPGME port.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26