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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (hide annotations)
Thu Nov 3 17:55:18 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26017 byte(s)
Fix crash in the GPG preference dialog.
Allow to have an empty secret keyring.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26