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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations)
Fri Oct 28 07:15:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 25941 byte(s)
A lot of bug fixes. See ChangeLog.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26