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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (hide annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File size: 25674 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26