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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (show annotations)
Mon Jan 9 09:15:29 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26270 byte(s)
A lot of minor bug fixes.
New icons.

For a complete history, see the ChangeLog entries.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26