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

Diff of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.34  
changed lines
  Added in v.58

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26