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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 137 - (show annotations)
Mon Jan 9 14:01:51 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26591 byte(s)
2006-01-09  Timo Schulz  <ts@g10code.com>
 
        * WinPT.cpp (load_gettext): Remove file locking.
        (WinMain): Use pre-defined autoconf constants.
        * wptW32API.cpp (init_file_lock, release_file_lock): Deleted.
        * wptGPG.cpp (check_gnupg_engine): Add param @need_gpg_ver.
        Change all callers.

Remove all static version constants. The only place for
constants is now configure.c (config.h).


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 (const char *need_gpg_ver,
357 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 need_major = 0, need_minor = 0, need_patch = 0;
364 int rc = 1;
365
366 /* Convert the needed GPG version to the integer format. */
367 rc = parse_version_nr (need_gpg_ver,
368 &need_major, &need_minor, &need_patch);
369 if (rc)
370 return rc;
371
372 gpgme_new (&ctx);
373 inf = gpgme_ctx_get_engine_info (ctx);
374 if (!inf) {
375 gpgme_release (ctx);
376 return -1;
377 }
378
379 /* We need to exec GPG again to find out if IDEA is available. */
380 if (gpg_get_version (&eng))
381 return -1;
382 if (strstr (eng, "IDEA"))
383 idea_available = 1;
384 free (eng);
385 rc = parse_version_nr (inf->version, &major, &minor, &patch);
386 if (rc) {
387 gpgme_release (ctx);
388 return rc;
389 }
390
391 if (major > need_major)
392 rc = 0;
393 else if (major == need_major && minor > need_minor)
394 rc = 0;
395 else if (major == need_major && minor == need_minor &&
396 patch >= need_patch)
397 rc = 0;
398
399 /* Return the current GPG version. */
400 *r_major = major;
401 *r_minor = minor;
402 *r_patch = patch;
403 return rc;
404 }
405
406
407 int
408 check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)
409 {
410 gpg_optfile_t opt;
411 gpg_option_t e;
412 int rc = 0;
413
414 *r_secrings = 0;
415 *r_pubrings = 0;
416 rc = parse_gpg_options( fname, &opt );
417 if( rc )
418 return WPTERR_FILE_OPEN;
419
420 for( e = opt->list; e; e = e->next ) {
421 if( !strcmp( e->name, "secret-keyring" ) ) {
422 if( !file_exist_check( e->val ) )
423 r_secrings[0]++;
424 }
425 else if( !strcmp( e->name, "keyring" ) ) {
426 if( !file_exist_check( e->val ) )
427 r_pubrings[0]++;
428 }
429 }
430 release_gpg_options( opt );
431 return 0;
432 } /* check_gnupg_cfgfile */
433
434
435 /* Usually GPG creates the pubring.gpg, secring.gpg on
436 the first start, but to make sure they always exist
437 create them empty if needed. */
438 static void
439 create_empty_keyring (int _pub)
440 {
441 char *name;
442 FILE *f;
443
444 name = get_gnupg_keyring (_pub, 0);
445 if (file_exist_check (name) != 0) {
446 f = fopen (name, "ab");
447 if (f != NULL)
448 fclose (f);
449 }
450 free_if_alloc (name);
451 }
452
453
454 /* Check if both keyrings are located in the gnupg home directory. */
455 int
456 gnupg_access_files (void)
457 {
458 int rc = 0;
459 int pubring_ok = 0, secring_ok = 0;
460 int secrings = 0, pubrings = 0;
461 char *optfile;
462
463 create_empty_keyring (1);
464 if (gnupg_access_keyring (1))
465 rc = WPTERR_GPG_KEYRINGS;
466 else
467 pubring_ok = 1;
468
469 create_empty_keyring (0);
470 if (gnupg_access_keyring (0))
471 rc = WPTERR_GPG_KEYRINGS;
472 else
473 secring_ok = 1;
474
475 if (!pubring_ok || !secring_ok) {
476 optfile = get_gnupg_cfgfile ();
477 if (!optfile)
478 return WPTERR_GPG_KEYRINGS;
479 rc = file_exist_check (optfile);
480 if (!rc && get_file_size (optfile) > 0) {
481 rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);
482 if (!rc && secrings && pubrings) {
483 free_if_alloc (optfile);
484 return 0; /* found two keyrings in the option file */
485 }
486 else if ((!rc && pubrings && secring_ok)
487 || (!rc && secrings && pubring_ok)) {
488 free_if_alloc (optfile);
489 return 0; /* found one keyring and one entry in the options file */
490 }
491 else
492 return WPTERR_GPG_OPT_KEYRINGS;
493 }
494 free_if_alloc (optfile);
495 rc = WPTERR_GPG_KEYRINGS;
496 }
497 return rc;
498 }
499
500
501 static int
502 create_gpg_options (void)
503 {
504 FILE *fp;
505 char *s, *optfile;
506
507 s = get_gnupg_path ();
508 if( s == NULL )
509 return WPTERR_FILE_CREAT;
510 optfile = make_filename (s, GPG_CONF, NULL);
511 fp = fopen (optfile, "wb");
512 if (fp == NULL) {
513 return WPTERR_FILE_CREAT;
514 goto fail;
515 }
516 fwrite (options_skel, 1, strlen (options_skel), fp);
517 fclose (fp);
518
519 fail:
520 free_if_alloc (s);
521 free_if_alloc (optfile);
522 return 0;
523 } /* create_gpg_options */
524
525
526 /*
527 * Return the contents of the options file as a char buf.
528 */
529 char *
530 get_gnupg_config (void)
531 {
532 FILE * fp;
533 char * p = NULL, * optfile = NULL;
534 int fsize, rc = 0;
535
536 optfile = get_gnupg_cfgfile ();
537 if( optfile == NULL )
538 return NULL;
539 fsize = get_file_size( optfile );
540 if( !fsize ) {
541 rc = create_gpg_options( );
542 if ( rc )
543 return NULL;
544 fsize = get_file_size( optfile );
545 }
546 if( fsize > 100000 )
547 goto leave; /* too large */
548 p = new char[fsize+1];
549 if( p == NULL )
550 BUG( NULL );
551 fp = fopen( optfile, "rb" );
552 if( fp == NULL ) {
553 free_if_alloc( p );
554 return NULL;
555 }
556 fread( p, 1, fsize, fp );
557 fclose( fp );
558 p[fsize] = '\0';
559 free_if_alloc( optfile );
560
561 leave:
562 return p;
563 } /* get_gnupg_config */
564
565
566 int
567 set_gnupg_default_key (const char * key)
568 {
569 gpg_optfile_t opt;
570 gpg_option_t e;
571 char *optfile = NULL;
572 int rc = 0;
573
574 optfile = get_gnupg_cfgfile ();
575 if (!optfile)
576 return -1;
577 rc = parse_gpg_options (optfile, &opt);
578 if( rc ) {
579 free_if_alloc (optfile);
580 return -1;
581 }
582 e = find_option (opt, "default-key");
583 if (e) {
584 free_if_alloc (e->val);
585 e->val = m_strdup (key);
586 e->used = 1;
587 }
588 else
589 add_entry (opt, ENTRY_MULTI, "default-key", key);
590 rc = commit_gpg_options (optfile, opt);
591
592 free_if_alloc (optfile);
593 release_gpg_options (opt);
594
595 return rc;
596 } /* set_gnupg_default_key */
597
598
599 /*
600 * Set the contents of the options file.
601 */
602 int
603 set_gnupg_options( const char *buf, size_t buflen )
604 {
605 FILE *fp;
606 char *optfile = NULL;
607
608 optfile = get_gnupg_cfgfile( );
609 if( optfile == NULL )
610 return WPTERR_FILE_CREAT;
611
612 fp = fopen( optfile, "wb" );
613 if( fp == NULL ) {
614 free_if_alloc( optfile );
615 return WPTERR_FILE_CREAT;
616 }
617 fwrite( buf, 1, buflen, fp );
618 fclose( fp );
619 free_if_alloc( optfile );
620 return 0;
621 } /* set_gnupg_options */
622
623 /*
624 * Check if the line contains a valid GPG argument.
625 */
626 static int
627 check_line( const char *buf )
628 {
629 int j, len;
630 int rc = 0;
631
632 if( *buf == '#' || *buf == '\r' || *buf == '\n' )
633 return 1;
634 rc = 0;
635 for ( j = 0; valid_gpg_args[j]; j++ ) {
636 len = strlen( valid_gpg_args[j] );
637 if( !strncmp( valid_gpg_args[j], buf, len ) )
638 rc = 1;
639 }
640
641 return rc;
642 } /* check_line */
643
644
645 int
646 check_gnupg_options( const char *buf )
647 {
648 char line[1024];
649 int nbytes = 0;
650 unsigned j;
651
652 for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {
653 line[nbytes++] = buf[j];
654 if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {
655 line[nbytes] = '\0';
656 if( !check_line( line ) ) {
657 msg_box( NULL, line, "options", MB_OK );
658 return 1;
659 }
660 nbytes = 0;
661 }
662 }
663
664 return 0;
665 } /* check_gnupg_options */
666
667
668 /* Store the last access of the file inside the watcher @ctx. */
669 static int
670 get_last_gnupg_access (gpg_watcher_s *ctx)
671 {
672 HANDLE fd;
673 char *path;
674 char *file;
675
676 path = get_gnupg_path ();
677 file = make_filename (path, ctx->object, NULL);
678 fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
679 if (fd == INVALID_HANDLE_VALUE) {
680 free_if_alloc (path);
681 free_if_alloc (file);
682 return WPTERR_FILE_OPEN;
683 }
684 GetFileTime (fd, NULL, NULL, &ctx->access);
685 CloseHandle (fd);
686 free_if_alloc (path);
687 free_if_alloc (file);
688 return 0;
689 }
690
691
692 /* Check if the file inside watcher @ctx was modified. */
693 static void
694 check_last_gnupg_access (gpg_watcher_s *ctx)
695 {
696 ctx->modified = 0;
697
698 if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
699 ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
700 ctx->modified = 1;
701
702 /* XXX: find a better way. without it, winpt --keymanager loads
703 the key cache twice. */
704 if (ctx->last_access.dwLowDateTime == 0)
705 ctx->modified = 0;
706
707 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
708 ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
709 }
710
711
712 /* Init GPG watcher table for all monitored files. */
713 void
714 init_gnupg_table (void)
715 {
716 char *p;
717 int j;
718
719 for (j = 0; j < gpg_table_count; j++) {
720 p = gpg_table[j].object = m_strdup (gpg_objs[j]);
721 if (!p)
722 BUG (NULL);
723 memset (&gpg_table[j].access, 0, sizeof (FILETIME));
724 memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
725 gpg_table[j].modified = 0;
726 }
727 }
728
729
730 void
731 free_gnupg_table (void)
732 {
733 int j;
734
735 for (j=0; j < gpg_table_count; j++)
736 free_if_alloc (gpg_table[j].object);
737 }
738
739
740 /* Return the amount of files modified since the last call. */
741 int
742 keyring_check_last_access (void)
743 {
744 int rc, j;
745
746 rc = 0;
747 for (j = 0; j < gpg_table_count; j++) {
748 get_last_gnupg_access (&gpg_table[j]);
749 check_last_gnupg_access (&gpg_table[j]);
750 if (gpg_table[j].modified)
751 rc++;
752 }
753
754 return rc;
755 }
756
757
758 const char*
759 gnupg_check_file_ext (const char *fname, int *r_type)
760 {
761 char file_ext[5];
762
763 if (r_type)
764 *r_type = PGP_NONE;
765 if (!strchr (fname, '.' ))
766 return "UNKNOWN";
767
768 strncpy (file_ext, fname + strlen (fname) - 4, 4);
769 file_ext[4] = '\0';
770 if (!stricmp (file_ext, ".asc"))
771 return "ARMORED";
772 else if (!stricmp (file_ext, ".sig")) {
773 if (r_type)
774 *r_type = PGP_SIG;
775 return "SIGNED";
776 }
777 else if (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
778 if (r_type)
779 *r_type = PGP_MESSAGE;
780 return "ENCRYPTED";
781 }
782 return "UNKNOWN";
783 }
784
785
786 char*
787 get_gnupg_keyring_from_options (const char * fname, int pub)
788 {
789 gpg_optfile_t opt;
790 gpg_option_t e;
791 char * kring = NULL;
792 int rc = 0;
793
794 rc = parse_gpg_options (fname, &opt);
795 if (rc)
796 return NULL;
797 if (pub)
798 e = find_option (opt, "keyring");
799 else
800 e = find_option (opt, "secret-keyring");
801 if (e)
802 kring = m_strdup (e->val);
803 release_gpg_options (opt);
804
805 return kring;
806 }
807
808
809
810 /* XXX: does not work with write-protected floppies */
811 static int
812 my_access (const char *fname)
813 {
814 HANDLE hd;
815 hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
816 NULL, OPEN_EXISTING, 0, NULL);
817 if (hd == INVALID_HANDLE_VALUE)
818 return -1;
819 CloseHandle (hd);
820 return 0;
821 }
822
823
824 /* Check the file permissions of the public keyring.
825 If @showmsg is 1 output a message in case of errors.
826 Return value: 1 if read-only attribute
827 2 if file is opened by another process exclusively. */
828 int
829 gpg_check_permissions (int showmsg)
830 {
831 char *p = NULL;
832 char *name = NULL;
833 int failed = 0, ans=0, attrs=0;
834
835 p = get_gnupg_path ();
836 if (check_keyring (&p) && p) {
837 name = make_filename (p, "pubring", "gpg");
838 if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
839 ans = msg_box (NULL,
840 _("The selected keyring has the read-only file\n"
841 "attribute. In this state you do not have write\n"
842 "access. Do you want to remove the attribute?"),
843 _("GPG Information"), MB_YESNO);
844 if (ans == IDYES) {
845 attrs &= ~FILE_ATTRIBUTE_READONLY;
846 if (!SetFileAttributes (name, attrs)) {
847 msg_box (NULL, _("Could not reset read-only state."),
848 _("GPG Error"), MB_ERR);
849 failed = 1;
850 }
851 }
852 else if (ans == IDNO) {
853 /* All commands with write access will be disabled. */
854 failed = 1;
855 }
856 }
857 if (my_access (name)) {
858 if (showmsg)
859 msg_box (NULL,
860 _("You do not have file access to modify the contents of\n"
861 "one or both of the selected keyrings.\n"
862 "\n"
863 "The keyrings are in a read-only state which is propably\n"
864 "caused by another program which already opened the files.\n"),
865 _("GPG Warning"), MB_WARN);
866 failed = 2;
867 }
868 }
869 free_if_alloc (p);
870 free_if_alloc (name);
871 return failed;
872 }
873
874
875 /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
876 then check for $APPDATA\gnupg. Create the dir if it does not exists. */
877 int
878 gnupg_check_homedir (void)
879 {
880 char *homedir = NULL;
881 int val = 0;
882 int rc = 0;
883
884 homedir = get_reg_entry_gpg (GPG_REG_HOME);
885 if (!homedir)
886 homedir = multi_gnupg_path (0);
887 if (homedir) {
888 if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
889 val = log_box (_("Preferences"), MB_YESNO,
890 _("%s does not exit.\n"
891 "Do you want to create this directory?"), homedir);
892 if (val == IDYES) {
893 if (!CreateDirectory (homedir, NULL))
894 rc = WPTERR_DIR_CREAT;
895 }
896 else
897 rc = WPTERR_DIR_OPEN;
898 }
899 free_if_alloc (homedir);
900 }
901 return rc;
902 }
903
904
905 int
906 gnupg_copy_keyrings (void)
907 {
908 const char * pring, * sring;
909 char * file = NULL, * path = NULL;
910 int id = 0, rc = 0;
911 HWND hwnd;
912
913 path = get_gnupg_path ();
914 if (!path)
915 return WPTERR_GENERAL;
916 hwnd = GetDesktopWindow ();
917
918 pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
919 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
920 if (!pring) {
921 msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
922 free_if_alloc (path);
923 return WPTERR_GENERAL;
924 }
925 file = make_filename (path, "pubring", "gpg");
926 if (file_exist_check (file) == 0) {
927 id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
928 if (id == IDNO)
929 goto fail;
930 }
931 if (!CopyFile (pring, file, FALSE)) {
932 msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
933 rc = WPTERR_FILE_READ;
934 goto fail;
935 }
936 free_if_alloc (file);
937
938 sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
939 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
940 if (!sring) {
941 msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
942 return WPTERR_GENERAL;
943 }
944 file = make_filename (path, "secring", "gpg");
945 if (file_exist_check (file) == 0) {
946 id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
947 if( id == IDNO )
948 goto fail;
949 }
950 if (!CopyFile (sring, file, FALSE)) {
951 msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
952 rc = WPTERR_FILE_READ;
953 }
954
955 fail:
956 free_if_alloc (file);
957 free_if_alloc (path);
958 return rc;
959 } /* gnupg_import_keyrings */
960
961
962 /* Backup the gpg.conf file. */
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)
971 return;
972 _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
973 CopyFile (cfgfile, bak, FALSE);
974 free_if_alloc (cfgfile);
975 }
976
977
978 static int
979 backup_one_file (const char *srcpath, const char *srcn,
980 const char *dstpath, const char *dstn)
981 {
982 char * src, * dst;
983 BOOL rc;
984
985 src = make_filename (srcpath, srcn, "gpg");
986 if (!src)
987 BUG (NULL);
988 dst = make_filename (dstpath, dstn, "gpg");
989 if (!dst)
990 BUG (NULL);
991 rc = CopyFile (src, dst, FALSE);
992 free_if_alloc (src);
993 free_if_alloc (dst);
994 if (!rc)
995 {
996 log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
997 return WPTERR_GENERAL;
998 }
999 return 0;
1000 } /* backup_one_file */
1001
1002
1003 /* Figure out first public keyring which is not empty.
1004 Return value: 1 on success. */
1005 static int
1006 check_keyring (char **r_path)
1007 {
1008 char *p;
1009 char *opt;
1010 char *name;
1011
1012 if (!*r_path)
1013 return 0;
1014 p = make_filename (*r_path, "pubring", "gpg");
1015 if (!p || get_file_size (p) <= 0)
1016 return 0;
1017
1018 opt = get_gnupg_cfgfile ();
1019 if (!opt)
1020 BUG (0);
1021 name = get_gnupg_keyring_from_options (opt, 1);
1022 free_if_alloc (opt);
1023 free_if_alloc (p);
1024 if (!name)
1025 return 0;
1026 p = strrchr (name, '\\');
1027 if (!p) {
1028 free_if_alloc (name);
1029 return 0;
1030 }
1031 free_if_alloc (*r_path);
1032 *r_path = new char [strlen (name)+1];
1033 memset (*r_path, 0, strlen (name));
1034 strncpy (*r_path, name, (p-name));
1035 free_if_alloc (name);
1036 return 1;
1037 }
1038
1039
1040 /* Return a temp name based on the day of the week. */
1041 static char*
1042 get_backup_name (const char *templ)
1043 {
1044 struct tm *tm;
1045 char *p;
1046 time_t t;
1047
1048 t = time (NULL);
1049 tm = localtime (&t);
1050 p = new char [strlen (templ) + 8 + 1];
1051 if (!p)
1052 BUG (0);
1053 sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1054 return p;
1055 }
1056
1057
1058 /* Make backups of all keyrings. The public key ring is
1059 rotated like this pubring-%d.gpg. */
1060 void
1061 gnupg_backup_keyrings (void)
1062 {
1063 char *srcpath = NULL, *dstpath = NULL;
1064 char *name=NULL;
1065 int rc, bakmode=0;
1066
1067 if (!reg_prefs.auto_backup)
1068 return;
1069 bakmode = reg_prefs.backup.mode;
1070 srcpath = get_gnupg_path ();
1071 check_keyring (&srcpath);
1072 if (bakmode == 1) {
1073 dstpath = multi_gnupg_path (1);
1074 check_keyring (&dstpath);
1075 }
1076 else if (bakmode == 2) {
1077 char *tmpfile;
1078 FILE *fp;
1079
1080 dstpath = m_strdup (reg_prefs.backup.path);
1081 if (!dstpath)
1082 BUG (0);
1083 tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1084 fp = fopen (tmpfile, "wb");
1085 if (!fp)
1086 rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1087 _("The backup drive '%s' does not seems to accessable.\n"
1088 "Please insert/check the drive to continue."), dstpath);
1089 else {
1090 rc = 0;
1091 fclose (fp);
1092 remove (tmpfile);
1093 }
1094 free_if_alloc (tmpfile);
1095 if (!fp || rc == IDCANCEL)
1096 return;
1097 }
1098 else {
1099 log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1100 return;
1101 }
1102 name = get_backup_name ("pubring-bak");
1103 rc = backup_one_file (srcpath, "pubring", dstpath, name);
1104 if (!rc)
1105 rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1106 free_if_alloc (name);
1107 free_if_alloc (srcpath);
1108 free_if_alloc (dstpath);
1109 }
1110
1111
1112 /* Display GPG error from file if possible. */
1113 void
1114 gnupg_display_error (void)
1115 {
1116 char tmpath[512], * errstr;
1117 size_t size = 0;
1118 FILE * fp;
1119
1120 GetTempPath (sizeof tmpath - 32, (tmpath));
1121 strcat (tmpath, "gpg_stderr");
1122 size = get_file_size (tmpath);
1123 if (file_exist_check (tmpath) || size <= 0)
1124 return;
1125 fp = fopen( tmpath, "rb" );
1126 if (!fp) {
1127 msg_box (NULL, _("No GPG error description available."),
1128 _("GPG Error"), MB_INFO);
1129 return;
1130 }
1131 errstr = new char[size+1];
1132 if (!errstr)
1133 BUG (0);
1134 fread (errstr, 1, size, fp);
1135 errstr[size] = '\0';
1136 fclose (fp);
1137 msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1138 free_if_alloc (errstr);
1139 }
1140
1141
1142
1143 /* check that the requested GPG keyring exist and.
1144 Return value: 0 for success. */
1145 int
1146 gnupg_access_keyring (int _pub)
1147 {
1148 int rc = 0;
1149 char *name = get_gnupg_keyring (_pub, 1);
1150 if (!name || file_exist_check (name))
1151 rc = -1;
1152 free_if_alloc (name);
1153 return rc;
1154 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26