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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 73 - (hide annotations)
Tue Nov 8 07:15:13 2005 UTC (19 years, 3 months ago) by twoaday
File size: 26698 byte(s)
2005-11-08  Timo Schulz  <ts@g10code.com>
 
        More minor changes to avoid GCC warnings.
         
        * wptGPG.cpp (check_homedir): Free memory in case of errors.
        (multi_gnupg_path): Add strict mode. If non-strict mode return
        the folder even if it does not exist.
        (check_for_gpgwin): New.
        * wptKeyserverDlg.cpp (hkp_recv_key): Make sure import_res is
        initialized.
        * wptRegistry.cpp (get_reg_entry_gpg4win): New.
        (get_reg_entry_mo): Support for gpg4win.
         
For complete changes see ChangeLogs.

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     return get_reg_entry_gpg4win ("\\gpg.exe");
304     }
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     while (buf && isdigit( *buf ) && i < 8)
346     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     char * eng = NULL;
362     int major=0, minor=0, patch=0;
363     int rc;
364    
365     gpgme_new (&ctx);
366     inf = gpgme_ctx_get_engine_info (ctx);
367     if (!inf) {
368     gpgme_release (ctx);
369     return -1;
370     }
371     /* 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     rc = parse_version_nr( inf->version, &major, &minor, &patch );
378     if( rc ) {
379     gpgme_release (ctx);
380     return rc;
381     }
382 werner 58 /* FIXME: This check is wrong! */
383 werner 36 if (major < *r_major || minor < *r_minor)
384     rc = 1;
385     else {
386     if (patch < *r_patch)
387     rc = 1;
388     rc = 0;
389     }
390     *r_major = major;
391     *r_minor = minor;
392     *r_patch = patch;
393     return rc;
394     }
395    
396    
397     int
398     check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)
399     {
400     gpg_optfile_t opt;
401     gpg_option_t e;
402     int rc = 0;
403    
404     *r_secrings = 0;
405     *r_pubrings = 0;
406     rc = parse_gpg_options( fname, &opt );
407     if( rc )
408     return WPTERR_FILE_OPEN;
409    
410     for( e = opt->list; e; e = e->next ) {
411     if( !strcmp( e->name, "secret-keyring" ) ) {
412     if( !file_exist_check( e->val ) )
413     r_secrings[0]++;
414     }
415     else if( !strcmp( e->name, "keyring" ) ) {
416     if( !file_exist_check( e->val ) )
417     r_pubrings[0]++;
418     }
419     }
420     release_gpg_options( opt );
421     return 0;
422     } /* check_gnupg_cfgfile */
423    
424    
425     /*
426     * Check if both keyrings are located in the gnupg home directory.
427     */
428     int
429     gnupg_access_files (void)
430     {
431     int rc = 0;
432     int pubring_ok = 0, secring_ok = 0;
433     int secrings = 0, pubrings = 0;
434     char *optfile;
435    
436     if (gnupg_access_keyring (1))
437     rc = WPTERR_GPG_KEYRINGS;
438     else
439     pubring_ok = 1;
440    
441     if (gnupg_access_keyring (0))
442     rc = WPTERR_GPG_KEYRINGS;
443     else
444     secring_ok = 1;
445 twoaday 73
446 werner 36 if (!pubring_ok || !secring_ok) {
447     optfile = get_gnupg_cfgfile ();
448     if (!optfile)
449     return WPTERR_GPG_KEYRINGS;
450     rc = file_exist_check (optfile);
451 twoaday 73 if (!rc && get_file_size (optfile) > 0) {
452 werner 36 rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);
453     if (!rc && secrings && pubrings) {
454     free_if_alloc (optfile);
455     return 0; /* found two keyrings in the option file */
456     }
457     else if ((!rc && pubrings && secring_ok)
458     || (!rc && secrings && pubring_ok)) {
459     free_if_alloc (optfile);
460     return 0; /* found one keyring and one entry in the options file */
461     }
462     else
463     return WPTERR_GPG_OPT_KEYRINGS;
464     }
465     free_if_alloc (optfile);
466     rc = WPTERR_GPG_KEYRINGS;
467     }
468     return rc;
469     } /* gnupg_access_files */
470    
471    
472     static int
473     create_gpg_options (void)
474     {
475     FILE *fp;
476     char *s, *optfile;
477    
478 twoaday 73 s = get_gnupg_path ();
479 werner 36 if( s == NULL )
480     return WPTERR_FILE_CREAT;
481 twoaday 73 optfile = make_filename (s, GPG_CONF, NULL);
482 werner 36 fp = fopen( optfile, "wb" );
483     if( fp == NULL ) {
484     return WPTERR_FILE_CREAT;
485     goto fail;
486     }
487     fwrite( options_skel, 1, strlen( options_skel ), fp );
488     fclose( fp );
489    
490     fail:
491     free_if_alloc( s );
492     free_if_alloc( optfile );
493     return 0;
494     } /* create_gpg_options */
495    
496    
497     /*
498     * Return the contents of the options file as a char buf.
499     */
500     char *
501     get_gnupg_config (void)
502     {
503     FILE * fp;
504     char * p = NULL, * optfile = NULL;
505     int fsize, rc = 0;
506    
507     optfile = get_gnupg_cfgfile ();
508     if( optfile == NULL )
509     return NULL;
510     fsize = get_file_size( optfile );
511     if( !fsize ) {
512     rc = create_gpg_options( );
513     if ( rc )
514     return NULL;
515     fsize = get_file_size( optfile );
516     }
517     if( fsize > 100000 )
518     goto leave; /* too large */
519     p = new char[fsize+1];
520     if( p == NULL )
521     BUG( NULL );
522     fp = fopen( optfile, "rb" );
523     if( fp == NULL ) {
524     free_if_alloc( p );
525     return NULL;
526     }
527     fread( p, 1, fsize, fp );
528     fclose( fp );
529     p[fsize] = '\0';
530     free_if_alloc( optfile );
531    
532     leave:
533     return p;
534     } /* get_gnupg_config */
535    
536    
537     int
538     set_gnupg_default_key (const char * key)
539     {
540     gpg_optfile_t opt;
541     gpg_option_t e;
542     char *optfile = NULL;
543     int rc = 0;
544    
545     optfile = get_gnupg_cfgfile ();
546     if (!optfile)
547     return -1;
548     rc = parse_gpg_options (optfile, &opt);
549     if( rc ) {
550     free_if_alloc (optfile);
551     return -1;
552     }
553     e = find_option (opt, "default-key");
554     if (e) {
555     free_if_alloc (e->val);
556     e->val = m_strdup (key);
557     e->used = 1;
558     }
559     else
560     add_entry (opt, ENTRY_MULTI, "default-key", key);
561     rc = commit_gpg_options (optfile, opt);
562    
563     free_if_alloc (optfile);
564     release_gpg_options (opt);
565    
566     return rc;
567     } /* set_gnupg_default_key */
568    
569    
570     /*
571     * Set the contents of the options file.
572     */
573     int
574     set_gnupg_options( const char *buf, size_t buflen )
575     {
576     FILE *fp;
577     char *optfile = NULL;
578    
579     optfile = get_gnupg_cfgfile( );
580     if( optfile == NULL )
581     return WPTERR_FILE_CREAT;
582    
583     fp = fopen( optfile, "wb" );
584     if( fp == NULL ) {
585     free_if_alloc( optfile );
586     return WPTERR_FILE_CREAT;
587     }
588     fwrite( buf, 1, buflen, fp );
589     fclose( fp );
590     free_if_alloc( optfile );
591     return 0;
592     } /* set_gnupg_options */
593    
594     /*
595     * Check if the line contains a valid GPG argument.
596     */
597     static int
598     check_line( const char *buf )
599     {
600     int j, len;
601     int rc = 0;
602    
603     if( *buf == '#' || *buf == '\r' || *buf == '\n' )
604     return 1;
605     rc = 0;
606     for ( j = 0; valid_gpg_args[j]; j++ ) {
607     len = strlen( valid_gpg_args[j] );
608     if( !strncmp( valid_gpg_args[j], buf, len ) )
609     rc = 1;
610     }
611    
612     return rc;
613     } /* check_line */
614    
615    
616     int
617     check_gnupg_options( const char *buf )
618     {
619     char line[1024];
620     int nbytes = 0;
621     unsigned j;
622    
623     for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {
624     line[nbytes++] = buf[j];
625     if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {
626     line[nbytes] = '\0';
627     if( !check_line( line ) ) {
628     msg_box( NULL, line, "options", MB_OK );
629     return 1;
630     }
631     nbytes = 0;
632     }
633     }
634    
635     return 0;
636     } /* check_gnupg_options */
637    
638    
639     /* Store the last access of the file inside the watcher @ctx. */
640     static int
641     get_last_gnupg_access (gpg_watcher_s *ctx)
642     {
643     HANDLE fd;
644     char *path;
645     char *file;
646    
647     path = get_gnupg_path ();
648     file = make_filename (path, ctx->object, NULL);
649     fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
650     if (fd == INVALID_HANDLE_VALUE) {
651     free_if_alloc (path);
652     free_if_alloc (file);
653     return WPTERR_FILE_OPEN;
654     }
655     GetFileTime (fd, NULL, NULL, &ctx->access);
656     CloseHandle (fd);
657     free_if_alloc (path);
658     free_if_alloc (file);
659     return 0;
660     }
661    
662    
663     /* Check if the file inside watcher @ctx was modified. */
664     static void
665     check_last_gnupg_access (gpg_watcher_s *ctx)
666     {
667     ctx->modified = 0;
668    
669     if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
670     ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
671     ctx->modified = 1;
672    
673     ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
674     ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
675     }
676    
677    
678     /* Init GPG watcher table for all monitored files. */
679     void
680     init_gnupg_table (void)
681     {
682     char *p;
683     int j;
684    
685     for (j = 0; j < gpg_table_count; j++) {
686     p = gpg_table[j].object = m_strdup (gpg_objs[j]);
687     if (!p)
688     BUG (NULL);
689     memset (&gpg_table[j].access, 0, sizeof (FILETIME));
690     memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
691     gpg_table[j].modified = 0;
692     }
693     }
694    
695    
696     void
697     free_gnupg_table (void)
698     {
699     int j;
700    
701     for (j=0; j < gpg_table_count; j++)
702     free_if_alloc (gpg_table[j].object);
703     }
704    
705    
706     /* Return the amount of files modified since the last call. */
707     int
708     keyring_check_last_access (void)
709     {
710     int rc, j;
711    
712     rc = 0;
713     for (j = 0; j < gpg_table_count; j++) {
714     get_last_gnupg_access (&gpg_table[j]);
715     check_last_gnupg_access (&gpg_table[j]);
716     if (gpg_table[j].modified)
717     rc++;
718     }
719    
720     return rc;
721     }
722    
723    
724     const char*
725     gnupg_check_file_ext (const char *fname, int *r_type)
726     {
727     char file_ext[5];
728    
729     if (r_type)
730     *r_type = PGP_NONE;
731     if (!strchr (fname, '.' ))
732     return "UNKNOWN";
733    
734     strncpy (file_ext, fname + strlen (fname) - 4, 4);
735     file_ext[4] = '\0';
736     if (!stricmp (file_ext, ".asc"))
737     return "ARMORED";
738     else if (!stricmp (file_ext, ".sig")) {
739     if (r_type)
740     *r_type = PGP_SIG;
741     return "SIGNED";
742     }
743     else if (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
744     if (r_type)
745     *r_type = PGP_MESSAGE;
746     return "ENCRYPTED";
747     }
748     return "UNKNOWN";
749     }
750    
751    
752     char*
753     get_gnupg_keyring_from_options (const char * fname, int pub)
754     {
755     gpg_optfile_t opt;
756     gpg_option_t e;
757     char * kring = NULL;
758     int rc = 0;
759    
760     rc = parse_gpg_options (fname, &opt);
761     if (rc)
762     return NULL;
763     if (pub)
764     e = find_option (opt, "keyring");
765     else
766     e = find_option (opt, "secret-keyring");
767     if (e)
768     kring = m_strdup (e->val);
769     release_gpg_options (opt);
770    
771     return kring;
772     }
773    
774    
775    
776     /* XXX: does not work with write-protected floppies */
777     static int
778     my_access (const char * fname)
779     {
780     HANDLE hd;
781     hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
782     NULL, OPEN_EXISTING, 0, NULL);
783     if (hd == INVALID_HANDLE_VALUE)
784     return -1;
785     CloseHandle (hd);
786     return 0;
787     }
788    
789    
790     int
791     gpg_check_permissions (int showmsg)
792     {
793     char * p, * name = NULL;
794     int failed = 0, ans=0, attrs=0;
795    
796     p = get_gnupg_path ();
797     check_keyring (&p);
798     if (p) {
799     name = make_filename (p, "pubring", "gpg");
800     free_if_alloc (p);
801     if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
802     ans = msg_box (NULL,
803     _("The selected keyring has the read-only file\n"
804     "attribute. In this state you do not have write\n"
805     "access. Do you want to remove the attribute?"),
806     _("GPG Information"), MB_YESNO);
807     if (ans == IDYES) {
808     attrs &= ~FILE_ATTRIBUTE_READONLY;
809     if (!SetFileAttributes (name, attrs)) {
810     msg_box (NULL, _("Could not reset read-only state."),
811     _("GPG Error"), MB_ERR);
812     failed = 1;
813     }
814     }
815     else if (ans == IDNO) {
816     /*
817     msg_box (NULL, _("All commands with write access to the keyring\n"
818     "will be disabled."), _("GPG Information"), MB_INFO);
819     */
820     failed = 1;
821     }
822     }
823     if (my_access (name)) {
824     if (showmsg)
825     msg_box (NULL,
826     _("You do not have file access to modify the contents of\n"
827     "one or both of the selected keyrings.\n"
828     "\n"
829     "The keyrings are in a read-only state which is propably\n"
830     "caused by another program which already opened the files.\n"),
831     _("GPG Warning"), MB_WARN);
832     failed = 2;
833     }
834     }
835     free_if_alloc (name);
836     return failed;
837     } /* gpg_check_permissions */
838    
839    
840     /* Check the GPG home dir. If all methods failed, try to
841     create the default folder. */
842     static int
843     check_homedir (void)
844     {
845     char *homedir = NULL;
846 twoaday 73 int yes = 0, set_reg=0;
847     int rc = 0;
848 werner 36
849 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
850     if (!homedir) {
851     set_reg = 1;
852     homedir = multi_gnupg_path (0);
853     }
854 werner 36 if (!homedir)
855     homedir = m_strdup ("c:\\gnupg");
856     if (homedir) {
857     if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
858     yes = log_box (_("Preferences"), MB_YESNO,
859     _("%s does not exit.\n"
860     "Do you want to create this directory?"), homedir);
861     if (yes == IDYES) {
862 twoaday 73 if (!CreateDirectory (homedir, NULL))
863     rc = WPTERR_DIR_CREAT;
864 werner 36 }
865 twoaday 73 else
866     rc = WPTERR_DIR_OPEN;
867 werner 36 }
868 twoaday 73 if (set_reg)
869     set_reg_entry_gpg (GPG_REG_HOME, homedir);
870 werner 36 free_if_alloc (homedir);
871     }
872 twoaday 73 return rc;
873 werner 36 }
874    
875    
876     int
877     gnupg_check_homedir (void)
878     {
879     char *homedir = NULL;
880     char *prog = NULL;
881 twoaday 69 int rc = 0;
882 werner 36
883     rc = check_homedir ();
884     if (rc)
885     return rc;
886 twoaday 73 if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&
887     !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {
888 werner 36 prog = make_filename (homedir, "gpg", "exe");
889     if (file_exist_check (prog) == 0) {
890 twoaday 73 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
891 werner 36 if (rc)
892     goto fail;
893     }
894     free_if_alloc (homedir);
895     free_if_alloc (prog);
896     return rc;
897     }
898 twoaday 73 if ((prog = get_reg_entry_gpg (GPG_REG_EXE))
899 werner 36 && file_exist_check (prog)) {
900     free_if_alloc (prog);
901 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
902 werner 36 if (!homedir) {
903     rc = WPTERR_GENERAL;
904     goto fail;
905     }
906     prog = make_filename (homedir, "gpg", "exe");
907     if (file_exist_check (prog) == 0) {
908 twoaday 73 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
909 werner 36 if (rc)
910     goto fail;
911     free_if_alloc (prog);
912     return rc;
913     }
914     }
915    
916     /* Change the return code if homedir doesn't exist or if the program
917     doesn't exist. Note that exist_checks return 0 to suggest existance. */
918     if ((!homedir || dir_exist_check (homedir)))
919     rc = WPTERR_GENERAL;
920    
921     fail:
922     free_if_alloc (homedir);
923     free_if_alloc (prog);
924     return rc;
925     } /* gnupg_check_homedir */
926    
927    
928     int
929     gnupg_copy_keyrings (void)
930     {
931     const char * pring, * sring;
932     char * file = NULL, * path = NULL;
933     int id = 0, rc = 0;
934     HWND hwnd;
935    
936     path = get_gnupg_path ();
937     if (!path)
938     return WPTERR_GENERAL;
939     hwnd = GetDesktopWindow ();
940    
941     pring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your public keyring"),
942     _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
943     if (!pring) {
944     msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
945     free_if_alloc (path);
946     return WPTERR_GENERAL;
947     }
948     file = make_filename (path, "pubring", "gpg");
949     if (file_exist_check (file) == 0) {
950     id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
951     if (id == IDNO)
952     goto fail;
953     }
954     if (!CopyFile (pring, file, FALSE)) {
955     msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
956     rc = WPTERR_FILE_READ;
957     goto fail;
958     }
959     free_if_alloc (file);
960    
961     sring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your secret keyring"),
962     _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
963     if (!sring) {
964     msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
965     return WPTERR_GENERAL;
966     }
967     file = make_filename (path, "secring", "gpg");
968     if (file_exist_check (file) == 0) {
969     id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
970     if( id == IDNO )
971     goto fail;
972     }
973     if (!CopyFile (sring, file, FALSE)) {
974     msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
975     rc = WPTERR_FILE_READ;
976     }
977    
978     fail:
979     free_if_alloc (file);
980     free_if_alloc (path);
981     return rc;
982     } /* gnupg_import_keyrings */
983    
984    
985     void
986     gnupg_backup_options (void)
987     {
988     char *cfgfile = NULL;
989     char bak[512];
990    
991     cfgfile = get_gnupg_cfgfile ();
992     if (cfgfile == NULL)
993     return;
994     _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
995     CopyFile (cfgfile, bak, FALSE);
996     free_if_alloc (cfgfile);
997     } /* gnupg_backup_options */
998    
999    
1000    
1001     static int
1002     backup_one_file (const char *srcpath, const char *srcn,
1003     const char *dstpath, const char *dstn)
1004     {
1005     char * src, * dst;
1006     BOOL rc;
1007    
1008     src = make_filename (srcpath, srcn, "gpg");
1009     if (!src)
1010     BUG (NULL);
1011     dst = make_filename (dstpath, dstn, "gpg");
1012     if (!dst)
1013     BUG (NULL);
1014     rc = CopyFile (src, dst, FALSE);
1015     free_if_alloc (src);
1016     free_if_alloc (dst);
1017     if (!rc)
1018     {
1019     log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1020     return WPTERR_GENERAL;
1021     }
1022     return 0;
1023     } /* backup_one_file */
1024    
1025    
1026     static int
1027     check_keyring (char ** r_path)
1028     {
1029     char * p;
1030     char * opt, * name;
1031    
1032     if (!*r_path)
1033     return 0;
1034     p = make_filename (*r_path, "pubring", "gpg");
1035     if (!p || get_file_size (p) > 0)
1036     return 0;
1037    
1038     opt = get_gnupg_cfgfile ();
1039     if (!opt)
1040     BUG (0);
1041     name = get_gnupg_keyring_from_options (opt, 1);
1042     free_if_alloc (opt);
1043     free_if_alloc (p);
1044     if (!name)
1045     return 0;
1046     p = strrchr (name, '\\');
1047     if (!p)
1048     {
1049     free_if_alloc (name);
1050     return 0;
1051     }
1052     free_if_alloc (*r_path);
1053     *r_path = new char [strlen (name)+1];
1054     memset (*r_path, 0, strlen (name));
1055     strncpy (*r_path, name, (p-name));
1056     free_if_alloc (name);
1057     return 1;
1058     }
1059    
1060    
1061     static char*
1062     get_backup_name (const char *templ)
1063     {
1064     struct tm *tm;
1065     char *p;
1066    
1067     time_t t = time (NULL);
1068     tm = localtime (&t);
1069     p = new char [strlen (templ) + 8 + 1];
1070     if (!p)
1071     BUG (0);
1072     sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1073     return p;
1074     }
1075    
1076    
1077     void
1078     gnupg_backup_keyrings (void)
1079     {
1080     char *srcpath = NULL, *dstpath = NULL;
1081     char *name=NULL;
1082     int rc, bakmode=0;
1083    
1084     if (!reg_prefs.auto_backup)
1085     return;
1086     bakmode = reg_prefs.backup.mode;
1087     srcpath = get_gnupg_path ();
1088     check_keyring (&srcpath);
1089     if (bakmode == 1) {
1090     dstpath = get_gnupg_path ();
1091     check_keyring (&dstpath);
1092     }
1093     else if (bakmode == 2) {
1094     char * tmpfile;
1095     FILE * fp;
1096    
1097     dstpath = m_strdup (reg_prefs.backup.path);
1098     if (!dstpath)
1099     BUG (0);
1100     tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1101     fp = fopen (tmpfile, "wb");
1102     if (!fp)
1103     rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1104     _("The backup drive '%s' does not seems to accessable.\n"
1105     "Please insert/check the drive to continue."), dstpath);
1106     else {
1107     rc = 0;
1108     fclose (fp);
1109 twoaday 73 remove (tmpfile);
1110 werner 36 }
1111     free_if_alloc (tmpfile);
1112     if (!fp || rc == IDCANCEL)
1113     return;
1114     }
1115     else {
1116     log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1117     return;
1118     }
1119     name = get_backup_name ("pubring-bak");
1120     rc = backup_one_file (srcpath, "pubring", dstpath, name);
1121     if (!rc)
1122     rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1123     free_if_alloc (name);
1124     free_if_alloc (srcpath);
1125     free_if_alloc (dstpath);
1126     } /* gnupg_backup_keyrings */
1127    
1128    
1129     /* Display GPG error from file if possible. */
1130     void
1131     gnupg_display_error (void)
1132     {
1133     char tmpath[512], * errstr;
1134     size_t size = 0;
1135     FILE * fp;
1136    
1137     GetTempPath (sizeof tmpath - 32, (tmpath));
1138     strcat (tmpath, "gpg_stderr");
1139     size = get_file_size (tmpath);
1140     if (file_exist_check (tmpath) || size <= 0)
1141     return;
1142     fp = fopen( tmpath, "rb" );
1143     if (!fp) {
1144     msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );
1145     return;
1146     }
1147     errstr = new char[size+1];
1148     if (!errstr)
1149     BUG (0);
1150     fread (errstr, 1, size, fp);
1151     errstr[size] = '\0';
1152     fclose (fp);
1153     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1154     free_if_alloc (errstr);
1155     }
1156    
1157    
1158    
1159     /* check that the requested GPG keyring exist and.
1160     Return value: 0 for success. */
1161     int
1162     gnupg_access_keyring (int _pub)
1163     {
1164     int rc = 0;
1165     char *name = get_gnupg_keyring (_pub, 1);
1166     if (!name || file_exist_check (name))
1167     rc = -1;
1168     free_if_alloc (name);
1169     return rc;
1170     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26