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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 179 - (hide annotations)
Fri Feb 24 13:12:26 2006 UTC (19 years ago) by twoaday
File size: 26472 byte(s)
Prepare 0.11.8


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 twoaday 179 /* Set the default key in the gpg.conf.
558     If @key is NULL, the entry will be deleted. */
559 werner 36 int
560 twoaday 179 set_gnupg_default_key (const char *key)
561 werner 36 {
562     gpg_optfile_t opt;
563     gpg_option_t e;
564     char *optfile = NULL;
565     int rc = 0;
566    
567     optfile = get_gnupg_cfgfile ();
568     if (!optfile)
569 twoaday 179 return WPTERR_FILE_OPEN;
570 werner 36 rc = parse_gpg_options (optfile, &opt);
571 twoaday 179 if (rc) {
572 werner 36 free_if_alloc (optfile);
573 twoaday 179 return WPTERR_GENERAL;
574 werner 36 }
575     e = find_option (opt, "default-key");
576 twoaday 179 if (e && !key)
577     e->used = 0;
578     else if (e) {
579 werner 36 free_if_alloc (e->val);
580     e->val = m_strdup (key);
581     e->used = 1;
582     }
583     else
584     add_entry (opt, ENTRY_MULTI, "default-key", key);
585     rc = commit_gpg_options (optfile, opt);
586    
587     free_if_alloc (optfile);
588     release_gpg_options (opt);
589    
590     return rc;
591 twoaday 179 }
592 werner 36
593    
594     /*
595     * Set the contents of the options file.
596     */
597     int
598     set_gnupg_options( const char *buf, size_t buflen )
599     {
600     FILE *fp;
601     char *optfile = NULL;
602    
603     optfile = get_gnupg_cfgfile( );
604     if( optfile == NULL )
605     return WPTERR_FILE_CREAT;
606    
607     fp = fopen( optfile, "wb" );
608     if( fp == NULL ) {
609     free_if_alloc( optfile );
610     return WPTERR_FILE_CREAT;
611     }
612     fwrite( buf, 1, buflen, fp );
613     fclose( fp );
614     free_if_alloc( optfile );
615     return 0;
616     } /* set_gnupg_options */
617    
618     /*
619     * Check if the line contains a valid GPG argument.
620     */
621     static int
622     check_line( const char *buf )
623     {
624     int j, len;
625     int rc = 0;
626    
627     if( *buf == '#' || *buf == '\r' || *buf == '\n' )
628     return 1;
629     rc = 0;
630     for ( j = 0; valid_gpg_args[j]; j++ ) {
631     len = strlen( valid_gpg_args[j] );
632     if( !strncmp( valid_gpg_args[j], buf, len ) )
633     rc = 1;
634     }
635    
636     return rc;
637     } /* check_line */
638    
639    
640     int
641     check_gnupg_options( const char *buf )
642     {
643     char line[1024];
644     int nbytes = 0;
645     unsigned j;
646    
647     for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {
648     line[nbytes++] = buf[j];
649     if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {
650     line[nbytes] = '\0';
651     if( !check_line( line ) ) {
652     msg_box( NULL, line, "options", MB_OK );
653     return 1;
654     }
655     nbytes = 0;
656     }
657     }
658    
659     return 0;
660     } /* check_gnupg_options */
661    
662    
663     /* Store the last access of the file inside the watcher @ctx. */
664     static int
665     get_last_gnupg_access (gpg_watcher_s *ctx)
666     {
667     HANDLE fd;
668     char *path;
669     char *file;
670    
671     path = get_gnupg_path ();
672     file = make_filename (path, ctx->object, NULL);
673     fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
674     if (fd == INVALID_HANDLE_VALUE) {
675     free_if_alloc (path);
676     free_if_alloc (file);
677     return WPTERR_FILE_OPEN;
678     }
679     GetFileTime (fd, NULL, NULL, &ctx->access);
680     CloseHandle (fd);
681     free_if_alloc (path);
682     free_if_alloc (file);
683     return 0;
684     }
685    
686    
687     /* Check if the file inside watcher @ctx was modified. */
688     static void
689     check_last_gnupg_access (gpg_watcher_s *ctx)
690     {
691     ctx->modified = 0;
692    
693     if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
694     ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
695     ctx->modified = 1;
696 twoaday 85
697     /* XXX: find a better way. without it, winpt --keymanager loads
698 twoaday 117 the key cache twice. */
699 twoaday 85 if (ctx->last_access.dwLowDateTime == 0)
700     ctx->modified = 0;
701 twoaday 117
702 werner 36 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
703     ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
704     }
705    
706    
707     /* Init GPG watcher table for all monitored files. */
708     void
709     init_gnupg_table (void)
710     {
711     char *p;
712     int j;
713    
714     for (j = 0; j < gpg_table_count; j++) {
715     p = gpg_table[j].object = m_strdup (gpg_objs[j]);
716     if (!p)
717     BUG (NULL);
718     memset (&gpg_table[j].access, 0, sizeof (FILETIME));
719     memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
720     gpg_table[j].modified = 0;
721     }
722     }
723    
724    
725     void
726     free_gnupg_table (void)
727     {
728     int j;
729    
730     for (j=0; j < gpg_table_count; j++)
731     free_if_alloc (gpg_table[j].object);
732     }
733    
734    
735     /* Return the amount of files modified since the last call. */
736     int
737     keyring_check_last_access (void)
738     {
739     int rc, j;
740    
741     rc = 0;
742     for (j = 0; j < gpg_table_count; j++) {
743     get_last_gnupg_access (&gpg_table[j]);
744     check_last_gnupg_access (&gpg_table[j]);
745     if (gpg_table[j].modified)
746     rc++;
747     }
748    
749     return rc;
750     }
751    
752    
753     const char*
754     gnupg_check_file_ext (const char *fname, int *r_type)
755     {
756     char file_ext[5];
757    
758     if (r_type)
759     *r_type = PGP_NONE;
760     if (!strchr (fname, '.' ))
761     return "UNKNOWN";
762    
763     strncpy (file_ext, fname + strlen (fname) - 4, 4);
764     file_ext[4] = '\0';
765     if (!stricmp (file_ext, ".asc"))
766     return "ARMORED";
767     else if (!stricmp (file_ext, ".sig")) {
768     if (r_type)
769     *r_type = PGP_SIG;
770     return "SIGNED";
771     }
772     else if (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
773     if (r_type)
774     *r_type = PGP_MESSAGE;
775     return "ENCRYPTED";
776     }
777     return "UNKNOWN";
778     }
779    
780    
781     char*
782     get_gnupg_keyring_from_options (const char * fname, int pub)
783     {
784     gpg_optfile_t opt;
785     gpg_option_t e;
786     char * kring = NULL;
787     int rc = 0;
788    
789     rc = parse_gpg_options (fname, &opt);
790     if (rc)
791     return NULL;
792     if (pub)
793     e = find_option (opt, "keyring");
794     else
795     e = find_option (opt, "secret-keyring");
796     if (e)
797     kring = m_strdup (e->val);
798     release_gpg_options (opt);
799    
800     return kring;
801     }
802    
803    
804    
805     /* XXX: does not work with write-protected floppies */
806     static int
807 twoaday 128 my_access (const char *fname)
808 werner 36 {
809     HANDLE hd;
810     hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
811     NULL, OPEN_EXISTING, 0, NULL);
812     if (hd == INVALID_HANDLE_VALUE)
813     return -1;
814     CloseHandle (hd);
815     return 0;
816     }
817    
818    
819 twoaday 78 /* Check the file permissions of the public keyring.
820     If @showmsg is 1 output a message in case of errors.
821     Return value: 1 if read-only attribute
822     2 if file is opened by another process exclusively. */
823 werner 36 int
824     gpg_check_permissions (int showmsg)
825     {
826 twoaday 128 char *p = NULL;
827     char *name = NULL;
828 werner 36 int failed = 0, ans=0, attrs=0;
829    
830     p = get_gnupg_path ();
831 twoaday 128 if (check_keyring (&p) && p) {
832 werner 36 name = make_filename (p, "pubring", "gpg");
833     if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
834     ans = msg_box (NULL,
835     _("The selected keyring has the read-only file\n"
836     "attribute. In this state you do not have write\n"
837     "access. Do you want to remove the attribute?"),
838     _("GPG Information"), MB_YESNO);
839     if (ans == IDYES) {
840     attrs &= ~FILE_ATTRIBUTE_READONLY;
841     if (!SetFileAttributes (name, attrs)) {
842     msg_box (NULL, _("Could not reset read-only state."),
843     _("GPG Error"), MB_ERR);
844     failed = 1;
845     }
846     }
847     else if (ans == IDNO) {
848 twoaday 78 /* All commands with write access will be disabled. */
849 werner 36 failed = 1;
850     }
851     }
852     if (my_access (name)) {
853     if (showmsg)
854     msg_box (NULL,
855     _("You do not have file access to modify the contents of\n"
856     "one or both of the selected keyrings.\n"
857     "\n"
858     "The keyrings are in a read-only state which is propably\n"
859     "caused by another program which already opened the files.\n"),
860     _("GPG Warning"), MB_WARN);
861     failed = 2;
862     }
863     }
864 twoaday 128 free_if_alloc (p);
865 werner 36 free_if_alloc (name);
866     return failed;
867 twoaday 78 }
868 werner 36
869    
870 twoaday 128 /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
871     then check for $APPDATA\gnupg. Create the dir if it does not exists. */
872     int
873     gnupg_check_homedir (void)
874 werner 36 {
875     char *homedir = NULL;
876 twoaday 128 int val = 0;
877 twoaday 73 int rc = 0;
878 werner 36
879 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
880 twoaday 128 if (!homedir)
881 twoaday 73 homedir = multi_gnupg_path (0);
882 werner 36 if (homedir) {
883     if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
884 twoaday 128 val = log_box (_("Preferences"), MB_YESNO,
885 werner 36 _("%s does not exit.\n"
886     "Do you want to create this directory?"), homedir);
887 twoaday 128 if (val == IDYES) {
888 twoaday 73 if (!CreateDirectory (homedir, NULL))
889     rc = WPTERR_DIR_CREAT;
890 werner 36 }
891 twoaday 73 else
892     rc = WPTERR_DIR_OPEN;
893 werner 36 }
894     free_if_alloc (homedir);
895     }
896 twoaday 73 return rc;
897 werner 36 }
898    
899    
900     int
901     gnupg_copy_keyrings (void)
902     {
903     const char * pring, * sring;
904     char * file = NULL, * path = NULL;
905     int id = 0, rc = 0;
906     HWND hwnd;
907    
908     path = get_gnupg_path ();
909     if (!path)
910     return WPTERR_GENERAL;
911     hwnd = GetDesktopWindow ();
912    
913 twoaday 77 pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
914 twoaday 167 "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);
915 werner 36 if (!pring) {
916     msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
917     free_if_alloc (path);
918     return WPTERR_GENERAL;
919     }
920     file = make_filename (path, "pubring", "gpg");
921     if (file_exist_check (file) == 0) {
922     id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
923     if (id == IDNO)
924     goto fail;
925     }
926     if (!CopyFile (pring, file, FALSE)) {
927     msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
928     rc = WPTERR_FILE_READ;
929     goto fail;
930     }
931     free_if_alloc (file);
932    
933 twoaday 77 sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
934 twoaday 167 "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
935 werner 36 if (!sring) {
936     msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
937     return WPTERR_GENERAL;
938     }
939     file = make_filename (path, "secring", "gpg");
940     if (file_exist_check (file) == 0) {
941     id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
942     if( id == IDNO )
943     goto fail;
944     }
945     if (!CopyFile (sring, file, FALSE)) {
946     msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
947     rc = WPTERR_FILE_READ;
948     }
949    
950     fail:
951     free_if_alloc (file);
952     free_if_alloc (path);
953     return rc;
954     } /* gnupg_import_keyrings */
955    
956    
957 twoaday 128 /* Backup the gpg.conf file. */
958 werner 36 void
959     gnupg_backup_options (void)
960     {
961     char *cfgfile = NULL;
962     char bak[512];
963    
964     cfgfile = get_gnupg_cfgfile ();
965 twoaday 128 if (!cfgfile)
966 werner 36 return;
967     _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
968     CopyFile (cfgfile, bak, FALSE);
969     free_if_alloc (cfgfile);
970 twoaday 128 }
971 werner 36
972    
973     static int
974     backup_one_file (const char *srcpath, const char *srcn,
975     const char *dstpath, const char *dstn)
976     {
977     char * src, * dst;
978     BOOL rc;
979    
980     src = make_filename (srcpath, srcn, "gpg");
981     if (!src)
982     BUG (NULL);
983     dst = make_filename (dstpath, dstn, "gpg");
984     if (!dst)
985     BUG (NULL);
986     rc = CopyFile (src, dst, FALSE);
987     free_if_alloc (src);
988     free_if_alloc (dst);
989     if (!rc)
990     {
991     log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
992     return WPTERR_GENERAL;
993     }
994     return 0;
995     } /* backup_one_file */
996    
997    
998 twoaday 128 /* Figure out first public keyring which is not empty.
999     Return value: 1 on success. */
1000 werner 36 static int
1001 twoaday 128 check_keyring (char **r_path)
1002 werner 36 {
1003 twoaday 128 char *p;
1004     char *opt;
1005     char *name;
1006 werner 36
1007     if (!*r_path)
1008     return 0;
1009     p = make_filename (*r_path, "pubring", "gpg");
1010 twoaday 128 if (!p || get_file_size (p) <= 0)
1011 werner 36 return 0;
1012    
1013     opt = get_gnupg_cfgfile ();
1014     if (!opt)
1015     BUG (0);
1016     name = get_gnupg_keyring_from_options (opt, 1);
1017     free_if_alloc (opt);
1018     free_if_alloc (p);
1019     if (!name)
1020     return 0;
1021     p = strrchr (name, '\\');
1022 twoaday 128 if (!p) {
1023 werner 36 free_if_alloc (name);
1024     return 0;
1025     }
1026     free_if_alloc (*r_path);
1027     *r_path = new char [strlen (name)+1];
1028     memset (*r_path, 0, strlen (name));
1029     strncpy (*r_path, name, (p-name));
1030     free_if_alloc (name);
1031     return 1;
1032     }
1033    
1034    
1035 twoaday 128 /* Return a temp name based on the day of the week. */
1036 werner 36 static char*
1037     get_backup_name (const char *templ)
1038     {
1039     struct tm *tm;
1040     char *p;
1041 twoaday 128 time_t t;
1042 werner 36
1043 twoaday 128 t = time (NULL);
1044 werner 36 tm = localtime (&t);
1045     p = new char [strlen (templ) + 8 + 1];
1046     if (!p)
1047     BUG (0);
1048     sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1049     return p;
1050     }
1051    
1052    
1053 twoaday 117 /* Make backups of all keyrings. The public key ring is
1054     rotated like this pubring-%d.gpg. */
1055 werner 36 void
1056     gnupg_backup_keyrings (void)
1057     {
1058     char *srcpath = NULL, *dstpath = NULL;
1059     char *name=NULL;
1060     int rc, bakmode=0;
1061    
1062     if (!reg_prefs.auto_backup)
1063     return;
1064     bakmode = reg_prefs.backup.mode;
1065 twoaday 117 srcpath = get_gnupg_path ();
1066 werner 36 check_keyring (&srcpath);
1067     if (bakmode == 1) {
1068 twoaday 117 dstpath = multi_gnupg_path (1);
1069 werner 36 check_keyring (&dstpath);
1070     }
1071     else if (bakmode == 2) {
1072 twoaday 117 char *tmpfile;
1073     FILE *fp;
1074 werner 36
1075     dstpath = m_strdup (reg_prefs.backup.path);
1076     if (!dstpath)
1077     BUG (0);
1078     tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1079     fp = fopen (tmpfile, "wb");
1080     if (!fp)
1081     rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1082     _("The backup drive '%s' does not seems to accessable.\n"
1083     "Please insert/check the drive to continue."), dstpath);
1084     else {
1085     rc = 0;
1086     fclose (fp);
1087 twoaday 73 remove (tmpfile);
1088 werner 36 }
1089     free_if_alloc (tmpfile);
1090     if (!fp || rc == IDCANCEL)
1091     return;
1092     }
1093     else {
1094     log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1095     return;
1096     }
1097     name = get_backup_name ("pubring-bak");
1098     rc = backup_one_file (srcpath, "pubring", dstpath, name);
1099     if (!rc)
1100     rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1101     free_if_alloc (name);
1102     free_if_alloc (srcpath);
1103     free_if_alloc (dstpath);
1104 twoaday 117 }
1105 werner 36
1106    
1107     /* Display GPG error from file if possible. */
1108     void
1109     gnupg_display_error (void)
1110     {
1111 twoaday 175 char tmpath[512], *errstr;
1112 werner 36 size_t size = 0;
1113 twoaday 175 FILE *fp;
1114 werner 36
1115 twoaday 175 get_temp_name (tmpath, sizeof (tmpath), "gpg_stderr");
1116 werner 36 size = get_file_size (tmpath);
1117     if (file_exist_check (tmpath) || size <= 0)
1118     return;
1119     fp = fopen( tmpath, "rb" );
1120     if (!fp) {
1121 twoaday 128 msg_box (NULL, _("No GPG error description available."),
1122     _("GPG Error"), MB_INFO);
1123 werner 36 return;
1124     }
1125     errstr = new char[size+1];
1126     if (!errstr)
1127     BUG (0);
1128     fread (errstr, 1, size, fp);
1129     errstr[size] = '\0';
1130     fclose (fp);
1131     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1132     free_if_alloc (errstr);
1133     }
1134    
1135    
1136    
1137     /* check that the requested GPG keyring exist and.
1138     Return value: 0 for success. */
1139     int
1140     gnupg_access_keyring (int _pub)
1141     {
1142     int rc = 0;
1143     char *name = get_gnupg_keyring (_pub, 1);
1144     if (!name || file_exist_check (name))
1145     rc = -1;
1146     free_if_alloc (name);
1147     return rc;
1148     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26