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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 137 - (hide annotations)
Mon Jan 9 14:01:51 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26591 byte(s)
2006-01-09  Timo Schulz  <ts@g10code.com>
 
        * WinPT.cpp (load_gettext): Remove file locking.
        (WinMain): Use pre-defined autoconf constants.
        * wptW32API.cpp (init_file_lock, release_file_lock): Deleted.
        * wptGPG.cpp (check_gnupg_engine): Add param @need_gpg_ver.
        Change all callers.

Remove all static version constants. The only place for
constants is now configure.c (config.h).


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26