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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 58 - (show annotations)
Wed Nov 2 13:36:03 2005 UTC (19 years, 3 months ago) by werner
File size: 26094 byte(s)
Add comments and a README.SVN

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26