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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations)
Fri Oct 28 08:25:30 2005 UTC (19 years, 4 months ago) by werner
File size: 26011 byte(s)
Readded lost changes from revision 40

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26