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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (hide annotations)
Mon Jan 9 09:15:29 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26270 byte(s)
A lot of minor bug fixes.
New icons.

For a complete history, see the ChangeLog entries.


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     parse_version_nr (const char * buf, int *major, int *minor, int *patch)
329     {
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     check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)
357     {
358     gpgme_ctx_t ctx;
359     gpgme_engine_info_t inf;
360 twoaday 78 char *eng = NULL;
361 werner 36 int major=0, minor=0, patch=0;
362 twoaday 78 int rc = 1;
363 werner 36
364     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 78 rc = parse_version_nr (inf->version, &major, &minor, &patch);
378     if (rc) {
379 werner 36 gpgme_release (ctx);
380     return rc;
381     }
382 twoaday 78
383     if (major > *r_major)
384 werner 36 rc = 0;
385 twoaday 78 else if (major == *r_major && minor > *r_minor)
386     rc = 0;
387     else if (major == *r_major && minor == *r_minor &&
388     patch >= *r_patch)
389     rc = 0;
390    
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 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
911     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 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
931     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