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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations)
Fri Oct 28 07:15:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 25941 byte(s)
A lot of bug fixes. See ChangeLog.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26