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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26