/[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 117 by twoaday, Thu Dec 8 09:26:32 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)      /* XXX: find a better way. without it, winpt --keymanager loads
676          *r_type = PGP_NONE;              the key cache twice. */
677      if (!strchr (fname, '.' ))      if (ctx->last_access.dwLowDateTime == 0)
678          return "UNKNOWN";          ctx->modified = 0;
679    
680      strncpy (file_ext, fname + strlen (fname) - 4, 4);      ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
681      file_ext[4] = '\0';      ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
682      if (!stricmp (file_ext, ".asc"))  }
683          return "ARMORED";  
684      else if (!stricmp (file_ext, ".sig")) {  
685          if (r_type)  /* Init GPG watcher table for all monitored files. */
686              *r_type = PGP_SIG;  void
687          return "SIGNED";  init_gnupg_table (void)
688      }  {      
689      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      char *p;
690          if (r_type)      int j;
691              *r_type = PGP_MESSAGE;  
692          return "ENCRYPTED";      for (j = 0; j < gpg_table_count; j++) {
693      }          p = gpg_table[j].object = m_strdup (gpg_objs[j]);
694      return "UNKNOWN";          if (!p)
695  }              BUG (NULL);
696            memset (&gpg_table[j].access, 0, sizeof (FILETIME));
697            memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
698  char*          gpg_table[j].modified = 0;
699  get_gnupg_keyring_from_options (const char * fname, int pub)      }
700  {  }
701      gpg_optfile_t opt;  
702      gpg_option_t e;  
703      char * kring = NULL;  void
704      int rc = 0;  free_gnupg_table (void)
705    {
706      rc = parse_gpg_options (fname, &opt);      int j;
707      if (rc)  
708          return NULL;      for (j=0; j < gpg_table_count; j++)
709      if (pub)          free_if_alloc (gpg_table[j].object);
710          e = find_option (opt, "keyring");  }
711      else  
712          e = find_option (opt, "secret-keyring");  
713      if (e)  /* Return the amount of files modified since the last call. */
714          kring = m_strdup (e->val);  int
715      release_gpg_options (opt);  keyring_check_last_access (void)
716    {      
717      return kring;      int rc, j;
718  }  
719        rc = 0;
720        for (j = 0; j < gpg_table_count; j++) {
721            get_last_gnupg_access (&gpg_table[j]);
722  /* XXX: does not work with write-protected floppies */          check_last_gnupg_access (&gpg_table[j]);
723  static int          if (gpg_table[j].modified)
724  my_access (const char * fname)              rc++;      
725  {      }
726      HANDLE hd;  
727      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,      return rc;
728                       NULL, OPEN_EXISTING, 0, NULL);  }
729      if (hd == INVALID_HANDLE_VALUE)  
730          return -1;  
731      CloseHandle (hd);  const char*
732      return 0;  gnupg_check_file_ext (const char *fname, int *r_type)
733  }  {              
734        char file_ext[5];
735    
736  int      if (r_type)
737  gpg_check_permissions (int showmsg)          *r_type = PGP_NONE;
738  {      if (!strchr (fname, '.' ))
739      char * p, * name = NULL;          return "UNKNOWN";
740      int failed = 0, ans=0, attrs=0;  
741        strncpy (file_ext, fname + strlen (fname) - 4, 4);
742      p = get_gnupg_path ();      file_ext[4] = '\0';
743      check_keyring (&p);      if (!stricmp (file_ext, ".asc"))
744      if (p) {          return "ARMORED";
745          name = make_filename (p, "pubring", "gpg");      else if (!stricmp (file_ext, ".sig")) {
746          free_if_alloc (p);          if (r_type)
747          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {              *r_type = PGP_SIG;
748              ans = msg_box (NULL,          return "SIGNED";
749                             _("The selected keyring has the read-only file\n"      }
750                               "attribute. In this state you do not have write\n"      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {
751                               "access. Do you want to remove the attribute?"),          if (r_type)
752                       _("GPG Information"), MB_YESNO);              *r_type = PGP_MESSAGE;
753              if (ans == IDYES) {          return "ENCRYPTED";
754                  attrs &= ~FILE_ATTRIBUTE_READONLY;      }
755                  if (!SetFileAttributes (name, attrs)) {      return "UNKNOWN";
756                      msg_box (NULL, _("Could not reset read-only state."),  }
757                               _("GPG Error"), MB_ERR);  
758                      failed = 1;  
759                  }  char*
760              }  get_gnupg_keyring_from_options (const char * fname, int pub)
761              else if (ans == IDNO) {  {
762                  /*      gpg_optfile_t opt;
763                  msg_box (NULL, _("All commands with write access to the keyring\n"      gpg_option_t e;
764                                   "will be disabled."), _("GPG Information"), MB_INFO);      char * kring = NULL;
765                  */      int rc = 0;
766                  failed = 1;  
767              }      rc = parse_gpg_options (fname, &opt);
768          }      if (rc)
769          if (my_access (name)) {          return NULL;
770              if (showmsg)      if (pub)
771                  msg_box (NULL,          e = find_option (opt, "keyring");
772                  _("You do not have file access to modify the contents of\n"      else
773                    "one or both of the selected keyrings.\n"          e = find_option (opt, "secret-keyring");
774                    "\n"      if (e)
775                    "The keyrings are in a read-only state which is propably\n"          kring = m_strdup (e->val);
776                    "caused by another program which already opened the files.\n"),      release_gpg_options (opt);
777                     _("GPG Warning"), MB_WARN);  
778              failed = 2;      return kring;
779          }  }
780      }  
781      free_if_alloc (name);  
782      return failed;  
783  } /* gpg_check_permissions */  /* XXX: does not work with write-protected floppies */
784    static int
785    my_access (const char * fname)
786  /* Check the GPG home dir. If all methods failed, try to  {
787     create the default folder. */      HANDLE hd;
788  static int      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
789  check_homedir (void)                       NULL, OPEN_EXISTING, 0, NULL);
790  {            if (hd == INVALID_HANDLE_VALUE)
791      char *homedir = NULL;          return -1;
792      int yes = 0;      CloseHandle (hd);
793        return 0;
794      homedir = get_reg_entry_gpg ("HomeDir");  }
795      if (!homedir)  
796          homedir = multi_gnupg_path ();  
797      if (!homedir)  /* Check the file permissions of the public keyring.
798          homedir = m_strdup ("c:\\gnupg");     If @showmsg is 1 output a message in case of errors.
799      if (homedir) {     Return value: 1 if read-only attribute
800          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {                   2 if file is opened by another process exclusively. */
801              yes = log_box (_("Preferences"), MB_YESNO,  int
802                             _("%s does not exit.\n"  gpg_check_permissions (int showmsg)
803                               "Do you want to create this directory?"), homedir);  {
804              if (yes == IDYES) {      char * p, * name = NULL;
805                  BOOL ec = CreateDirectory (homedir, NULL);      int failed = 0, ans=0, attrs=0;
806                  free_if_alloc (homedir);  
807                  if (ec == FALSE)      p = get_gnupg_path ();
808                      return WPTERR_DIR_CREAT;      check_keyring (&p);
809                  return 0;      if (p) {
810              }          name = make_filename (p, "pubring", "gpg");
811              return WPTERR_DIR_OPEN;          free_if_alloc (p);
812          }          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
813          free_if_alloc (homedir);              ans = msg_box (NULL,
814      }                             _("The selected keyring has the read-only file\n"
815      return 0;                               "attribute. In this state you do not have write\n"
816  }                               "access. Do you want to remove the attribute?"),
817                         _("GPG Information"), MB_YESNO);
818                if (ans == IDYES) {
819  int                  attrs &= ~FILE_ATTRIBUTE_READONLY;
820  gnupg_check_homedir (void)                  if (!SetFileAttributes (name, attrs)) {
821  {                            msg_box (NULL, _("Could not reset read-only state."),
822      char *homedir = NULL;                               _("GPG Error"), MB_ERR);
823      char *prog = NULL;                      failed = 1;
824      int rc = 0, ec = 0;                  }
825                    }
826      rc = check_homedir ();              else if (ans == IDNO) {
827      if (rc)                  /* All commands with write access will be disabled. */
828          return rc;                  failed = 1;
829      if ((homedir = get_reg_entry_gpg ("HomeDir")) &&              }
830          !(prog = get_reg_entry_gpg ("gpgProgram" ))) {          }
831          prog = make_filename (homedir, "gpg", "exe");          if (my_access (name)) {
832          if (file_exist_check (prog) == 0) {              if (showmsg)
833              rc = set_reg_entry_gpg ("gpgProgram", prog);                  msg_box (NULL,
834              if (rc)                  _("You do not have file access to modify the contents of\n"
835                  goto fail;                    "one or both of the selected keyrings.\n"
836          }                    "\n"
837          free_if_alloc (homedir);                    "The keyrings are in a read-only state which is propably\n"
838          free_if_alloc (prog);                    "caused by another program which already opened the files.\n"),
839          return rc;                     _("GPG Warning"), MB_WARN);
840      }              failed = 2;
841      if ((prog = get_reg_entry_gpg ("gpgProgram"))          }
842          && file_exist_check (prog)) {      }
843          free_if_alloc (prog);      free_if_alloc (name);
844          homedir = get_reg_entry_gpg ("HomeDir");      return failed;
845          if (!homedir) {  }
846              rc = WPTERR_GENERAL;  
847              goto fail;  
848          }  /* Check the GPG home dir. If all methods failed, try to
849          prog = make_filename (homedir, "gpg", "exe");     create the default folder. */
850          if (file_exist_check (prog) == 0) {  static int
851              rc = set_reg_entry_gpg ("gpgProgram", prog);  check_homedir (void)
852              if (rc)  {      
853                  goto fail;      char *homedir = NULL;
854              free_if_alloc (prog);      int yes = 0, set_reg=0;
855              return rc;      int rc = 0;
856          }  
857      }      homedir = get_reg_entry_gpg (GPG_REG_HOME);
858            if (!homedir) {
859      /* Change the return code if homedir doesn't exist or if the program          set_reg = 1;
860         doesn't exist. Note that exist_checks return 0 to suggest existance. */          homedir = multi_gnupg_path (0);
861      if ((!homedir || dir_exist_check (homedir)))      }
862          rc = WPTERR_GENERAL;      if (!homedir)
863                homedir = m_strdup ("c:\\gnupg");
864  fail:      if (homedir) {
865      free_if_alloc (homedir);          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
866      free_if_alloc (prog);              yes = log_box (_("Preferences"), MB_YESNO,
867      return rc;                             _("%s does not exit.\n"
868  } /* gnupg_check_homedir */                               "Do you want to create this directory?"), homedir);
869                if (yes == IDYES) {
870                    if (!CreateDirectory (homedir, NULL))
871  int                      rc = WPTERR_DIR_CREAT;
872  gnupg_copy_keyrings (void)              }
873  {              else
874      const char * pring, * sring;                  rc = WPTERR_DIR_OPEN;
875      char * file = NULL, * path = NULL;          }
876      int id = 0, rc = 0;          if (set_reg)
877      HWND hwnd;              set_reg_entry_gpg (GPG_REG_HOME, homedir);
878                free_if_alloc (homedir);
879      path = get_gnupg_path ();      }
880      if (!path)      return rc;
881          return WPTERR_GENERAL;  }
882      hwnd = GetDesktopWindow ();  
883    
884      pring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your public keyring"),  int
885                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);  gnupg_check_homedir (void)
886      if (!pring) {  {      
887          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);      char *homedir = NULL;
888          free_if_alloc (path);      char *prog = NULL;
889          return WPTERR_GENERAL;      int rc = 0;
890      }      
891      file = make_filename (path, "pubring", "gpg");      rc = check_homedir ();
892      if (file_exist_check (file) == 0) {      if (rc)
893          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          return rc;
894          if (id == IDNO)      if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&
895              goto fail;          !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {
896      }          prog = make_filename (homedir, "gpg", "exe");
897      if (!CopyFile (pring, file, FALSE)) {          if (file_exist_check (prog) == 0) {
898          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);              rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
899          rc = WPTERR_FILE_READ;              if (rc)
900          goto fail;                  goto fail;
901      }          }
902      free_if_alloc (file);          free_if_alloc (homedir);
903            free_if_alloc (prog);
904      sring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your secret keyring"),          return rc;
905                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);      }
906      if (!sring) {      if ((prog = get_reg_entry_gpg (GPG_REG_EXE))
907          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          && file_exist_check (prog)) {
908          return WPTERR_GENERAL;          free_if_alloc (prog);
909      }          homedir = get_reg_entry_gpg (GPG_REG_HOME);
910      file = make_filename (path, "secring", "gpg");          if (!homedir) {
911      if (file_exist_check (file) == 0) {              rc = WPTERR_GENERAL;
912          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);              goto fail;
913          if( id == IDNO )          }
914              goto fail;          prog = make_filename (homedir, "gpg", "exe");
915      }          if (file_exist_check (prog) == 0) {
916      if (!CopyFile (sring, file, FALSE)) {              rc = set_reg_entry_gpg (GPG_REG_EXE, prog);
917          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);              if (rc)
918          rc = WPTERR_FILE_READ;                  goto fail;
919      }              free_if_alloc (prog);
920                return rc;
921  fail:          }
922      free_if_alloc (file);      }
923      free_if_alloc (path);      
924      return rc;      /* Change the return code if homedir doesn't exist or if the program
925  } /* gnupg_import_keyrings */         doesn't exist. Note that exist_checks return 0 to suggest existance. */
926        if ((!homedir || dir_exist_check (homedir)))
927            rc = WPTERR_GENERAL;
928  void      
929  gnupg_backup_options (void)  fail:
930  {      free_if_alloc (homedir);
931      char *cfgfile = NULL;      free_if_alloc (prog);
932      char bak[512];      return rc;
933    } /* gnupg_check_homedir */
934      cfgfile = get_gnupg_cfgfile ();  
935      if (cfgfile == NULL)  
936          return;  int
937      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);  gnupg_copy_keyrings (void)
938      CopyFile (cfgfile, bak, FALSE);  {
939      free_if_alloc (cfgfile);      const char * pring, * sring;
940  } /* gnupg_backup_options */      char * file = NULL, * path = NULL;
941        int id = 0, rc = 0;
942        HWND hwnd;
943        
944  static int      path = get_gnupg_path ();
945  backup_one_file (const char *srcpath, const char *srcn,      if (!path)
946                   const char *dstpath, const char *dstn)          return WPTERR_GENERAL;
947  {      hwnd = GetDesktopWindow ();
948      char * src, * dst;  
949      BOOL rc;      pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),
950                                  _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);
951      src = make_filename (srcpath, srcn, "gpg");      if (!pring) {
952      if (!src)          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);
953          BUG (NULL);          free_if_alloc (path);
954      dst = make_filename (dstpath, dstn, "gpg");          return WPTERR_GENERAL;
955      if (!dst)      }
956          BUG (NULL);      file = make_filename (path, "pubring", "gpg");
957      rc = CopyFile (src, dst, FALSE);      if (file_exist_check (file) == 0) {
958      free_if_alloc (src);          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);
959      free_if_alloc (dst);          if (id == IDNO)
960      if (!rc)              goto fail;
961      {      }
962          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);      if (!CopyFile (pring, file, FALSE)) {
963          return WPTERR_GENERAL;          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);
964      }          rc = WPTERR_FILE_READ;
965      return 0;          goto fail;
966  } /* backup_one_file */      }
967        free_if_alloc (file);
968    
969  static int      sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),
970  check_keyring (char ** r_path)                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);
971  {      if (!sring) {
972      char * p;          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );
973      char * opt, * name;          return WPTERR_GENERAL;
974        }
975      if (!*r_path)      file = make_filename (path, "secring", "gpg");
976          return 0;      if (file_exist_check (file) == 0) {
977      p = make_filename (*r_path, "pubring", "gpg");          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);
978      if (!p || get_file_size (p) > 0)          if( id == IDNO )
979          return 0;              goto fail;
980        }
981      opt = get_gnupg_cfgfile ();      if (!CopyFile (sring, file, FALSE)) {
982      if (!opt)          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
983          BUG (0);          rc = WPTERR_FILE_READ;
984      name = get_gnupg_keyring_from_options (opt, 1);      }
985      free_if_alloc (opt);  
986      free_if_alloc (p);  fail:
987      if (!name)      free_if_alloc (file);
988          return 0;      free_if_alloc (path);
989      p = strrchr (name, '\\');      return rc;
990      if (!p)  } /* gnupg_import_keyrings */
991      {  
992          free_if_alloc (name);  
993          return 0;        void
994      }  gnupg_backup_options (void)
995      free_if_alloc (*r_path);  {
996      *r_path = new char [strlen (name)+1];      char *cfgfile = NULL;
997      memset (*r_path, 0, strlen (name));      char bak[512];
998      strncpy (*r_path, name, (p-name));  
999      free_if_alloc (name);      cfgfile = get_gnupg_cfgfile ();
1000      return 1;      if (cfgfile == NULL)
1001  }          return;
1002        _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
1003        CopyFile (cfgfile, bak, FALSE);
1004  static char*      free_if_alloc (cfgfile);
1005  get_backup_name (const char *templ)  } /* gnupg_backup_options */
1006  {  
1007      struct tm *tm;  
1008      char *p;  
1009    static int
1010      time_t t = time (NULL);  backup_one_file (const char *srcpath, const char *srcn,
1011      tm = localtime (&t);                   const char *dstpath, const char *dstn)
1012      p = new char [strlen (templ) + 8 + 1];  {
1013      if (!p)      char * src, * dst;
1014          BUG (0);      BOOL rc;
1015      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);  
1016      return p;      src = make_filename (srcpath, srcn, "gpg");
1017  }      if (!src)
1018            BUG (NULL);
1019        dst = make_filename (dstpath, dstn, "gpg");
1020  void      if (!dst)
1021  gnupg_backup_keyrings (void)          BUG (NULL);
1022  {      rc = CopyFile (src, dst, FALSE);
1023      char *srcpath = NULL, *dstpath = NULL;      free_if_alloc (src);
1024      char *name=NULL;      free_if_alloc (dst);
1025      int rc, bakmode=0;      if (!rc)
1026        {
1027      if (!reg_prefs.auto_backup)          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1028          return;          return WPTERR_GENERAL;
1029      bakmode = reg_prefs.backup.mode;      }
1030      srcpath =  get_gnupg_path ();      return 0;
1031      check_keyring (&srcpath);  } /* backup_one_file */
1032      if (bakmode == 1) {  
1033          dstpath = get_gnupg_path ();  
1034          check_keyring (&dstpath);  static int
1035      }  check_keyring (char ** r_path)
1036      else if (bakmode == 2) {  {
1037          char * tmpfile;      char * p;
1038          FILE * fp;      char * opt, * name;
1039    
1040          dstpath = m_strdup (reg_prefs.backup.path);      if (!*r_path)
1041          if (!dstpath)          return 0;
1042              BUG (0);      p = make_filename (*r_path, "pubring", "gpg");
1043          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");      if (!p || get_file_size (p) > 0)
1044          fp = fopen (tmpfile, "wb");          return 0;
1045          if (!fp)  
1046              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,      opt = get_gnupg_cfgfile ();
1047                            _("The backup drive '%s' does not seems to accessable.\n"      if (!opt)
1048                              "Please insert/check the drive to continue."), dstpath);          BUG (0);
1049          else {      name = get_gnupg_keyring_from_options (opt, 1);
1050              rc = 0;      free_if_alloc (opt);
1051              fclose (fp);      free_if_alloc (p);
1052              unlink (tmpfile);      if (!name)
1053          }          return 0;
1054          free_if_alloc (tmpfile);      p = strrchr (name, '\\');
1055          if (!fp || rc == IDCANCEL)      if (!p)
1056              return;      {
1057      }          free_if_alloc (name);
1058      else {          return 0;      
1059          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);      }
1060          return;      free_if_alloc (*r_path);
1061      }      *r_path = new char [strlen (name)+1];
1062      name = get_backup_name ("pubring-bak");      memset (*r_path, 0, strlen (name));
1063      rc = backup_one_file (srcpath, "pubring", dstpath, name);      strncpy (*r_path, name, (p-name));
1064      if (!rc)      free_if_alloc (name);
1065          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");      return 1;
1066      free_if_alloc (name);  }
1067      free_if_alloc (srcpath);  
1068      free_if_alloc (dstpath);  
1069  } /* gnupg_backup_keyrings */  static char*
1070    get_backup_name (const char *templ)
1071    {
1072  /* Display GPG error from file if possible. */      struct tm *tm;
1073  void      char *p;
1074  gnupg_display_error (void)  
1075  {            time_t t = time (NULL);
1076      char tmpath[512], * errstr;      tm = localtime (&t);
1077      size_t size = 0;      p = new char [strlen (templ) + 8 + 1];
1078      FILE * fp;      if (!p)
1079            BUG (0);
1080      GetTempPath (sizeof tmpath - 32, (tmpath));      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);
1081      strcat (tmpath, "gpg_stderr");      return p;
1082      size = get_file_size (tmpath);  }
1083      if (file_exist_check (tmpath) || size <= 0)  
1084          return;  
1085      fp = fopen( tmpath, "rb" );  /* Make backups of all keyrings. The public key ring is
1086      if (!fp) {     rotated like this pubring-%d.gpg. */
1087          msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );  void
1088          return;  gnupg_backup_keyrings (void)
1089      }  {
1090      errstr = new char[size+1];      char *srcpath = NULL, *dstpath = NULL;
1091      if (!errstr)      char *name=NULL;
1092          BUG (0);      int rc, bakmode=0;
1093      fread (errstr, 1, size, fp);  
1094      errstr[size] = '\0';      if (!reg_prefs.auto_backup)
1095      fclose (fp);          return;
1096      msg_box (NULL, errstr, _("GPG Error"), MB_INFO);      bakmode = reg_prefs.backup.mode;
1097      free_if_alloc (errstr);      srcpath = get_gnupg_path ();
1098  }      check_keyring (&srcpath);
1099        if (bakmode == 1) {
1100            dstpath = multi_gnupg_path (1);
1101            check_keyring (&dstpath);
1102  /* check that the requested GPG keyring exist and.      }
1103     Return value: 0 for success. */      else if (bakmode == 2) {
1104  int          char *tmpfile;
1105  gnupg_access_keyring (int _pub)          FILE *fp;
1106  {  
1107      int rc = 0;          dstpath = m_strdup (reg_prefs.backup.path);
1108      char *name = get_gnupg_keyring (_pub, 1);          if (!dstpath)
1109      if (!name || file_exist_check (name))              BUG (0);
1110          rc = -1;          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1111      free_if_alloc (name);          fp = fopen (tmpfile, "wb");
1112      return rc;          if (!fp)
1113  }              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1114                              _("The backup drive '%s' does not seems to accessable.\n"
1115                                "Please insert/check the drive to continue."), dstpath);
1116            else {
1117                rc = 0;
1118                fclose (fp);
1119                remove (tmpfile);
1120            }
1121            free_if_alloc (tmpfile);
1122            if (!fp || rc == IDCANCEL)
1123                return;
1124        }
1125        else {
1126            log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);
1127            return;
1128        }
1129        name = get_backup_name ("pubring-bak");
1130        rc = backup_one_file (srcpath, "pubring", dstpath, name);
1131        if (!rc)
1132            rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1133        free_if_alloc (name);
1134        free_if_alloc (srcpath);
1135        free_if_alloc (dstpath);
1136    }
1137    
1138    
1139    /* Display GPG error from file if possible. */
1140    void
1141    gnupg_display_error (void)
1142    {      
1143        char tmpath[512], * errstr;
1144        size_t size = 0;
1145        FILE * fp;
1146    
1147        GetTempPath (sizeof tmpath - 32, (tmpath));
1148        strcat (tmpath, "gpg_stderr");
1149        size = get_file_size (tmpath);
1150        if (file_exist_check (tmpath) || size <= 0)
1151            return;
1152        fp = fopen( tmpath, "rb" );
1153        if (!fp) {
1154            msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );
1155            return;
1156        }
1157        errstr = new char[size+1];
1158        if (!errstr)
1159            BUG (0);
1160        fread (errstr, 1, size, fp);
1161        errstr[size] = '\0';
1162        fclose (fp);
1163        msg_box (NULL, errstr, _("GPG Error"), MB_INFO);
1164        free_if_alloc (errstr);
1165    }
1166    
1167    
1168    
1169    /* check that the requested GPG keyring exist and.
1170       Return value: 0 for success. */
1171    int
1172    gnupg_access_keyring (int _pub)
1173    {
1174        int rc = 0;
1175        char *name = get_gnupg_keyring (_pub, 1);
1176        if (!name || file_exist_check (name))
1177            rc = -1;
1178        free_if_alloc (name);
1179        return rc;
1180    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26