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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26