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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide annotations)
Wed Oct 26 11:20:09 2005 UTC (19 years, 4 months ago) by twoaday
File size: 26490 byte(s)
2005-10-25  Timo Schulz  <twoaday@g10code.com>
                                                                                
        * wptGPGUtil.cpp (create_process): Hide window.
        * wptKeyPropsDlg.cpp (get_photo_tmpname): New.
        * wptClipSignEncDlg.cpp (clip_signenc_dlg_proc): Remove
        static var 'enable'.
        * wptKeygenDlg.cpp (keygen_dlg_proc): Likewise.
        (gpg_genkey_params): Make sure all primary keys are capable
        for signing and certification.
        * wptKeySigDlg.cpp (is_sig): If no item is selected, return 0.
        * wptGPG.cpp (gnupg_access_keyring): Check return value for
        NULL. Noted by Ralf.
        (get_gnupg_prog): Simplified.
        (check_homedir): Fixed. Return 0 when the dir is successfully created.
        * wptKeyManagerDlg.cpp (km_file_import): Use the hourglass to
        indicate a pending GPG process.
        * wptFileManager.cpp (op_begin, op_end): New. Indicate an start
        and and of an operation. For now just the cursor changes.
        (fm_parse_command_line): Remove debug output. Thanks to Ralf again.
        * WinPT.cpp (WinMain): Check if there is already an instance and
        set a variable early as possible.
        (load_gettext): If a previous instance was found, do not output
        any errors. Kudos to Ralf.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26