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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 78 - (show annotations)
Tue Nov 15 08:54:44 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26813 byte(s)
2005-11-14  Timo Schulz  <ts@g10code.com>
 
        * wptGPG.cpp (check_gnupg_engine): Fix version check.
        * wptMainProc.cpp (winpt_main_proc): Check keyring
        file permissions always and do not use interative output
        when the windows session ends.
        * wptProxySettingsDlg.cpp (proxy_settings_dlg_proc):
        Localize all strings.
        * wptPassphraseDlg.cpp (passwd_dlg_proc): Likewise.
        * wptGPGPrefsDlg.cpp (gpg_prefs_dlg): Likewise.
        * wptKeyEditDlgs.cpp (do_init_keylist): Skip all
        non-valid keys.
         


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26