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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Fri Oct 28 08:25:30 2005 UTC (19 years, 4 months ago) by werner
File size: 26011 byte(s)
Readded lost changes from revision 40

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26