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

Annotation of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 271 - (hide annotations)
Sun Nov 5 08:57:45 2006 UTC (18 years, 3 months ago) by twoaday
File size: 26504 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26