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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26