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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 85 - (hide annotations)
Fri Nov 18 07:20:40 2005 UTC (19 years, 3 months ago) by twoaday
File size: 27001 byte(s)
2005-11-17  Timo Schulz  <ts@g10code.com>
 
        * wptGPG.cpp (check_last_gnupg_access): Kludge to avoid that
        the cache will be loaded twice.
        * wptRegistry.cpp (regist_inst_winpt): More comments.
        * wptKeyManagerDlg.cpp (do_center_window): Make sure that
        neg. coordinates are never used.
        * wptClipVerifyDlg.cpp (clip_verify_dlg_proc): Localize all
        strings.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Likewise.
        * wptFileManagerDlg.cpp (filemanager_dlg_proc): Localize menu
        and save 'AlwaysOnTop' in the registry.
         

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 twoaday 85
675     /* XXX: find a better way. without it, winpt --keymanager loads
676     the key cache twice otherwise. */
677     if (ctx->last_access.dwLowDateTime == 0)
678     ctx->modified = 0;
679    
680 werner 36 ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
681     ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
682     }
683    
684    
685     /* Init GPG watcher table for all monitored files. */
686     void
687     init_gnupg_table (void)
688     {
689     char *p;
690     int j;
691    
692     for (j = 0; j < gpg_table_count; j++) {
693     p = gpg_table[j].object = m_strdup (gpg_objs[j]);
694     if (!p)
695     BUG (NULL);
696     memset (&gpg_table[j].access, 0, sizeof (FILETIME));
697     memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
698     gpg_table[j].modified = 0;
699     }
700     }
701    
702    
703     void
704     free_gnupg_table (void)
705     {
706     int j;
707    
708     for (j=0; j < gpg_table_count; j++)
709     free_if_alloc (gpg_table[j].object);
710     }
711    
712    
713     /* Return the amount of files modified since the last call. */
714     int
715     keyring_check_last_access (void)
716     {
717     int rc, j;
718    
719     rc = 0;
720     for (j = 0; j < gpg_table_count; j++) {
721     get_last_gnupg_access (&gpg_table[j]);
722     check_last_gnupg_access (&gpg_table[j]);
723     if (gpg_table[j].modified)
724     rc++;
725     }
726    
727     return rc;
728     }
729    
730    
731     const char*
732     gnupg_check_file_ext (const char *fname, int *r_type)
733     {
734     char file_ext[5];
735    
736     if (r_type)
737     *r_type = PGP_NONE;
738     if (!strchr (fname, '.' ))
739     return "UNKNOWN";
740    
741     strncpy (file_ext, fname + strlen (fname) - 4, 4);
742     file_ext[4] = '\0';
743     if (!stricmp (file_ext, ".asc"))
744     return "ARMORED";
745     else if (!stricmp (file_ext, ".sig")) {
746     if (r_type)
747     *r_type = PGP_SIG;
748     return "SIGNED";
749     }
750     else if (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
751     if (r_type)
752     *r_type = PGP_MESSAGE;
753     return "ENCRYPTED";
754     }
755     return "UNKNOWN";
756     }
757    
758    
759     char*
760     get_gnupg_keyring_from_options (const char * fname, int pub)
761     {
762     gpg_optfile_t opt;
763     gpg_option_t e;
764     char * kring = NULL;
765     int rc = 0;
766    
767     rc = parse_gpg_options (fname, &opt);
768     if (rc)
769     return NULL;
770     if (pub)
771     e = find_option (opt, "keyring");
772     else
773     e = find_option (opt, "secret-keyring");
774     if (e)
775     kring = m_strdup (e->val);
776     release_gpg_options (opt);
777    
778     return kring;
779     }
780    
781    
782    
783     /* XXX: does not work with write-protected floppies */
784     static int
785     my_access (const char * fname)
786     {
787     HANDLE hd;
788     hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
789     NULL, OPEN_EXISTING, 0, NULL);
790     if (hd == INVALID_HANDLE_VALUE)
791     return -1;
792     CloseHandle (hd);
793     return 0;
794     }
795    
796    
797 twoaday 78 /* Check the file permissions of the public keyring.
798     If @showmsg is 1 output a message in case of errors.
799     Return value: 1 if read-only attribute
800     2 if file is opened by another process exclusively. */
801 werner 36 int
802     gpg_check_permissions (int showmsg)
803     {
804     char * p, * name = NULL;
805     int failed = 0, ans=0, attrs=0;
806    
807     p = get_gnupg_path ();
808     check_keyring (&p);
809     if (p) {
810     name = make_filename (p, "pubring", "gpg");
811     free_if_alloc (p);
812     if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
813     ans = msg_box (NULL,
814     _("The selected keyring has the read-only file\n"
815     "attribute. In this state you do not have write\n"
816     "access. Do you want to remove the attribute?"),
817     _("GPG Information"), MB_YESNO);
818     if (ans == IDYES) {
819     attrs &= ~FILE_ATTRIBUTE_READONLY;
820     if (!SetFileAttributes (name, attrs)) {
821     msg_box (NULL, _("Could not reset read-only state."),
822     _("GPG Error"), MB_ERR);
823     failed = 1;
824     }
825     }
826     else if (ans == IDNO) {
827 twoaday 78 /* All commands with write access will be disabled. */
828 werner 36 failed = 1;
829     }
830     }
831     if (my_access (name)) {
832     if (showmsg)
833     msg_box (NULL,
834     _("You do not have file access to modify the contents of\n"
835     "one or both of the selected keyrings.\n"
836     "\n"
837     "The keyrings are in a read-only state which is propably\n"
838     "caused by another program which already opened the files.\n"),
839     _("GPG Warning"), MB_WARN);
840     failed = 2;
841     }
842     }
843     free_if_alloc (name);
844     return failed;
845 twoaday 78 }
846 werner 36
847    
848     /* Check the GPG home dir. If all methods failed, try to
849     create the default folder. */
850     static int
851     check_homedir (void)
852     {
853     char *homedir = NULL;
854 twoaday 73 int yes = 0, set_reg=0;
855     int rc = 0;
856 werner 36
857 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
858     if (!homedir) {
859     set_reg = 1;
860     homedir = multi_gnupg_path (0);
861     }
862 werner 36 if (!homedir)
863     homedir = m_strdup ("c:\\gnupg");
864     if (homedir) {
865     if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
866     yes = log_box (_("Preferences"), MB_YESNO,
867     _("%s does not exit.\n"
868     "Do you want to create this directory?"), homedir);
869     if (yes == IDYES) {
870 twoaday 73 if (!CreateDirectory (homedir, NULL))
871     rc = WPTERR_DIR_CREAT;
872 werner 36 }
873 twoaday 73 else
874     rc = WPTERR_DIR_OPEN;
875 werner 36 }
876 twoaday 73 if (set_reg)
877     set_reg_entry_gpg (GPG_REG_HOME, homedir);
878 werner 36 free_if_alloc (homedir);
879     }
880 twoaday 73 return rc;
881 werner 36 }
882    
883    
884     int
885     gnupg_check_homedir (void)
886     {
887     char *homedir = NULL;
888     char *prog = NULL;
889 twoaday 69 int rc = 0;
890 werner 36
891     rc = check_homedir ();
892     if (rc)
893     return rc;
894 twoaday 73 if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&
895     !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {
896 werner 36 prog = make_filename (homedir, "gpg", "exe");
897     if (file_exist_check (prog) == 0) {
898 twoaday 73 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
899 werner 36 if (rc)
900     goto fail;
901     }
902     free_if_alloc (homedir);
903     free_if_alloc (prog);
904     return rc;
905     }
906 twoaday 73 if ((prog = get_reg_entry_gpg (GPG_REG_EXE))
907 werner 36 && file_exist_check (prog)) {
908     free_if_alloc (prog);
909 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
910 werner 36 if (!homedir) {
911     rc = WPTERR_GENERAL;
912     goto fail;
913     }
914     prog = make_filename (homedir, "gpg", "exe");
915     if (file_exist_check (prog) == 0) {
916 twoaday 73 rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
917 werner 36 if (rc)
918     goto fail;
919     free_if_alloc (prog);
920     return rc;
921     }
922     }
923    
924     /* Change the return code if homedir doesn't exist or if the program
925     doesn't exist. Note that exist_checks return 0 to suggest existance. */
926     if ((!homedir || dir_exist_check (homedir)))
927     rc = WPTERR_GENERAL;
928    
929     fail:
930     free_if_alloc (homedir);
931     free_if_alloc (prog);
932     return rc;
933     } /* gnupg_check_homedir */
934    
935    
936     int
937     gnupg_copy_keyrings (void)
938     {
939     const char * pring, * sring;
940     char * file = NULL, * path = NULL;
941     int id = 0, rc = 0;
942     HWND hwnd;
943    
944     path = get_gnupg_path ();
945     if (!path)
946     return WPTERR_GENERAL;
947     hwnd = GetDesktopWindow ();
948    
949 twoaday 77 pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
950 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
951     if (!pring) {
952     msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
953     free_if_alloc (path);
954     return WPTERR_GENERAL;
955     }
956     file = make_filename (path, "pubring", "gpg");
957     if (file_exist_check (file) == 0) {
958     id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
959     if (id == IDNO)
960     goto fail;
961     }
962     if (!CopyFile (pring, file, FALSE)) {
963     msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
964     rc = WPTERR_FILE_READ;
965     goto fail;
966     }
967     free_if_alloc (file);
968    
969 twoaday 77 sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
970 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
971     if (!sring) {
972     msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
973     return WPTERR_GENERAL;
974     }
975     file = make_filename (path, "secring", "gpg");
976     if (file_exist_check (file) == 0) {
977     id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
978     if( id == IDNO )
979     goto fail;
980     }
981     if (!CopyFile (sring, file, FALSE)) {
982     msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
983     rc = WPTERR_FILE_READ;
984     }
985    
986     fail:
987     free_if_alloc (file);
988     free_if_alloc (path);
989     return rc;
990     } /* gnupg_import_keyrings */
991    
992    
993     void
994     gnupg_backup_options (void)
995     {
996     char *cfgfile = NULL;
997     char bak[512];
998    
999     cfgfile = get_gnupg_cfgfile ();
1000     if (cfgfile == NULL)
1001     return;
1002     _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
1003     CopyFile (cfgfile, bak, FALSE);
1004     free_if_alloc (cfgfile);
1005     } /* gnupg_backup_options */
1006    
1007    
1008    
1009     static int
1010     backup_one_file (const char *srcpath, const char *srcn,
1011     const char *dstpath, const char *dstn)
1012     {
1013     char * src, * dst;
1014     BOOL rc;
1015    
1016     src = make_filename (srcpath, srcn, "gpg");
1017     if (!src)
1018     BUG (NULL);
1019     dst = make_filename (dstpath, dstn, "gpg");
1020     if (!dst)
1021     BUG (NULL);
1022     rc = CopyFile (src, dst, FALSE);
1023     free_if_alloc (src);
1024     free_if_alloc (dst);
1025     if (!rc)
1026     {
1027     log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1028     return WPTERR_GENERAL;
1029     }
1030     return 0;
1031     } /* backup_one_file */
1032    
1033    
1034     static int
1035     check_keyring (char ** r_path)
1036     {
1037     char * p;
1038     char * opt, * name;
1039    
1040     if (!*r_path)
1041     return 0;
1042     p = make_filename (*r_path, "pubring", "gpg");
1043     if (!p || get_file_size (p) > 0)
1044     return 0;
1045    
1046     opt = get_gnupg_cfgfile ();
1047     if (!opt)
1048     BUG (0);
1049     name = get_gnupg_keyring_from_options (opt, 1);
1050     free_if_alloc (opt);
1051     free_if_alloc (p);
1052     if (!name)
1053     return 0;
1054     p = strrchr (name, '\\');
1055     if (!p)
1056     {
1057     free_if_alloc (name);
1058     return 0;
1059     }
1060     free_if_alloc (*r_path);
1061     *r_path = new char [strlen (name)+1];
1062     memset (*r_path, 0, strlen (name));
1063     strncpy (*r_path, name, (p-name));
1064     free_if_alloc (name);
1065     return 1;
1066     }
1067    
1068    
1069     static char*
1070     get_backup_name (const char *templ)
1071     {
1072     struct tm *tm;
1073     char *p;
1074    
1075     time_t t = time (NULL);
1076     tm = localtime (&t);
1077     p = new char [strlen (templ) + 8 + 1];
1078     if (!p)
1079     BUG (0);
1080     sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1081     return p;
1082     }
1083    
1084    
1085     void
1086     gnupg_backup_keyrings (void)
1087     {
1088     char *srcpath = NULL, *dstpath = NULL;
1089     char *name=NULL;
1090     int rc, bakmode=0;
1091    
1092     if (!reg_prefs.auto_backup)
1093     return;
1094     bakmode = reg_prefs.backup.mode;
1095     srcpath = get_gnupg_path ();
1096     check_keyring (&srcpath);
1097     if (bakmode == 1) {
1098     dstpath = get_gnupg_path ();
1099     check_keyring (&dstpath);
1100     }
1101     else if (bakmode == 2) {
1102     char * tmpfile;
1103     FILE * fp;
1104    
1105     dstpath = m_strdup (reg_prefs.backup.path);
1106     if (!dstpath)
1107     BUG (0);
1108     tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1109     fp = fopen (tmpfile, "wb");
1110     if (!fp)
1111     rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1112     _("The backup drive '%s' does not seems to accessable.\n"
1113     "Please insert/check the drive to continue."), dstpath);
1114     else {
1115     rc = 0;
1116     fclose (fp);
1117 twoaday 73 remove (tmpfile);
1118 werner 36 }
1119     free_if_alloc (tmpfile);
1120     if (!fp || rc == IDCANCEL)
1121     return;
1122     }
1123     else {
1124     log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1125     return;
1126     }
1127     name = get_backup_name ("pubring-bak");
1128     rc = backup_one_file (srcpath, "pubring", dstpath, name);
1129     if (!rc)
1130     rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1131     free_if_alloc (name);
1132     free_if_alloc (srcpath);
1133     free_if_alloc (dstpath);
1134     } /* gnupg_backup_keyrings */
1135    
1136    
1137     /* Display GPG error from file if possible. */
1138     void
1139     gnupg_display_error (void)
1140     {
1141     char tmpath[512], * errstr;
1142     size_t size = 0;
1143     FILE * fp;
1144    
1145     GetTempPath (sizeof tmpath - 32, (tmpath));
1146     strcat (tmpath, "gpg_stderr");
1147     size = get_file_size (tmpath);
1148     if (file_exist_check (tmpath) || size <= 0)
1149     return;
1150     fp = fopen( tmpath, "rb" );
1151     if (!fp) {
1152     msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );
1153     return;
1154     }
1155     errstr = new char[size+1];
1156     if (!errstr)
1157     BUG (0);
1158     fread (errstr, 1, size, fp);
1159     errstr[size] = '\0';
1160     fclose (fp);
1161     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1162     free_if_alloc (errstr);
1163     }
1164    
1165    
1166    
1167     /* check that the requested GPG keyring exist and.
1168     Return value: 0 for success. */
1169     int
1170     gnupg_access_keyring (int _pub)
1171     {
1172     int rc = 0;
1173     char *name = get_gnupg_keyring (_pub, 1);
1174     if (!name || file_exist_check (name))
1175     rc = -1;
1176     free_if_alloc (name);
1177     return rc;
1178     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26