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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 128 - (hide annotations)
Mon Dec 19 13:05:59 2005 UTC (19 years, 2 months ago) by twoaday
File size: 25782 byte(s)
2005-12-17  Timo Schulz  <ts@g10code.com>
 
        * wptUTF8.cpp: Removed unused charset array.
        * wptSigList.cpp (siglist_build): Increase size for 'class'
        column.
        * wptGPG.cpp (get_gnupg_path): Simplified.
        * WinPT.cpp (load_gpg_env): New.
        (check_crypto_engine): Return type is now bool.
        * wptRegistry.cpp (is_gpg4win_installed): New.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): More consistent
        dialog design.
        * wptKeyManagerDlg.cpp (translate_menu_strings): New.
        (translate_popupmenu_strings): New.
        * wptKeyEditDlgs.cpp (is_jpg_file): New.


1 werner 36 /* wptGPG.cpp - GnuPG configuration
2 twoaday 41 * Copyright (C) 2001-2005 Timo Schulz
3 werner 36 *
4     * This file is part of WinPT.
5     *
6     * WinPT is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * WinPT is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with WinPT; if not, write to the Free Software Foundation,
18     * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20 werner 42 #ifdef HAVE_CONFIG_H
21     #include <config.h>
22     #endif
23    
24 twoaday 41 #include <windows.h>
25 werner 36 #include <string.h>
26     #include <stdio.h>
27     #include <shlobj.h>
28     #include <ctype.h>
29     #include <io.h>
30 twoaday 41 #include <time.h>
31 werner 36
32     #include "wptGPG.h"
33 werner 48 #include "wptGpgCmds.h"
34 werner 36 #include "wptGPGOptSkel.h"
35     #include "wptTypes.h"
36     #include "wptNLS.h"
37     #include "wptRegistry.h"
38     #include "wptErrors.h"
39     #include "wptW32API.h"
40     #include "wptCrypto.h"
41    
42 twoaday 73 #define GPG_CONF "gpg.conf"
43     #define GPG_REG_EXE "gpgProgram" /* registry name for the binary. */
44     #define GPG_REG_HOME "HomeDir" /* registry name of the home dir. */
45 werner 36
46     struct gpg_watcher_s {
47     FILETIME last_access;
48     FILETIME access;
49     char *object;
50     int modified;
51     };
52    
53    
54     /* XXX need to watch for gpg.conf due to the fact keyring entries could be changed */
55     static const char * gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
56     static gpg_watcher_s gpg_table[3];
57     static int gpg_table_count = DIM (gpg_table);
58    
59     int idea_available = 0;
60    
61     static int check_keyring (char ** r_path);
62    
63    
64     /* Return the application data folder of the current user. */
65 twoaday 128 char*
66 twoaday 73 multi_gnupg_path (int strict)
67 werner 36 {
68     static char buf[256+64];
69     BOOL ec;
70    
71     /* MSDN: buf must be at least MAX_PATH=256 bytes */
72     memset (buf, 0, sizeof (buf));
73     /* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */
74     ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE);
75 twoaday 73 if (ec != 1) {
76     log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed\r\n",
77     (int)GetLastError ());
78 werner 36 return NULL;
79 twoaday 73 }
80 werner 36 strcat (buf, "\\gnupg");
81 twoaday 73 if (strict && access (buf, 00))
82 werner 36 return NULL;
83     return m_strdup (buf);
84     }
85    
86    
87 twoaday 128 /* Return the full path to the GPG home directory. First the 'HomeDir' entry
88     from the registry is used. Then the default $APPDATA\gnupg path. */
89 werner 36 char*
90     get_gnupg_path (void)
91     {
92 twoaday 128 char *path;
93    
94     path = get_reg_entry_gpg (GPG_REG_HOME);
95     if (path) {
96     if (dir_exist_check (path) == 0)
97     return path;
98     free_if_alloc (path);
99 werner 36 }
100 twoaday 128 path = multi_gnupg_path (1);
101     return path;
102 werner 36 }
103    
104    
105     /* Return the full path of the gpg config file.
106     A value of NULL indicates an error. */
107     char*
108     get_gnupg_cfgfile (void)
109     {
110 twoaday 73 char *p = NULL;
111     char *optfile = NULL;
112     char *path = NULL;
113 werner 36 size_t nlen = 0;
114    
115     path = get_gnupg_path ();
116     if (!path)
117     return NULL;
118     p = get_reg_entry_gpg ("OptFile");
119     if (p && !strcmp (p, "")) {
120     nlen = strlen (path) + 64;
121     optfile = new char[nlen + 1];
122     if (!optfile)
123     BUG (0);
124     _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);
125     }
126     else if (p) {
127     nlen = strlen( p ) + 4;
128     optfile = new char[nlen + 1];
129     if (!optfile)
130     BUG (NULL);
131     _snprintf (optfile, nlen, "%s", p);
132     }
133     else {
134     nlen = strlen (path) + 64;
135     optfile = new char[nlen + 1];
136     if( !optfile)
137     BUG (NULL);
138     _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);
139     }
140     free_if_alloc (path);
141     free_if_alloc (p);
142     return optfile;
143     }
144    
145    
146     /* Return the full path of the keyring. If @pub is 1, the public
147     keyring is return, otherwise the secret keyring. */
148     char*
149     get_gnupg_keyring (int pub, int strict)
150     {
151     char *optfile = NULL;
152     char *path = NULL;
153     char *keyring = NULL;
154    
155     path = get_gnupg_path ();
156     if (!path)
157     return NULL;
158     keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
159     if (!strict && !file_exist_check (keyring)) {
160     free_if_alloc (path);
161     return keyring;
162     }
163 twoaday 66 if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {
164 werner 36 free_if_alloc (keyring);
165     optfile = make_filename (path, GPG_CONF, NULL);
166     keyring = get_gnupg_keyring_from_options (optfile, pub);
167     }
168     free_if_alloc (path);
169     free_if_alloc (optfile);
170     return keyring;
171     }
172    
173    
174     /* Return the full path (with the gpg exe name). First the registry is scanned
175     for the entry 'gpgProgram'. If it wasn't set, the default path is the
176     appended string 'gpg.exe' is used. */
177 werner 58
178     /* FIXME: Use gpgme's engine info here. */
179 werner 36 char*
180     get_gnupg_prog (void)
181     {
182     char *p;
183     char *pgm = NULL;
184    
185 twoaday 73 p = get_reg_entry_gpg (GPG_REG_EXE);
186 werner 36 if (!p) {
187     char *path = get_gnupg_path ();
188     if (!path)
189     return NULL;
190     pgm = make_filename (path, "gpg", "exe");
191     free_if_alloc (path);
192     }
193     else {
194     pgm = m_strdup (p);
195     free_if_alloc (p);
196     }
197     return pgm;
198     }
199    
200    
201     /* Retrieve the first usable secret key from cache.
202     If no usable was found, @ret_no_useable is 1.
203     Return value: the keyid of the secret key. */
204     static char *
205     default_key_from_cache (int *ret_no_useable)
206     {
207 twoaday 73 const char *s;
208     char *keyid = NULL;
209 werner 36 gpgme_key_t key;
210     gpg_keycache_t sec = keycache_get_ctx (0);
211    
212     if (!sec)
213     BUG (0);
214     gpg_keycache_rewind (sec);
215     while (!gpg_keycache_next_key (sec, 1, &key)) {
216     if (key_is_useable (key)) {
217     s = key->subkeys->keyid;
218     if (s)
219     keyid = m_strdup (s+8);
220     break;
221     }
222     }
223 twoaday 66 if (!keyid)
224 werner 36 *ret_no_useable = 1;
225     return keyid;
226     }
227    
228    
229 twoaday 41 /* Load the gpg.conf and search for some options
230     and store the result in the global preference context.
231     Return value: 0 on success. */
232     int
233     gnupg_load_config (void)
234     {
235     int rc;
236     gpg_optfile_t opt;
237     gpg_option_t o;
238     char *conf = get_gnupg_cfgfile ();
239     if (!conf)
240     return -1;
241     rc = parse_gpg_options (conf, &opt);
242     if (rc) {
243     free_if_alloc (conf);
244     return -1;
245     }
246     o = find_option (opt, "ask-cert-level");
247     if (o)
248     reg_prefs.gpg.ask_cert_level = 1;
249     release_gpg_options (opt);
250     free_if_alloc (conf);
251     return 0;
252     }
253    
254    
255 werner 36 char*
256     get_gnupg_default_key (void)
257     {
258     gpg_optfile_t opt = NULL;
259     gpg_option_t e;
260     char * keyid = NULL, * optfile = NULL;
261     int no_usable=0, rc = 0;
262    
263     optfile = get_gnupg_cfgfile ();
264     if (!optfile)
265     return default_key_from_cache (&no_usable);
266     rc = parse_gpg_options (optfile, &opt);
267     if (rc) {
268 twoaday 73 free_if_alloc (optfile);
269     return default_key_from_cache (&no_usable);
270 werner 36 }
271     e = find_option( opt, "default-key" );
272     if ( e )
273     keyid = m_strdup( e->val );
274     if( !e ) {
275     e = find_option( opt, "local-user" );
276     if( e )
277     keyid = m_strdup( e->val );
278     }
279     if( !e ) {
280     e = find_option( opt, "encrypt-to" );
281     if( e )
282     keyid = m_strdup( e->val );
283     }
284 twoaday 41 free_if_alloc (optfile);
285     release_gpg_options (opt);
286 werner 36
287 twoaday 41 if (!keyid)
288     keyid = default_key_from_cache (&no_usable);
289 werner 36 return keyid;
290     } /* get_gnupg_default_key */
291    
292    
293 twoaday 73 /* Check if GPG4WIN is available and if so, use the
294     install path to figure out where the gpg.exe is. */
295     char*
296     check_for_gpg4win (void)
297     {
298 twoaday 74 return get_reg_entry_gpg4win ("gpg.exe");
299 twoaday 73 }
300    
301    
302 werner 36 /* Check if the gpg application (exe file) is available. */
303     int
304     check_gnupg_prog (void)
305     {
306 twoaday 73 char *gpgexe = NULL;
307 werner 36 int rc = 0;
308    
309 twoaday 73 gpgexe = get_gnupg_prog ();
310     if (!gpgexe || file_exist_check (gpgexe)) {
311     free_if_alloc (gpgexe);
312     gpgexe = check_for_gpg4win ();
313     if (!gpgexe || file_exist_check (gpgexe))
314     rc = WPTERR_GPG_EXEFILE;
315     else
316     set_reg_entry_gpg (GPG_REG_EXE, gpgexe);
317     }
318     free_if_alloc (gpgexe);
319 werner 36 return rc;
320     }
321    
322    
323     static int
324     parse_version_nr (const char * buf, int *major, int *minor, int *patch)
325     {
326     char tmp[8];
327     int i;
328    
329     i=0;
330     while (buf && *buf != '.' && i < 8)
331     tmp[i++] = *buf++;
332     tmp[i] = 0; buf++;
333     *major = atol( tmp );
334     i=0;
335     while (buf && *buf != '.' && i < 8)
336     tmp[i++] = *buf++;
337     tmp[i] = 0; buf++;
338     *minor = atol (tmp);
339     i=0;
340 twoaday 78 while (buf && isdigit (*buf) && i < 8)
341 werner 36 tmp[i++] = *buf++;
342     tmp[i] = 0;
343     *patch = atol (tmp);
344     return 0;
345     }
346    
347    
348     /* Check if the gnupg engine fullfills the minimum requirement
349     version given in @r_major.@r_minor.@r_patch. On success these
350     variables contain the GPG version which is installed. */
351     int
352     check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)
353     {
354     gpgme_ctx_t ctx;
355     gpgme_engine_info_t inf;
356 twoaday 78 char *eng = NULL;
357 werner 36 int major=0, minor=0, patch=0;
358 twoaday 78 int rc = 1;
359 werner 36
360     gpgme_new (&ctx);
361     inf = gpgme_ctx_get_engine_info (ctx);
362     if (!inf) {
363     gpgme_release (ctx);
364     return -1;
365     }
366 twoaday 78
367 werner 36 /* We need to exec GPG again to find out if IDEA is available. */
368     if (gpg_get_version (&eng))
369     return -1;
370     if (strstr (eng, "IDEA"))
371     idea_available = 1;
372     free (eng);
373 twoaday 78 rc = parse_version_nr (inf->version, &major, &minor, &patch);
374     if (rc) {
375 werner 36 gpgme_release (ctx);
376     return rc;
377     }
378 twoaday 78
379     if (major > *r_major)
380 werner 36 rc = 0;
381 twoaday 78 else if (major == *r_major && minor > *r_minor)
382     rc = 0;
383     else if (major == *r_major && minor == *r_minor &&
384     patch >= *r_patch)
385     rc = 0;
386    
387 werner 36 *r_major = major;
388     *r_minor = minor;
389     *r_patch = patch;
390     return rc;
391     }
392    
393    
394     int
395     check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)
396     {
397     gpg_optfile_t opt;
398     gpg_option_t e;
399     int rc = 0;
400    
401     *r_secrings = 0;
402     *r_pubrings = 0;
403     rc = parse_gpg_options( fname, &opt );
404     if( rc )
405     return WPTERR_FILE_OPEN;
406    
407     for( e = opt->list; e; e = e->next ) {
408     if( !strcmp( e->name, "secret-keyring" ) ) {
409     if( !file_exist_check( e->val ) )
410     r_secrings[0]++;
411     }
412     else if( !strcmp( e->name, "keyring" ) ) {
413     if( !file_exist_check( e->val ) )
414     r_pubrings[0]++;
415     }
416     }
417     release_gpg_options( opt );
418     return 0;
419     } /* check_gnupg_cfgfile */
420    
421    
422     /*
423     * Check if both keyrings are located in the gnupg home directory.
424     */
425     int
426     gnupg_access_files (void)
427     {
428     int rc = 0;
429     int pubring_ok = 0, secring_ok = 0;
430     int secrings = 0, pubrings = 0;
431     char *optfile;
432    
433     if (gnupg_access_keyring (1))
434     rc = WPTERR_GPG_KEYRINGS;
435     else
436     pubring_ok = 1;
437    
438     if (gnupg_access_keyring (0))
439     rc = WPTERR_GPG_KEYRINGS;
440     else
441     secring_ok = 1;
442 twoaday 73
443 werner 36 if (!pubring_ok || !secring_ok) {
444     optfile = get_gnupg_cfgfile ();
445     if (!optfile)
446     return WPTERR_GPG_KEYRINGS;
447     rc = file_exist_check (optfile);
448 twoaday 73 if (!rc && get_file_size (optfile) > 0) {
449 werner 36 rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);
450     if (!rc && secrings && pubrings) {
451     free_if_alloc (optfile);
452     return 0; /* found two keyrings in the option file */
453     }
454     else if ((!rc && pubrings && secring_ok)
455     || (!rc && secrings && pubring_ok)) {
456     free_if_alloc (optfile);
457     return 0; /* found one keyring and one entry in the options file */
458     }
459     else
460     return WPTERR_GPG_OPT_KEYRINGS;
461     }
462     free_if_alloc (optfile);
463     rc = WPTERR_GPG_KEYRINGS;
464     }
465     return rc;
466     } /* gnupg_access_files */
467    
468    
469     static int
470     create_gpg_options (void)
471     {
472     FILE *fp;
473     char *s, *optfile;
474    
475 twoaday 73 s = get_gnupg_path ();
476 werner 36 if( s == NULL )
477     return WPTERR_FILE_CREAT;
478 twoaday 73 optfile = make_filename (s, GPG_CONF, NULL);
479 werner 36 fp = fopen( optfile, "wb" );
480     if( fp == NULL ) {
481     return WPTERR_FILE_CREAT;
482     goto fail;
483     }
484     fwrite( options_skel, 1, strlen( options_skel ), fp );
485     fclose( fp );
486    
487     fail:
488     free_if_alloc( s );
489     free_if_alloc( optfile );
490     return 0;
491     } /* create_gpg_options */
492    
493    
494     /*
495     * Return the contents of the options file as a char buf.
496     */
497     char *
498     get_gnupg_config (void)
499     {
500     FILE * fp;
501     char * p = NULL, * optfile = NULL;
502     int fsize, rc = 0;
503    
504     optfile = get_gnupg_cfgfile ();
505     if( optfile == NULL )
506     return NULL;
507     fsize = get_file_size( optfile );
508     if( !fsize ) {
509     rc = create_gpg_options( );
510     if ( rc )
511     return NULL;
512     fsize = get_file_size( optfile );
513     }
514     if( fsize > 100000 )
515     goto leave; /* too large */
516     p = new char[fsize+1];
517     if( p == NULL )
518     BUG( NULL );
519     fp = fopen( optfile, "rb" );
520     if( fp == NULL ) {
521     free_if_alloc( p );
522     return NULL;
523     }
524     fread( p, 1, fsize, fp );
525     fclose( fp );
526     p[fsize] = '\0';
527     free_if_alloc( optfile );
528    
529     leave:
530     return p;
531     } /* get_gnupg_config */
532    
533    
534     int
535     set_gnupg_default_key (const char * key)
536     {
537     gpg_optfile_t opt;
538     gpg_option_t e;
539     char *optfile = NULL;
540     int rc = 0;
541    
542     optfile = get_gnupg_cfgfile ();
543     if (!optfile)
544     return -1;
545     rc = parse_gpg_options (optfile, &opt);
546     if( rc ) {
547     free_if_alloc (optfile);
548     return -1;
549     }
550     e = find_option (opt, "default-key");
551     if (e) {
552     free_if_alloc (e->val);
553     e->val = m_strdup (key);
554     e->used = 1;
555     }
556     else
557     add_entry (opt, ENTRY_MULTI, "default-key", key);
558     rc = commit_gpg_options (optfile, opt);
559    
560     free_if_alloc (optfile);
561     release_gpg_options (opt);
562    
563     return rc;
564     } /* set_gnupg_default_key */
565    
566    
567     /*
568     * Set the contents of the options file.
569     */
570     int
571     set_gnupg_options( const char *buf, size_t buflen )
572     {
573     FILE *fp;
574     char *optfile = NULL;
575    
576     optfile = get_gnupg_cfgfile( );
577     if( optfile == NULL )
578     return WPTERR_FILE_CREAT;
579    
580     fp = fopen( optfile, "wb" );
581     if( fp == NULL ) {
582     free_if_alloc( optfile );
583     return WPTERR_FILE_CREAT;
584     }
585     fwrite( buf, 1, buflen, fp );
586     fclose( fp );
587     free_if_alloc( optfile );
588     return 0;
589     } /* set_gnupg_options */
590    
591     /*
592     * Check if the line contains a valid GPG argument.
593     */
594     static int
595     check_line( const char *buf )
596     {
597     int j, len;
598     int rc = 0;
599    
600     if( *buf == '#' || *buf == '\r' || *buf == '\n' )
601     return 1;
602     rc = 0;
603     for ( j = 0; valid_gpg_args[j]; j++ ) {
604     len = strlen( valid_gpg_args[j] );
605     if( !strncmp( valid_gpg_args[j], buf, len ) )
606     rc = 1;
607     }
608    
609     return rc;
610     } /* check_line */
611    
612    
613     int
614     check_gnupg_options( const char *buf )
615     {
616     char line[1024];
617     int nbytes = 0;
618     unsigned j;
619    
620     for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {
621     line[nbytes++] = buf[j];
622     if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {
623     line[nbytes] = '\0';
624     if( !check_line( line ) ) {
625     msg_box( NULL, line, "options", MB_OK );
626     return 1;
627     }
628     nbytes = 0;
629     }
630     }
631    
632     return 0;
633     } /* check_gnupg_options */
634    
635    
636     /* Store the last access of the file inside the watcher @ctx. */
637     static int
638     get_last_gnupg_access (gpg_watcher_s *ctx)
639     {
640     HANDLE fd;
641     char *path;
642     char *file;
643    
644     path = get_gnupg_path ();
645     file = make_filename (path, ctx->object, NULL);
646     fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
647     if (fd == INVALID_HANDLE_VALUE) {
648     free_if_alloc (path);
649     free_if_alloc (file);
650     return WPTERR_FILE_OPEN;
651     }
652     GetFileTime (fd, NULL, NULL, &ctx->access);
653     CloseHandle (fd);
654     free_if_alloc (path);
655     free_if_alloc (file);
656     return 0;
657     }
658    
659    
660     /* Check if the file inside watcher @ctx was modified. */
661     static void
662     check_last_gnupg_access (gpg_watcher_s *ctx)
663     {
664     ctx->modified = 0;
665    
666     if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
667     ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
668     ctx->modified = 1;
669 twoaday 85
670     /* XXX: find a better way. without it, winpt --keymanager loads
671 twoaday 117 the key cache twice. */
672 twoaday 85 if (ctx->last_access.dwLowDateTime == 0)
673     ctx->modified = 0;
674 twoaday 117
675 werner 36 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 twoaday 128 my_access (const char *fname)
781 werner 36 {
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 twoaday 128 char *p = NULL;
800     char *name = NULL;
801 werner 36 int failed = 0, ans=0, attrs=0;
802    
803     p = get_gnupg_path ();
804 twoaday 128 if (check_keyring (&p) && p) {
805 werner 36 name = make_filename (p, "pubring", "gpg");
806     if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
807     ans = msg_box (NULL,
808     _("The selected keyring has the read-only file\n"
809     "attribute. In this state you do not have write\n"
810     "access. Do you want to remove the attribute?"),
811     _("GPG Information"), MB_YESNO);
812     if (ans == IDYES) {
813     attrs &= ~FILE_ATTRIBUTE_READONLY;
814     if (!SetFileAttributes (name, attrs)) {
815     msg_box (NULL, _("Could not reset read-only state."),
816     _("GPG Error"), MB_ERR);
817     failed = 1;
818     }
819     }
820     else if (ans == IDNO) {
821 twoaday 78 /* All commands with write access will be disabled. */
822 werner 36 failed = 1;
823     }
824     }
825     if (my_access (name)) {
826     if (showmsg)
827     msg_box (NULL,
828     _("You do not have file access to modify the contents of\n"
829     "one or both of the selected keyrings.\n"
830     "\n"
831     "The keyrings are in a read-only state which is propably\n"
832     "caused by another program which already opened the files.\n"),
833     _("GPG Warning"), MB_WARN);
834     failed = 2;
835     }
836     }
837 twoaday 128 free_if_alloc (p);
838 werner 36 free_if_alloc (name);
839     return failed;
840 twoaday 78 }
841 werner 36
842    
843 twoaday 128 /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
844     then check for $APPDATA\gnupg. Create the dir if it does not exists. */
845     int
846     gnupg_check_homedir (void)
847 werner 36 {
848     char *homedir = NULL;
849 twoaday 128 int val = 0;
850 twoaday 73 int rc = 0;
851 werner 36
852 twoaday 73 homedir = get_reg_entry_gpg (GPG_REG_HOME);
853 twoaday 128 if (!homedir)
854 twoaday 73 homedir = multi_gnupg_path (0);
855 werner 36 if (homedir) {
856     if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
857 twoaday 128 val = log_box (_("Preferences"), MB_YESNO,
858 werner 36 _("%s does not exit.\n"
859     "Do you want to create this directory?"), homedir);
860 twoaday 128 if (val == IDYES) {
861 twoaday 73 if (!CreateDirectory (homedir, NULL))
862     rc = WPTERR_DIR_CREAT;
863 werner 36 }
864 twoaday 73 else
865     rc = WPTERR_DIR_OPEN;
866 werner 36 }
867     free_if_alloc (homedir);
868     }
869 twoaday 73 return rc;
870 werner 36 }
871    
872    
873     int
874     gnupg_copy_keyrings (void)
875     {
876     const char * pring, * sring;
877     char * file = NULL, * path = NULL;
878     int id = 0, rc = 0;
879     HWND hwnd;
880    
881     path = get_gnupg_path ();
882     if (!path)
883     return WPTERR_GENERAL;
884     hwnd = GetDesktopWindow ();
885    
886 twoaday 77 pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
887 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
888     if (!pring) {
889     msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
890     free_if_alloc (path);
891     return WPTERR_GENERAL;
892     }
893     file = make_filename (path, "pubring", "gpg");
894     if (file_exist_check (file) == 0) {
895     id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
896     if (id == IDNO)
897     goto fail;
898     }
899     if (!CopyFile (pring, file, FALSE)) {
900     msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
901     rc = WPTERR_FILE_READ;
902     goto fail;
903     }
904     free_if_alloc (file);
905    
906 twoaday 77 sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
907 werner 36 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
908     if (!sring) {
909     msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
910     return WPTERR_GENERAL;
911     }
912     file = make_filename (path, "secring", "gpg");
913     if (file_exist_check (file) == 0) {
914     id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
915     if( id == IDNO )
916     goto fail;
917     }
918     if (!CopyFile (sring, file, FALSE)) {
919     msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
920     rc = WPTERR_FILE_READ;
921     }
922    
923     fail:
924     free_if_alloc (file);
925     free_if_alloc (path);
926     return rc;
927     } /* gnupg_import_keyrings */
928    
929    
930 twoaday 128 /* Backup the gpg.conf file. */
931 werner 36 void
932     gnupg_backup_options (void)
933     {
934     char *cfgfile = NULL;
935     char bak[512];
936    
937     cfgfile = get_gnupg_cfgfile ();
938 twoaday 128 if (!cfgfile)
939 werner 36 return;
940     _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
941     CopyFile (cfgfile, bak, FALSE);
942     free_if_alloc (cfgfile);
943 twoaday 128 }
944 werner 36
945    
946     static int
947     backup_one_file (const char *srcpath, const char *srcn,
948     const char *dstpath, const char *dstn)
949     {
950     char * src, * dst;
951     BOOL rc;
952    
953     src = make_filename (srcpath, srcn, "gpg");
954     if (!src)
955     BUG (NULL);
956     dst = make_filename (dstpath, dstn, "gpg");
957     if (!dst)
958     BUG (NULL);
959     rc = CopyFile (src, dst, FALSE);
960     free_if_alloc (src);
961     free_if_alloc (dst);
962     if (!rc)
963     {
964     log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
965     return WPTERR_GENERAL;
966     }
967     return 0;
968     } /* backup_one_file */
969    
970    
971 twoaday 128 /* Figure out first public keyring which is not empty.
972     Return value: 1 on success. */
973 werner 36 static int
974 twoaday 128 check_keyring (char **r_path)
975 werner 36 {
976 twoaday 128 char *p;
977     char *opt;
978     char *name;
979 werner 36
980     if (!*r_path)
981     return 0;
982     p = make_filename (*r_path, "pubring", "gpg");
983 twoaday 128 if (!p || get_file_size (p) <= 0)
984 werner 36 return 0;
985    
986     opt = get_gnupg_cfgfile ();
987     if (!opt)
988     BUG (0);
989     name = get_gnupg_keyring_from_options (opt, 1);
990     free_if_alloc (opt);
991     free_if_alloc (p);
992     if (!name)
993     return 0;
994     p = strrchr (name, '\\');
995 twoaday 128 if (!p) {
996 werner 36 free_if_alloc (name);
997     return 0;
998     }
999     free_if_alloc (*r_path);
1000     *r_path = new char [strlen (name)+1];
1001     memset (*r_path, 0, strlen (name));
1002     strncpy (*r_path, name, (p-name));
1003     free_if_alloc (name);
1004     return 1;
1005     }
1006    
1007    
1008 twoaday 128 /* Return a temp name based on the day of the week. */
1009 werner 36 static char*
1010     get_backup_name (const char *templ)
1011     {
1012     struct tm *tm;
1013     char *p;
1014 twoaday 128 time_t t;
1015 werner 36
1016 twoaday 128 t = time (NULL);
1017 werner 36 tm = localtime (&t);
1018     p = new char [strlen (templ) + 8 + 1];
1019     if (!p)
1020     BUG (0);
1021     sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1022     return p;
1023     }
1024    
1025    
1026 twoaday 117 /* Make backups of all keyrings. The public key ring is
1027     rotated like this pubring-%d.gpg. */
1028 werner 36 void
1029     gnupg_backup_keyrings (void)
1030     {
1031     char *srcpath = NULL, *dstpath = NULL;
1032     char *name=NULL;
1033     int rc, bakmode=0;
1034    
1035     if (!reg_prefs.auto_backup)
1036     return;
1037     bakmode = reg_prefs.backup.mode;
1038 twoaday 117 srcpath = get_gnupg_path ();
1039 werner 36 check_keyring (&srcpath);
1040     if (bakmode == 1) {
1041 twoaday 117 dstpath = multi_gnupg_path (1);
1042 werner 36 check_keyring (&dstpath);
1043     }
1044     else if (bakmode == 2) {
1045 twoaday 117 char *tmpfile;
1046     FILE *fp;
1047 werner 36
1048     dstpath = m_strdup (reg_prefs.backup.path);
1049     if (!dstpath)
1050     BUG (0);
1051     tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1052     fp = fopen (tmpfile, "wb");
1053     if (!fp)
1054     rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1055     _("The backup drive '%s' does not seems to accessable.\n"
1056     "Please insert/check the drive to continue."), dstpath);
1057     else {
1058     rc = 0;
1059     fclose (fp);
1060 twoaday 73 remove (tmpfile);
1061 werner 36 }
1062     free_if_alloc (tmpfile);
1063     if (!fp || rc == IDCANCEL)
1064     return;
1065     }
1066     else {
1067     log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1068     return;
1069     }
1070     name = get_backup_name ("pubring-bak");
1071     rc = backup_one_file (srcpath, "pubring", dstpath, name);
1072     if (!rc)
1073     rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1074     free_if_alloc (name);
1075     free_if_alloc (srcpath);
1076     free_if_alloc (dstpath);
1077 twoaday 117 }
1078 werner 36
1079    
1080     /* Display GPG error from file if possible. */
1081     void
1082     gnupg_display_error (void)
1083     {
1084     char tmpath[512], * errstr;
1085     size_t size = 0;
1086     FILE * fp;
1087    
1088     GetTempPath (sizeof tmpath - 32, (tmpath));
1089     strcat (tmpath, "gpg_stderr");
1090     size = get_file_size (tmpath);
1091     if (file_exist_check (tmpath) || size <= 0)
1092     return;
1093     fp = fopen( tmpath, "rb" );
1094     if (!fp) {
1095 twoaday 128 msg_box (NULL, _("No GPG error description available."),
1096     _("GPG Error"), MB_INFO);
1097 werner 36 return;
1098     }
1099     errstr = new char[size+1];
1100     if (!errstr)
1101     BUG (0);
1102     fread (errstr, 1, size, fp);
1103     errstr[size] = '\0';
1104     fclose (fp);
1105     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1106     free_if_alloc (errstr);
1107     }
1108    
1109    
1110    
1111     /* check that the requested GPG keyring exist and.
1112     Return value: 0 for success. */
1113     int
1114     gnupg_access_keyring (int _pub)
1115     {
1116     int rc = 0;
1117     char *name = get_gnupg_keyring (_pub, 1);
1118     if (!name || file_exist_check (name))
1119     rc = -1;
1120     free_if_alloc (name);
1121     return rc;
1122     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26