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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 58 - (hide annotations)
Wed Nov 2 13:36:03 2005 UTC (19 years, 3 months ago) by werner
File size: 26094 byte(s)
Add comments and a README.SVN

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26