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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 85 - (show annotations)
Fri Nov 18 07:20:40 2005 UTC (19 years, 3 months ago) by twoaday
File size: 27001 byte(s)
2005-11-17  Timo Schulz  <ts@g10code.com>
 
        * wptGPG.cpp (check_last_gnupg_access): Kludge to avoid that
        the cache will be loaded twice.
        * wptRegistry.cpp (regist_inst_winpt): More comments.
        * wptKeyManagerDlg.cpp (do_center_window): Make sure that
        neg. coordinates are never used.
        * wptClipVerifyDlg.cpp (clip_verify_dlg_proc): Localize all
        strings.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Likewise.
        * wptFileManagerDlg.cpp (filemanager_dlg_proc): Localize menu
        and save 'AlwaysOnTop' in the registry.
         

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 /* XXX: find a better way. without it, winpt --keymanager loads
676 the key cache twice otherwise. */
677 if (ctx->last_access.dwLowDateTime == 0)
678 ctx->modified = 0;
679
680 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
681 ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
682 }
683
684
685 /* Init GPG watcher table for all monitored files. */
686 void
687 init_gnupg_table (void)
688 {
689 char *p;
690 int j;
691
692 for (j = 0; j < gpg_table_count; j++) {
693 p = gpg_table[j].object = m_strdup (gpg_objs[j]);
694 if (!p)
695 BUG (NULL);
696 memset (&gpg_table[j].access, 0, sizeof (FILETIME));
697 memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
698 gpg_table[j].modified = 0;
699 }
700 }
701
702
703 void
704 free_gnupg_table (void)
705 {
706 int j;
707
708 for (j=0; j < gpg_table_count; j++)
709 free_if_alloc (gpg_table[j].object);
710 }
711
712
713 /* Return the amount of files modified since the last call. */
714 int
715 keyring_check_last_access (void)
716 {
717 int rc, j;
718
719 rc = 0;
720 for (j = 0; j < gpg_table_count; j++) {
721 get_last_gnupg_access (&gpg_table[j]);
722 check_last_gnupg_access (&gpg_table[j]);
723 if (gpg_table[j].modified)
724 rc++;
725 }
726
727 return rc;
728 }
729
730
731 const char*
732 gnupg_check_file_ext (const char *fname, int *r_type)
733 {
734 char file_ext[5];
735
736 if (r_type)
737 *r_type = PGP_NONE;
738 if (!strchr (fname, '.' ))
739 return "UNKNOWN";
740
741 strncpy (file_ext, fname + strlen (fname) - 4, 4);
742 file_ext[4] = '\0';
743 if (!stricmp (file_ext, ".asc"))
744 return "ARMORED";
745 else if (!stricmp (file_ext, ".sig")) {
746 if (r_type)
747 *r_type = PGP_SIG;
748 return "SIGNED";
749 }
750 else if (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
751 if (r_type)
752 *r_type = PGP_MESSAGE;
753 return "ENCRYPTED";
754 }
755 return "UNKNOWN";
756 }
757
758
759 char*
760 get_gnupg_keyring_from_options (const char * fname, int pub)
761 {
762 gpg_optfile_t opt;
763 gpg_option_t e;
764 char * kring = NULL;
765 int rc = 0;
766
767 rc = parse_gpg_options (fname, &opt);
768 if (rc)
769 return NULL;
770 if (pub)
771 e = find_option (opt, "keyring");
772 else
773 e = find_option (opt, "secret-keyring");
774 if (e)
775 kring = m_strdup (e->val);
776 release_gpg_options (opt);
777
778 return kring;
779 }
780
781
782
783 /* XXX: does not work with write-protected floppies */
784 static int
785 my_access (const char * fname)
786 {
787 HANDLE hd;
788 hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
789 NULL, OPEN_EXISTING, 0, NULL);
790 if (hd == INVALID_HANDLE_VALUE)
791 return -1;
792 CloseHandle (hd);
793 return 0;
794 }
795
796
797 /* Check the file permissions of the public keyring.
798 If @showmsg is 1 output a message in case of errors.
799 Return value: 1 if read-only attribute
800 2 if file is opened by another process exclusively. */
801 int
802 gpg_check_permissions (int showmsg)
803 {
804 char * p, * name = NULL;
805 int failed = 0, ans=0, attrs=0;
806
807 p = get_gnupg_path ();
808 check_keyring (&p);
809 if (p) {
810 name = make_filename (p, "pubring", "gpg");
811 free_if_alloc (p);
812 if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
813 ans = msg_box (NULL,
814 _("The selected keyring has the read-only file\n"
815 "attribute. In this state you do not have write\n"
816 "access. Do you want to remove the attribute?"),
817 _("GPG Information"), MB_YESNO);
818 if (ans == IDYES) {
819 attrs &= ~FILE_ATTRIBUTE_READONLY;
820 if (!SetFileAttributes (name, attrs)) {
821 msg_box (NULL, _("Could not reset read-only state."),
822 _("GPG Error"), MB_ERR);
823 failed = 1;
824 }
825 }
826 else if (ans == IDNO) {
827 /* All commands with write access will be disabled. */
828 failed = 1;
829 }
830 }
831 if (my_access (name)) {
832 if (showmsg)
833 msg_box (NULL,
834 _("You do not have file access to modify the contents of\n"
835 "one or both of the selected keyrings.\n"
836 "\n"
837 "The keyrings are in a read-only state which is propably\n"
838 "caused by another program which already opened the files.\n"),
839 _("GPG Warning"), MB_WARN);
840 failed = 2;
841 }
842 }
843 free_if_alloc (name);
844 return failed;
845 }
846
847
848 /* Check the GPG home dir. If all methods failed, try to
849 create the default folder. */
850 static int
851 check_homedir (void)
852 {
853 char *homedir = NULL;
854 int yes = 0, set_reg=0;
855 int rc = 0;
856
857 homedir = get_reg_entry_gpg (GPG_REG_HOME);
858 if (!homedir) {
859 set_reg = 1;
860 homedir = multi_gnupg_path (0);
861 }
862 if (!homedir)
863 homedir = m_strdup ("c:\\gnupg");
864 if (homedir) {
865 if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
866 yes = log_box (_("Preferences"), MB_YESNO,
867 _("%s does not exit.\n"
868 "Do you want to create this directory?"), homedir);
869 if (yes == IDYES) {
870 if (!CreateDirectory (homedir, NULL))
871 rc = WPTERR_DIR_CREAT;
872 }
873 else
874 rc = WPTERR_DIR_OPEN;
875 }
876 if (set_reg)
877 set_reg_entry_gpg (GPG_REG_HOME, homedir);
878 free_if_alloc (homedir);
879 }
880 return rc;
881 }
882
883
884 int
885 gnupg_check_homedir (void)
886 {
887 char *homedir = NULL;
888 char *prog = NULL;
889 int rc = 0;
890
891 rc = check_homedir ();
892 if (rc)
893 return rc;
894 if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&
895 !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {
896 prog = make_filename (homedir, "gpg", "exe");
897 if (file_exist_check (prog) == 0) {
898 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
899 if (rc)
900 goto fail;
901 }
902 free_if_alloc (homedir);
903 free_if_alloc (prog);
904 return rc;
905 }
906 if ((prog = get_reg_entry_gpg (GPG_REG_EXE))
907 && file_exist_check (prog)) {
908 free_if_alloc (prog);
909 homedir = get_reg_entry_gpg (GPG_REG_HOME);
910 if (!homedir) {
911 rc = WPTERR_GENERAL;
912 goto fail;
913 }
914 prog = make_filename (homedir, "gpg", "exe");
915 if (file_exist_check (prog) == 0) {
916 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
917 if (rc)
918 goto fail;
919 free_if_alloc (prog);
920 return rc;
921 }
922 }
923
924 /* Change the return code if homedir doesn't exist or if the program
925 doesn't exist. Note that exist_checks return 0 to suggest existance. */
926 if ((!homedir || dir_exist_check (homedir)))
927 rc = WPTERR_GENERAL;
928
929 fail:
930 free_if_alloc (homedir);
931 free_if_alloc (prog);
932 return rc;
933 } /* gnupg_check_homedir */
934
935
936 int
937 gnupg_copy_keyrings (void)
938 {
939 const char * pring, * sring;
940 char * file = NULL, * path = NULL;
941 int id = 0, rc = 0;
942 HWND hwnd;
943
944 path = get_gnupg_path ();
945 if (!path)
946 return WPTERR_GENERAL;
947 hwnd = GetDesktopWindow ();
948
949 pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
950 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
951 if (!pring) {
952 msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
953 free_if_alloc (path);
954 return WPTERR_GENERAL;
955 }
956 file = make_filename (path, "pubring", "gpg");
957 if (file_exist_check (file) == 0) {
958 id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
959 if (id == IDNO)
960 goto fail;
961 }
962 if (!CopyFile (pring, file, FALSE)) {
963 msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
964 rc = WPTERR_FILE_READ;
965 goto fail;
966 }
967 free_if_alloc (file);
968
969 sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
970 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
971 if (!sring) {
972 msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
973 return WPTERR_GENERAL;
974 }
975 file = make_filename (path, "secring", "gpg");
976 if (file_exist_check (file) == 0) {
977 id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
978 if( id == IDNO )
979 goto fail;
980 }
981 if (!CopyFile (sring, file, FALSE)) {
982 msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
983 rc = WPTERR_FILE_READ;
984 }
985
986 fail:
987 free_if_alloc (file);
988 free_if_alloc (path);
989 return rc;
990 } /* gnupg_import_keyrings */
991
992
993 void
994 gnupg_backup_options (void)
995 {
996 char *cfgfile = NULL;
997 char bak[512];
998
999 cfgfile = get_gnupg_cfgfile ();
1000 if (cfgfile == NULL)
1001 return;
1002 _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
1003 CopyFile (cfgfile, bak, FALSE);
1004 free_if_alloc (cfgfile);
1005 } /* gnupg_backup_options */
1006
1007
1008
1009 static int
1010 backup_one_file (const char *srcpath, const char *srcn,
1011 const char *dstpath, const char *dstn)
1012 {
1013 char * src, * dst;
1014 BOOL rc;
1015
1016 src = make_filename (srcpath, srcn, "gpg");
1017 if (!src)
1018 BUG (NULL);
1019 dst = make_filename (dstpath, dstn, "gpg");
1020 if (!dst)
1021 BUG (NULL);
1022 rc = CopyFile (src, dst, FALSE);
1023 free_if_alloc (src);
1024 free_if_alloc (dst);
1025 if (!rc)
1026 {
1027 log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1028 return WPTERR_GENERAL;
1029 }
1030 return 0;
1031 } /* backup_one_file */
1032
1033
1034 static int
1035 check_keyring (char ** r_path)
1036 {
1037 char * p;
1038 char * opt, * name;
1039
1040 if (!*r_path)
1041 return 0;
1042 p = make_filename (*r_path, "pubring", "gpg");
1043 if (!p || get_file_size (p) > 0)
1044 return 0;
1045
1046 opt = get_gnupg_cfgfile ();
1047 if (!opt)
1048 BUG (0);
1049 name = get_gnupg_keyring_from_options (opt, 1);
1050 free_if_alloc (opt);
1051 free_if_alloc (p);
1052 if (!name)
1053 return 0;
1054 p = strrchr (name, '\\');
1055 if (!p)
1056 {
1057 free_if_alloc (name);
1058 return 0;
1059 }
1060 free_if_alloc (*r_path);
1061 *r_path = new char [strlen (name)+1];
1062 memset (*r_path, 0, strlen (name));
1063 strncpy (*r_path, name, (p-name));
1064 free_if_alloc (name);
1065 return 1;
1066 }
1067
1068
1069 static char*
1070 get_backup_name (const char *templ)
1071 {
1072 struct tm *tm;
1073 char *p;
1074
1075 time_t t = time (NULL);
1076 tm = localtime (&t);
1077 p = new char [strlen (templ) + 8 + 1];
1078 if (!p)
1079 BUG (0);
1080 sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1081 return p;
1082 }
1083
1084
1085 void
1086 gnupg_backup_keyrings (void)
1087 {
1088 char *srcpath = NULL, *dstpath = NULL;
1089 char *name=NULL;
1090 int rc, bakmode=0;
1091
1092 if (!reg_prefs.auto_backup)
1093 return;
1094 bakmode = reg_prefs.backup.mode;
1095 srcpath = get_gnupg_path ();
1096 check_keyring (&srcpath);
1097 if (bakmode == 1) {
1098 dstpath = get_gnupg_path ();
1099 check_keyring (&dstpath);
1100 }
1101 else if (bakmode == 2) {
1102 char * tmpfile;
1103 FILE * fp;
1104
1105 dstpath = m_strdup (reg_prefs.backup.path);
1106 if (!dstpath)
1107 BUG (0);
1108 tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1109 fp = fopen (tmpfile, "wb");
1110 if (!fp)
1111 rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1112 _("The backup drive '%s' does not seems to accessable.\n"
1113 "Please insert/check the drive to continue."), dstpath);
1114 else {
1115 rc = 0;
1116 fclose (fp);
1117 remove (tmpfile);
1118 }
1119 free_if_alloc (tmpfile);
1120 if (!fp || rc == IDCANCEL)
1121 return;
1122 }
1123 else {
1124 log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1125 return;
1126 }
1127 name = get_backup_name ("pubring-bak");
1128 rc = backup_one_file (srcpath, "pubring", dstpath, name);
1129 if (!rc)
1130 rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1131 free_if_alloc (name);
1132 free_if_alloc (srcpath);
1133 free_if_alloc (dstpath);
1134 } /* gnupg_backup_keyrings */
1135
1136
1137 /* Display GPG error from file if possible. */
1138 void
1139 gnupg_display_error (void)
1140 {
1141 char tmpath[512], * errstr;
1142 size_t size = 0;
1143 FILE * fp;
1144
1145 GetTempPath (sizeof tmpath - 32, (tmpath));
1146 strcat (tmpath, "gpg_stderr");
1147 size = get_file_size (tmpath);
1148 if (file_exist_check (tmpath) || size <= 0)
1149 return;
1150 fp = fopen( tmpath, "rb" );
1151 if (!fp) {
1152 msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );
1153 return;
1154 }
1155 errstr = new char[size+1];
1156 if (!errstr)
1157 BUG (0);
1158 fread (errstr, 1, size, fp);
1159 errstr[size] = '\0';
1160 fclose (fp);
1161 msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1162 free_if_alloc (errstr);
1163 }
1164
1165
1166
1167 /* check that the requested GPG keyring exist and.
1168 Return value: 0 for success. */
1169 int
1170 gnupg_access_keyring (int _pub)
1171 {
1172 int rc = 0;
1173 char *name = get_gnupg_keyring (_pub, 1);
1174 if (!name || file_exist_check (name))
1175 rc = -1;
1176 free_if_alloc (name);
1177 return rc;
1178 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26