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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 78 - (hide annotations)
Tue Nov 15 08:54:44 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26813 byte(s)
2005-11-14  Timo Schulz  <ts@g10code.com>
 
        * wptGPG.cpp (check_gnupg_engine): Fix version check.
        * wptMainProc.cpp (winpt_main_proc): Check keyring
        file permissions always and do not use interative output
        when the windows session ends.
        * wptProxySettingsDlg.cpp (proxy_settings_dlg_proc):
        Localize all strings.
        * wptPassphraseDlg.cpp (passwd_dlg_proc): Likewise.
        * wptGPGPrefsDlg.cpp (gpg_prefs_dlg): Likewise.
        * wptKeyEditDlgs.cpp (do_init_keylist): Skip all
        non-valid keys.
         


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26