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

Legend:
Removed from v.66  
changed lines
  Added in v.270

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26