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

Legend:
Removed from v.2  
changed lines
  Added in v.36

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26