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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26