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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File size: 25674 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


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 if( strncmp( buf, "gpg ", 4 ) )
275 return -1;
276 buf += 4;
277 if( strncmp( buf, "(GnuPG) ", 8 ) )
278 return -1;
279 buf += 8;
280 i=0;
281 while( buf && *buf != '.' && i < 8 )
282 tmp[i++] = *buf++;
283 tmp[i] = 0; buf++;
284 *major = atol( tmp );
285 i=0;
286 while( buf && *buf != '.' && i < 8 )
287 tmp[i++] = *buf++;
288 tmp[i] = 0; buf++;
289 *minor = atol( tmp );
290 i=0;
291 while( buf && isdigit( *buf ) && i < 8 )
292 tmp[i++] = *buf++;
293 tmp[i] = 0;
294 *patch = atol( tmp );
295 return 0;
296 }
297
298
299 int
300 check_gnupg_engine (int * r_major, int * r_minor, int * r_patch)
301 {
302 gpgme_ctx_t ctx;
303 gpgme_engine_info_t inf;
304 char * eng = NULL;
305 int major=0, minor=0, patch=0;
306 int rc;
307
308 gpgme_new (&ctx);
309 inf = gpgme_ctx_get_engine_info (ctx);
310 if (!inf) {
311 gpgme_release (ctx);
312 return -1;
313 }
314 if( strstr( eng, "IDEA" ) )
315 idea_available = 1;
316 rc = parse_version_nr( inf->version, &major, &minor, &patch );
317 if( rc ) {
318 gpgme_release (ctx);
319 return rc;
320 }
321 if( major < *r_major
322 || minor < *r_minor)
323 rc = 1;
324 else {
325 if (patch < *r_patch )
326 rc = 1;
327 rc = 0;
328 }
329 *r_major = major;
330 *r_minor = minor;
331 *r_patch = patch;
332 return rc;
333 } /* check_gnupg_engine */
334
335
336 int
337 check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)
338 {
339 gpg_optfile_t opt;
340 gpg_option_t e;
341 int rc = 0;
342
343 if( r_secrings )
344 *r_secrings = 0;
345 if( r_pubrings )
346 *r_pubrings = 0;
347 rc = parse_gpg_options( fname, &opt );
348 if( rc )
349 return WPTERR_FILE_OPEN;
350
351 for( e = opt->list; e; e = e->next ) {
352 if( !strcmp( e->name, "secret-keyring" ) ) {
353 if( !file_exist_check( e->val ) )
354 r_secrings[0]++;
355 }
356 else if( !strcmp( e->name, "keyring" ) ) {
357 if( !file_exist_check( e->val ) )
358 r_pubrings[0]++;
359 }
360 }
361 release_gpg_options( opt );
362 return 0;
363 } /* check_gnupg_cfgfile */
364
365 /*
366 * Check if both keyrings are located in the gnupg home directory.
367 */
368 int
369 gnupg_access_files (void)
370 {
371 int rc = 0;
372 int pubring_ok = 0, secring_ok = 0;
373 int secrings = 0, pubrings = 0;
374 char *optfile;
375
376 if (gnupg_access_keyring (1))
377 rc = WPTERR_GPG_KEYRINGS;
378 else
379 pubring_ok = 1;
380
381 if (gnupg_access_keyring (0))
382 rc = WPTERR_GPG_KEYRINGS;
383 else
384 secring_ok = 1;
385 if (!pubring_ok || !secring_ok) {
386 optfile = get_gnupg_cfgfile ();
387 if (!optfile)
388 return WPTERR_GPG_KEYRINGS;
389 rc = file_exist_check (optfile);
390 if (!rc && get_file_size(optfile) > 0) {
391 rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);
392 if (!rc && secrings && pubrings) {
393 free_if_alloc (optfile);
394 return 0; /* found two keyrings in the option file */
395 }
396 else if ((!rc && pubrings && secring_ok)
397 || (!rc && secrings && pubring_ok)) {
398 free_if_alloc (optfile);
399 return 0; /* found one keyring and one entry in the options file */
400 }
401 else
402 return WPTERR_GPG_OPT_KEYRINGS;
403 }
404 free_if_alloc (optfile);
405 rc = WPTERR_GPG_KEYRINGS;
406 }
407 return rc;
408 } /* gnupg_access_files */
409
410
411 static int
412 create_gpg_options( void )
413 {
414 FILE *fp;
415 char *s, *optfile;
416
417 s = get_gnupg_path( );
418 if( s == NULL )
419 return WPTERR_FILE_CREAT;
420 optfile = make_filename( s, GPG_CONF, NULL );
421 fp = fopen( optfile, "wb" );
422 if( fp == NULL ) {
423 return WPTERR_FILE_CREAT;
424 goto fail;
425 }
426 fwrite( options_skel, 1, strlen( options_skel ), fp );
427 fclose( fp );
428
429 fail:
430 free_if_alloc( s );
431 free_if_alloc( optfile );
432 return 0;
433 } /* create_gpg_options */
434
435
436 /*
437 * Return the contents of the options file as a char buf.
438 */
439 char *
440 get_gnupg_config (void)
441 {
442 FILE * fp;
443 char * p = NULL, * optfile = NULL;
444 int fsize, rc = 0;
445
446 optfile = get_gnupg_cfgfile ();
447 if( optfile == NULL )
448 return NULL;
449 fsize = get_file_size( optfile );
450 if( !fsize ) {
451 rc = create_gpg_options( );
452 if ( rc )
453 return NULL;
454 fsize = get_file_size( optfile );
455 }
456 if( fsize > 100000 )
457 goto leave; /* too large */
458 p = new char[fsize+1];
459 if( p == NULL )
460 BUG( NULL );
461 fp = fopen( optfile, "rb" );
462 if( fp == NULL ) {
463 free_if_alloc( p );
464 return NULL;
465 }
466 fread( p, 1, fsize, fp );
467 fclose( fp );
468 p[fsize] = '\0';
469 free_if_alloc( optfile );
470
471 leave:
472 return p;
473 } /* get_gnupg_config */
474
475
476 int
477 set_gnupg_default_key (const char * key)
478 {
479 gpg_optfile_t opt;
480 gpg_option_t e;
481 char *optfile = NULL;
482 int rc = 0;
483
484 optfile = get_gnupg_cfgfile ();
485 if (!optfile)
486 return -1;
487 rc = parse_gpg_options (optfile, &opt);
488 if( rc ) {
489 free_if_alloc (optfile);
490 return -1;
491 }
492 e = find_option (opt, "default-key");
493 if (e) {
494 free_if_alloc (e->val);
495 e->val = m_strdup (key);
496 e->used = 1;
497 }
498 else
499 add_entry (opt, ENTRY_MULTI, "default-key", key);
500 rc = commit_gpg_options (optfile, opt);
501
502 free_if_alloc (optfile);
503 release_gpg_options (opt);
504
505 return rc;
506 } /* set_gnupg_default_key */
507
508
509 /*
510 * Set the contents of the options file.
511 */
512 int
513 set_gnupg_options( const char *buf, size_t buflen )
514 {
515 FILE *fp;
516 char *optfile = NULL;
517
518 optfile = get_gnupg_cfgfile( );
519 if( optfile == NULL )
520 return WPTERR_FILE_CREAT;
521
522 fp = fopen( optfile, "wb" );
523 if( fp == NULL ) {
524 free_if_alloc( optfile );
525 return WPTERR_FILE_CREAT;
526 }
527 fwrite( buf, 1, buflen, fp );
528 fclose( fp );
529 free_if_alloc( optfile );
530 return 0;
531 } /* set_gnupg_options */
532
533 /*
534 * Check if the line contains a valid GPG argument.
535 */
536 static int
537 check_line( const char *buf )
538 {
539 int j, len;
540 int rc = 0;
541
542 if( *buf == '#' || *buf == '\r' || *buf == '\n' )
543 return 1;
544 rc = 0;
545 for ( j = 0; valid_gpg_args[j]; j++ ) {
546 len = strlen( valid_gpg_args[j] );
547 if( !strncmp( valid_gpg_args[j], buf, len ) )
548 rc = 1;
549 }
550
551 return rc;
552 } /* check_line */
553
554
555 int
556 check_gnupg_options( const char *buf )
557 {
558 char line[1024];
559 int nbytes = 0;
560 unsigned j;
561
562 for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {
563 line[nbytes++] = buf[j];
564 if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {
565 line[nbytes] = '\0';
566 if( !check_line( line ) ) {
567 msg_box( NULL, line, "options", MB_OK );
568 return 1;
569 }
570 nbytes = 0;
571 }
572 }
573
574 return 0;
575 } /* check_gnupg_options */
576
577
578 static int
579 get_last_gnupg_access (gpg_watcher_s * ctx)
580 {
581 HANDLE fd;
582 char *path = NULL, *file = NULL;
583
584 path = get_gnupg_path ();
585 file = make_filename (path, ctx->object, NULL);
586 fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
587 if( fd == INVALID_HANDLE_VALUE ) {
588 free_if_alloc (path);
589 free_if_alloc (file);
590 return WPTERR_FILE_OPEN;
591 }
592 GetFileTime (fd, NULL, NULL, &ctx->access);
593 CloseHandle (fd);
594 free_if_alloc (path);
595 free_if_alloc (file);
596 return 0;
597 } /* get_last_gnupg_access */
598
599
600 static void
601 check_last_gnupg_access( gpg_watcher_s *ctx )
602 {
603 ctx->modified = 0;
604
605 if( ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
606 ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime )
607 ctx->modified = 1;
608
609 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
610 ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
611 } /* check_last_gnupg_access */
612
613
614 void
615 init_gnupg_table (void)
616 {
617 int j;
618
619 for (j = 0; j < gpg_table_count; j++) {
620 gpg_table[j].object = m_strdup (gpg_objs[j]);
621 memset (&gpg_table[j].access, 0, sizeof (FILETIME));
622 memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
623 gpg_table[j].modified = 0;
624 }
625 } /* init_gnupg_table */
626
627
628 void
629 free_gnupg_table (void)
630 {
631 int j;
632
633 for (j=0; j < gpg_table_count; j++)
634 free_if_alloc (gpg_table[j].object);
635 } /* free_gnupg_table */
636
637
638 int
639 keyring_check_last_access (void)
640 {
641 int rc, j;
642
643 rc = 0;
644 for (j = 0; j < gpg_table_count; j++) {
645 get_last_gnupg_access( &gpg_table[j] );
646 check_last_gnupg_access( &gpg_table[j] );
647 if ( gpg_table[j].modified )
648 rc++;
649 }
650
651 return rc;
652 } /* keyring_check_last_access */
653
654
655 const char *
656 gnupg_check_file_ext (const char * fname)
657 {
658 char file_ext[5];
659
660 if (!strchr( fname, '.' ))
661 return "UNKNOWN";
662
663 strncpy (file_ext, fname + strlen (fname) - 4, 4);
664 file_ext[4] = '\0';
665 if (!stricmp (file_ext, ".asc"))
666 return "ARMORED";
667 else if (!stricmp (file_ext, ".sig"))
668 return "SIGNED";
669 else if (!stricmp (file_ext, ".gpg")
670 || !stricmp (file_ext, ".pgp"))
671 return "ENCRYPTED";
672 else
673 return "UNKNOWN";
674
675 return "UNKNOWN";
676 } /* gnupg_check_file_ext */
677
678
679 char *
680 get_gnupg_keyring_from_options (const char * fname, int pub)
681 {
682 gpg_optfile_t opt;
683 gpg_option_t e;
684 char * kring = NULL;
685 int rc = 0;
686
687 rc = parse_gpg_options (fname, &opt);
688 if (rc)
689 return NULL;
690 if (pub)
691 e = find_option (opt, "keyring");
692 else
693 e = find_option (opt, "secret-keyring");
694 if (e)
695 kring = m_strdup (e->val);
696 release_gpg_options (opt);
697
698 return kring;
699 } /* get_gnupg_keyring_from_options */
700
701
702
703 /* XXX: does not work with write-protected floppies */
704 static int
705 my_access (const char * fname)
706 {
707 HANDLE hd;
708 hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
709 if (hd == INVALID_HANDLE_VALUE)
710 return -1;
711 CloseHandle (hd);
712 return 0;
713 } /* my_access */
714
715
716 int
717 gpg_check_permissions (int showmsg)
718 {
719 char * p, * name = NULL;
720 int failed = 0, ans=0, attrs=0;
721
722 p = get_gnupg_path ();
723 check_keyring (&p);
724 if (p) {
725 name = make_filename (p, "pubring", "gpg");
726 free_if_alloc (p);
727 if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
728 ans = msg_box (NULL,
729 _("The selected keyring has the read-only file\n"
730 "attribute. In this state you do not have write\n"
731 "access. Do you want to remove the attribute?"),
732 _("GPG Information"), MB_YESNO);
733 if (ans == IDYES) {
734 attrs &= ~FILE_ATTRIBUTE_READONLY;
735 if (!SetFileAttributes (name, attrs)) {
736 msg_box (NULL, _("Could not reset read-only state."),
737 _("GPG Error"), MB_ERR);
738 failed = 1;
739 }
740 }
741 else if (ans == IDNO) {
742 /*
743 msg_box (NULL, _("All commands with write access to the keyring\n"
744 "will be disabled."), _("GPG Information"), MB_INFO);
745 */
746 failed = 1;
747 }
748 }
749 if (my_access (name)) {
750 if (showmsg)
751 msg_box (NULL,
752 _("You do not have file access to modify the contents of\n"
753 "one or both of the selected keyrings.\n"
754 "\n"
755 "The keyrings are in a read-only state which is propably\n"
756 "caused by another program which already opened the files.\n"),
757 _("GPG Warning"), MB_WARN);
758 failed = 2;
759 }
760 }
761 free_if_alloc (name);
762 return failed;
763 } /* gpg_check_permissions */
764
765
766 static int
767 check_homedir (void)
768 {
769 char * homedir = NULL;
770 int yes = 0;
771
772 homedir = get_reg_entry_gpg ("HomeDir");
773 if (!homedir)
774 homedir = multi_gnupg_path ();
775 if (!homedir)
776 homedir = m_strdup ("c:\\gnupg");
777 if (homedir) {
778 if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
779 yes = log_box (_("Preferences"), MB_YESNO,
780 _("%s does not exit.\n"
781 "Do you want to create this directory?"), homedir);
782 if (yes == IDYES) {
783 if (CreateDirectory (homedir, NULL) == FALSE) {
784 free_if_alloc (homedir);
785 return WPTERR_DIR_CREAT;
786 }
787 }
788 return WPTERR_DIR_OPEN;
789 }
790 free_if_alloc (homedir);
791 }
792 return 0;
793 } /* check_homedir */
794
795
796 int
797 gnupg_check_homedir (void)
798 {
799 char *homedir = NULL, *prog = NULL;
800 int rc = 0, ec = 0;
801
802 rc = check_homedir ();
803 if (rc)
804 return rc;
805 if ((homedir = get_reg_entry_gpg ("HomeDir")) &&
806 !(prog = get_reg_entry_gpg ("gpgProgram" ))) {
807 prog = make_filename (homedir, "gpg", "exe");
808 if (file_exist_check (prog) == 0) {
809 rc = set_reg_entry_gpg ("gpgProgram", prog);
810 if (rc)
811 goto fail;
812 }
813 free_if_alloc (homedir);
814 free_if_alloc (prog);
815 return rc;
816 }
817 if ((prog = get_reg_entry_gpg ("gpgProgram"))
818 && file_exist_check (prog)) {
819 free_if_alloc (prog);
820 homedir = get_reg_entry_gpg ("HomeDir");
821 if (!homedir) {
822 rc = WPTERR_GENERAL;
823 goto fail;
824 }
825 prog = make_filename (homedir, "gpg", "exe");
826 if (file_exist_check (prog) == 0) {
827 rc = set_reg_entry_gpg ("gpgProgram", prog);
828 if (rc)
829 goto fail;
830 free_if_alloc (prog);
831 return rc;
832 }
833 }
834
835 /* Change the return code if homedir doesn't exist or if the program
836 doesn't exist. Note that exist_checks return 0 to suggest existance. */
837 if ((!homedir || dir_exist_check (homedir)))
838 rc = WPTERR_GENERAL;
839
840 fail:
841 free_if_alloc (homedir);
842 free_if_alloc (prog);
843 return rc;
844 } /* gnupg_check_homedir */
845
846
847 int
848 gnupg_copy_keyrings (void)
849 {
850 const char * pring, * sring;
851 char * file = NULL, * path = NULL;
852 int id = 0, rc = 0;
853 HWND hwnd;
854
855 path = get_gnupg_path ();
856 if (!path)
857 return WPTERR_GENERAL;
858 hwnd = GetDesktopWindow ();
859
860 pring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your public keyring"),
861 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
862 if (!pring) {
863 msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
864 free_if_alloc (path);
865 return WPTERR_GENERAL;
866 }
867 file = make_filename (path, "pubring", "gpg");
868 if (file_exist_check (file) == 0) {
869 id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
870 if (id == IDNO)
871 goto fail;
872 }
873 if (!CopyFile (pring, file, FALSE)) {
874 msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
875 rc = WPTERR_FILE_READ;
876 goto fail;
877 }
878 free_if_alloc (file);
879
880 sring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your secret keyring"),
881 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
882 if (!sring) {
883 msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
884 return WPTERR_GENERAL;
885 }
886 file = make_filename (path, "secring", "gpg");
887 if (file_exist_check (file) == 0) {
888 id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
889 if( id == IDNO )
890 goto fail;
891 }
892 if (!CopyFile (sring, file, FALSE)) {
893 msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
894 rc = WPTERR_FILE_READ;
895 }
896
897 fail:
898 free_if_alloc (file);
899 free_if_alloc (path);
900 return rc;
901 } /* gnupg_import_keyrings */
902
903
904 void
905 gnupg_backup_options (void)
906 {
907 char *cfgfile = NULL;
908 char bak[512];
909
910 cfgfile = get_gnupg_cfgfile ();
911 if (cfgfile == NULL)
912 return;
913 _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
914 CopyFile (cfgfile, bak, FALSE);
915 free_if_alloc (cfgfile);
916 } /* gnupg_backup_options */
917
918
919
920 static int
921 backup_one_file (const char * srcpath, const char * srcn,
922 const char * dstpath, const char * dstn)
923 {
924 char * src, * dst;
925 BOOL rc;
926
927 src = make_filename (srcpath, srcn, "gpg");
928 if (!src)
929 BUG (NULL);
930 dst = make_filename (dstpath, dstn, "gpg");
931 if (!dst)
932 BUG (NULL);
933 rc = CopyFile (src, dst, FALSE);
934 free_if_alloc (src);
935 free_if_alloc (dst);
936 if (!rc)
937 {
938 log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
939 return WPTERR_GENERAL;
940 }
941 return 0;
942 } /* backup_one_file */
943
944
945 static int
946 check_keyring (char ** r_path)
947 {
948 char * p;
949 char * opt, * name;
950
951 if (!*r_path)
952 return 0;
953 p = make_filename (*r_path, "pubring", "gpg");
954 if (!p || get_file_size (p) > 0)
955 return 0;
956
957 opt = get_gnupg_cfgfile ();
958 if (!opt)
959 BUG (0);
960 name = get_gnupg_keyring_from_options (opt, 1);
961 free_if_alloc (opt);
962 free_if_alloc (p);
963 if (!name)
964 return 0;
965 p = strrchr (name, '\\');
966 if (!p)
967 {
968 free_if_alloc (name);
969 return 0;
970 }
971 free_if_alloc (*r_path);
972 *r_path = new char [strlen (name)+1];
973 memset (*r_path, 0, strlen (name));
974 strncpy (*r_path, name, (p-name));
975 free_if_alloc (name);
976 return 1;
977 }
978
979
980 static char*
981 get_backup_name (const char *templ)
982 {
983 struct tm *tm;
984 char *p;
985
986 time_t t = time (NULL);
987 tm = localtime (&t);
988 p = new char [strlen (templ) + 8 + 1];
989 if (!p)
990 BUG (0);
991 sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
992 return p;
993 }
994
995
996 void
997 gnupg_backup_keyrings (void)
998 {
999 char *srcpath = NULL, *dstpath = NULL;
1000 char *name=NULL;
1001 int rc, bakmode=0;
1002
1003 if (!reg_prefs.auto_backup)
1004 return;
1005 bakmode = reg_prefs.backup.mode;
1006 srcpath = get_gnupg_path ();
1007 check_keyring (&srcpath);
1008 if (bakmode == 1) {
1009 dstpath = get_gnupg_path ();
1010 check_keyring (&dstpath);
1011 }
1012 else if (bakmode == 2) {
1013 char * tmpfile;
1014 FILE * fp;
1015
1016 dstpath = m_strdup (reg_prefs.backup.path);
1017 if (!dstpath)
1018 BUG (0);
1019 tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1020 fp = fopen (tmpfile, "wb");
1021 if (!fp)
1022 rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL, _("The backup drive '%s' does not seems to accessable.\n"
1023 "Please insert/check the drive to continue."), dstpath);
1024 else {
1025 rc = 0;
1026 fclose (fp);
1027 unlink (tmpfile);
1028 }
1029 free_if_alloc (tmpfile);
1030 if (!fp || rc == IDCANCEL)
1031 return;
1032 }
1033 else {
1034 log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1035 return;
1036 }
1037 name = get_backup_name ("pubring-bak");
1038 rc = backup_one_file (srcpath, "pubring", dstpath, name);
1039 if (!rc)
1040 rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1041 free_if_alloc (name);
1042 free_if_alloc (srcpath);
1043 free_if_alloc (dstpath);
1044 } /* gnupg_backup_keyrings */
1045
1046
1047 void
1048 gnupg_display_error (void)
1049 {
1050 char tmpath[512], * errstr;
1051 size_t size = 0;
1052 FILE * fp;
1053
1054 GetTempPath (sizeof tmpath - 32, (tmpath));
1055 strcat (tmpath, "gpg_stderr");
1056 size = get_file_size (tmpath);
1057 if (file_exist_check (tmpath) || size <= 0)
1058 return;
1059 fp = fopen( tmpath, "rb" );
1060 if (!fp) {
1061 msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );
1062 return;
1063 }
1064 errstr = new char[size+1];
1065 if (!errstr)
1066 BUG (0);
1067 fread (errstr, 1, size, fp);
1068 errstr[size] = '\0';
1069 fclose (fp);
1070 msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1071 free_if_alloc (errstr);
1072 } /* gnupg_display_error */
1073
1074
1075 int
1076 gnupg_access_keyring (int _pub)
1077 {
1078 int rc = 0;
1079 char * name = get_gnupg_keyring (_pub, 1);
1080 if (file_exist_check (name))
1081 rc = -1;
1082 free_if_alloc (name);
1083 return rc;
1084 }
1085

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26