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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 167 - (hide annotations)
Thu Jan 26 10:17:17 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26374 byte(s)
2006-01-25  Timo Schulz  <ts@g10code.com>
 
        * wptRegistry.cpp (get_reg_entry_gpg): Return NULL if
        the key exist with no value.
        * wptMDSumDlg.cpp (mdsum_dlg_proc): Translate string.
        * wptKeysignDlg.cpp (do_fill_seclist): Select the
        default key if possible.
        * wptFirstRunDlg.cpp (firstrun_dlg_proc): Directly
        return the choice.
        * wptKeylist.cpp (get_key_desc): New.
        (keylist_upd_key): Free memory.
        * wptKeyCache.cpp (gpg_keycache_get_default_key): New.
        (gpg_keycache_set_default_key): New.
        * WinPT.cpp (gpg_prefs_ok): New.
        (WinMain): Only start gpg prefs if needed.
         


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