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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations)
Sat Nov 5 12:28:12 2005 UTC (19 years, 3 months ago) by twoaday
File size: 25988 byte(s)
More minor fixes...

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26