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

Contents of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26674 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26