/[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 128 by twoaday, Mon Dec 19 13:05:59 2005 UTC revision 333 by twoaday, Tue Oct 13 10:51:21 2009 UTC
# Line 1  Line 1 
1  /* wptGPG.cpp - GnuPG configuration  /* wptGPG.cpp - GnuPG configuration
2   *      Copyright (C) 2001-2005 Timo Schulz   *      Copyright (C) 2001-2009 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 12  Line 12 
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.
  *  
  * You should have received a copy of the GNU General Public License  
  * along with WinPT; if not, write to the Free Software Foundation,  
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
15   */   */
16  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
17  #include <config.h>  #include <config.h>
# Line 30  Line 26 
26  #include <time.h>  #include <time.h>
27    
28  #include "wptGPG.h"  #include "wptGPG.h"
29    #include "wptGPGME.h"
30  #include "wptGpgCmds.h"  #include "wptGpgCmds.h"
 #include "wptGPGOptSkel.h"  
31  #include "wptTypes.h"  #include "wptTypes.h"
32  #include "wptNLS.h"  #include "wptNLS.h"
33  #include "wptRegistry.h"  #include "wptRegistry.h"
# Line 43  Line 39 
39  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
40  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
41    
42  struct gpg_watcher_s {  /* Context to monitor GPG file changes. */
43      FILETIME    last_access;  struct gpg_monitor_s {
44        FILETIME    last_access;    /* last write access. */
45      FILETIME    access;      FILETIME    access;
46      char        *object;      char        *object;        /* name of the object. */
47      int         modified;      char        *fpath_object;  /* full path to the object. */
48        int         modified;       /* 1 = modified. */
49  };  };
50    typedef struct gpg_monitor_s *gpg_monitor_t;
51    
52    static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
53  /* 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];  
54  static int gpg_table_count = DIM (gpg_table);  static int gpg_table_count = DIM (gpg_table);
55    
56  int idea_available = 0;  int idea_available = 0; /* if the IDEA extension is available. */
57    
58    
59  static int check_keyring (char ** r_path);  static int check_keyring (char ** r_path);
60    
# Line 65  static int check_keyring (char ** r_path Line 63  static int check_keyring (char ** r_path
63  char*  char*
64  multi_gnupg_path (int strict)  multi_gnupg_path (int strict)
65  {  {
66      static char buf[256+64];      static char buf[MAX_PATH+64];
67      BOOL ec;      BOOL ec;
68    
69      /* MSDN: buf must be at least MAX_PATH=256 bytes */      /* MSDN: buf must be at least MAX_PATH=256 bytes */
# Line 92  get_gnupg_path (void) Line 90  get_gnupg_path (void)
90      char *path;      char *path;
91    
92      path = get_reg_entry_gpg (GPG_REG_HOME);      path = get_reg_entry_gpg (GPG_REG_HOME);
93      if (path) {      if (path && dir_exist_check (path) == 0)
94          if (dir_exist_check (path) == 0)          return path;
95              return path;      free_if_alloc (path);
96          free_if_alloc (path);      return multi_gnupg_path (1);
     }  
     path = multi_gnupg_path (1);  
     return path;  
97  }  }
98    
99    
# Line 106  get_gnupg_path (void) Line 101  get_gnupg_path (void)
101     A value of NULL indicates an error. */     A value of NULL indicates an error. */
102  char*  char*
103  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
104  {      {
105      char *p = NULL;      char *optfile;
106      char *optfile = NULL;      char *path;
     char *path = NULL;  
     size_t nlen = 0;  
107    
108      path = get_gnupg_path ();      path = get_gnupg_path ();
109      if (!path)      if (!path)
110          return NULL;          return NULL;
111      p = get_reg_entry_gpg ("OptFile");      optfile = make_filename (path, GPG_CONF, NULL);
     if (p && !strcmp (p, "")) {  
         nlen = strlen (path) + 64;  
         optfile = new char[nlen + 1];  
         if (!optfile)  
             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);  
     }  
112      free_if_alloc (path);      free_if_alloc (path);
113      free_if_alloc (p);  
114      return optfile;      return optfile;
115  }  }
116    
117    
118    static char*
119    get_keyring_from_conf (const char *fname, int pub)
120    {
121        config_file_t opt;
122        conf_option_t e;
123        char *kring = NULL;
124        int rc;
125    
126        rc = parse_config (fname, &opt);
127        if (rc)
128            return NULL;
129        if (pub)
130            e = conf_find_option (opt, "keyring");
131        else
132            e = conf_find_option (opt, "secret-keyring");
133        if (e != NULL)
134            kring = m_strdup (e->val);
135        release_config (opt);
136    
137        return kring;
138    }
139    
140    
141  /* Return the full path of the keyring. If @pub is 1, the public  /* Return the full path of the keyring. If @pub is 1, the public
142     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
143  char*  char*
144  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
145  {      {    
146      char *optfile = NULL;      char *optfile;
147      char *path = NULL;      char *path;
148      char *keyring = NULL;      char *keyring;
149    
150      path = get_gnupg_path ();      path = get_gnupg_path ();
151      if (!path)      if (!path)
152          return NULL;          return NULL;
153      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
154      if (!strict && !file_exist_check (keyring)) {      if (strict && !file_exist_check (keyring)) {
155          free_if_alloc (path);          free_if_alloc (path);
156          return keyring;          return keyring;
157      }      }
158      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      else if (!strict) {
159            free_if_alloc (path);
160            return keyring;
161        }
162        if (file_exist_check (keyring) ||
163            (pub && get_file_size (keyring) == 0)) {
164          free_if_alloc (keyring);          free_if_alloc (keyring);
165          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
166          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
167            free_if_alloc (optfile);
168      }      }
169      free_if_alloc (path);      free_if_alloc (path);
170      free_if_alloc (optfile);      
171      return keyring;      return keyring;
172  }  }
173    
# Line 174  get_gnupg_keyring (int pub, int strict) Line 175  get_gnupg_keyring (int pub, int strict)
175  /* 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
176     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
177     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
178  char*  char*
179  get_gnupg_prog (void)  get_gnupg_prog (void)
180  {      {    
181      char *p;      char *path;
182      char *pgm = NULL;      char *pgm;
183    
184      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
185      if (!p) {      if (pgm)
186          char *path = get_gnupg_path ();          return pgm;
187          if (!path)      path = get_gnupg_path ();
188              return NULL;      if (!path)
189          pgm = make_filename (path, "gpg", "exe");          return NULL;    
190          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
191      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
192      return pgm;      return pgm;
193  }  }
194    
# Line 201  get_gnupg_prog (void) Line 196  get_gnupg_prog (void)
196  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
197     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
198     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
199  static char *  static char*
200  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
201  {  {    
202        gpgme_key_t key, pk;
203        gpg_keycache_t sec, pub;
204      const char *s;      const char *s;
205      char *keyid = NULL;      char *keyid = NULL;
     gpgme_key_t key;  
     gpg_keycache_t sec = keycache_get_ctx (0);  
206    
207      if (!sec)      sec = keycache_get_ctx (0);
208          BUG (0);      pub = keycache_get_ctx (1);
209      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
210      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
211          if (key_is_useable (key)) {          if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
212              s = key->subkeys->keyid;              s = key->subkeys->keyid;
213              if (s)                  if (s)
214                  keyid = m_strdup (s+8);                  keyid = m_strdup (s+8);
215              break;              break;
216          }          }
217      }      }
# Line 231  default_key_from_cache (int *ret_no_usea Line 226  default_key_from_cache (int *ret_no_usea
226     Return value: 0 on success. */     Return value: 0 on success. */
227  int  int
228  gnupg_load_config (void)  gnupg_load_config (void)
229  {  {    
230      int rc;      config_file_t opt;
231      gpg_optfile_t opt;      char *conf;
232      gpg_option_t o;      int rc = 0;
233      char *conf = get_gnupg_cfgfile ();      
234        conf = get_gnupg_cfgfile ();
235      if (!conf)      if (!conf)
236          return -1;          return -1;
237      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
238          free_if_alloc (conf);          free_if_alloc (conf);
239          return -1;          return -1;
240      }      }
     o = find_option (opt, "ask-cert-level");  
     if (o)  
         reg_prefs.gpg.ask_cert_level = 1;  
     release_gpg_options (opt);  
241      free_if_alloc (conf);      free_if_alloc (conf);
242      return 0;      if (conf_find_option (opt, "ask-cert-level"))
243            reg_prefs.gpg.ask_cert_level = 1;
244        if (conf_find_option (opt, "ask-cert-expire"))
245            reg_prefs.gpg.ask_cert_expire = 1;
246        /* The 'textmode' option for GPG is useful for text files
247           but it breaks the output of any binary data. Thus we return
248           a warning here to inform the user that binary output is broken. */
249        if (conf_find_option (opt, "textmode"))
250            rc = -2;
251        release_config (opt);
252    
253        return rc;
254  }  }
255    
256    
257    /* handle the case the user added a '!' to force a subkey. */
258    static char*
259    extract_keyid (const char *val)
260    {    
261        size_t len = strlen (val);
262    
263        if (len > 1 && val[len-1] == '!')
264            return substr (val, 0, len-1);
265        return m_strdup (val);
266    }
267    
268    
269    /* Return the default key.
270       This can be either a substring or a key ID. */
271  char*  char*
272  get_gnupg_default_key (void)  get_gnupg_default_key (void)
273  {      {    
274      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
275      gpg_option_t e;      conf_option_t e;
276      char * keyid = NULL, * optfile = NULL;      char *keyid = NULL, *optfile = NULL;
277      int no_usable=0, rc = 0;      int no_usable=0;
278    
279      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
280      if (!optfile)      if (!optfile)
281          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
282      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
283          free_if_alloc (optfile);          free_if_alloc (optfile);
284          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
285      }      }
286      e = find_option( opt, "default-key" );      /* First we search for config entries which specify a default key. */
287      if ( e )      e = conf_find_option (opt, "default-key");
288          keyid = m_strdup( e->val );      if (!e)
289      if( !e ) {          e = conf_find_option (opt, "local-user");
290          e = find_option( opt, "local-user" );      if (e)
291          if( e )          keyid = extract_keyid (e->val);
292              keyid = m_strdup( e->val );  
     }  
     if( !e ) {  
         e = find_option( opt, "encrypt-to" );  
         if( e )  
             keyid = m_strdup( e->val );  
     }  
293      free_if_alloc (optfile);      free_if_alloc (optfile);
294      release_gpg_options (opt);      release_config (opt);
295    
296        /* If no entry in the config has been found, we get a key
297           from the key cache. */
298      if (!keyid)      if (!keyid)
299          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
300      return keyid;      return keyid;
301  } /* get_gnupg_default_key */  }
302    
303    
304  /* Check if GPG4WIN is available and if so, use the  /* Check if GPG4WIN is available and if so, use the
# Line 321  check_gnupg_prog (void) Line 332  check_gnupg_prog (void)
332    
333    
334  static int  static int
335  parse_version_nr (const char * buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
336  {  {  
337      char tmp[8];      char *p;
338      int i;      char *tmp = m_strdup(buf);
339            
340      i=0;      int pos=0;
341      while (buf && *buf != '.' && i < 8)      while ((p = strsep(&tmp, ".")) != NULL) {
342          tmp[i++] = *buf++;          switch (++pos) {
343      tmp[i] = 0; buf++;          case 1: *major = atoi (p); break;
344      *major = atol( tmp );          case 2: *minor = atoi (p); break;
345      i=0;          case 3: *patch = atoi (p); break;
346      while (buf && *buf != '.' && i < 8)          }
347          tmp[i++] = *buf++;      }
348      tmp[i] = 0; buf++;      delete[] tmp;  
349      *minor = atol (tmp);      if (pos != 3)
350      i=0;          return -1;  
     while (buf && isdigit (*buf) && i < 8)  
         tmp[i++] = *buf++;  
     tmp[i] = 0;  
     *patch = atol (tmp);  
351      return 0;      return 0;
352  }  }
353    
# Line 349  parse_version_nr (const char * buf, int Line 356  parse_version_nr (const char * buf, int
356     version given in @r_major.@r_minor.@r_patch. On success these     version given in @r_major.@r_minor.@r_patch. On success these
357     variables contain the GPG version which is installed. */     variables contain the GPG version which is installed. */
358  int  int
359  check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)  check_gnupg_engine (const char *need_gpg_ver,
360                        int *r_major, int *r_minor, int *r_patch)
361  {  {
     gpgme_ctx_t ctx;  
362      gpgme_engine_info_t inf;      gpgme_engine_info_t inf;
363      char *eng = NULL;      char *eng = NULL;
364      int major=0, minor=0, patch=0;      int major=0, minor=0, patch=0;
365        int need_major = 0, need_minor = 0, need_patch = 0;
366      int rc = 1;      int rc = 1;
367            
368      gpgme_new (&ctx);      /* Convert the needed GPG version to the integer format. */
369      inf = gpgme_ctx_get_engine_info (ctx);      if (parse_version_nr (need_gpg_ver,
370      if (!inf) {                            &need_major, &need_minor, &need_patch))
371          gpgme_release (ctx);          return 1;
372          return -1;      
373      }      if (gpgme_get_engine_info (&inf))
374         return -1;
375    
376      /* 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. */
377      if (gpg_get_version (&eng))      if (gpg_get_version (&eng))
378          return -1;       return -1;
379      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
380          idea_available = 1;          idea_available = 1;
381      free (eng);      safe_free (eng);
382      rc = parse_version_nr (inf->version, &major, &minor, &patch);    
383      if (rc) {      if (parse_version_nr (inf->version, &major, &minor, &patch))
384          gpgme_release (ctx);          return 1;
         return rc;  
     }  
385    
386      if (major > *r_major)      if (major > need_major)
387          rc = 0;          rc = 0;
388      else if (major == *r_major && minor > *r_minor)                else if (major == need_major && minor > need_minor)      
389          rc = 0;          rc = 0;
390      else if (major == *r_major && minor == *r_minor &&      else if (major == need_major && minor == need_minor &&
391               patch >= *r_patch)               patch >= need_patch)
392          rc = 0;          rc = 0;
393    
394        /* Return the current GPG version. */
395      *r_major = major;      *r_major = major;
396      *r_minor = minor;      *r_minor = minor;
397      *r_patch = patch;      *r_patch = patch;
# Line 391  check_gnupg_engine (int *r_major, int *r Line 399  check_gnupg_engine (int *r_major, int *r
399  }  }
400    
401    
402  int  /* Count the keyring entries in the gpg.conf file.
403  check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)     Return value: 0 on success. */
404    static int
405    cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
406  {  {
407      gpg_optfile_t opt;          config_file_t opt;    
408      gpg_option_t e;      conf_option_t e;
     int rc = 0;  
409    
410      *r_secrings = 0;      *r_secrings = 0;
411      *r_pubrings = 0;      *r_pubrings = 0;
     rc = parse_gpg_options( fname, &opt );  
     if( rc )  
         return WPTERR_FILE_OPEN;  
412    
413      for( e = opt->list; e; e = e->next ) {      if (parse_config (fname, &opt))
414          if( !strcmp( e->name, "secret-keyring" ) ) {          return WPTERR_FILE_OPEN;
415              if( !file_exist_check( e->val ) )      for (e = opt->list; e; e = e->next) {
416            if (!strcmp (e->name, "secret-keyring")) {
417                if (!file_exist_check (e->val))
418                  r_secrings[0]++;                  r_secrings[0]++;
419          }          }
420          else if( !strcmp( e->name, "keyring" ) ) {          else if (!strcmp (e->name, "keyring")) {
421              if( !file_exist_check( e->val ) )              if (!file_exist_check (e->val))
422                  r_pubrings[0]++;                  r_pubrings[0]++;
423          }          }
424      }      }
425      release_gpg_options( opt );      release_config (opt);
426      return 0;      return 0;
427  } /* check_gnupg_cfgfile */  }
428    
429    
430  /*  /* Usually GPG creates the pubring.gpg, secring.gpg on
431   * Check if both keyrings are located in the gnupg home directory.     the first start, but to make sure they always exist
432   */     create them empty if needed. */
433    static void
434    create_empty_keyring (int _pub)
435    {
436        char *name;
437        FILE *fp;
438    
439        name = get_gnupg_keyring (_pub, 0);
440        if (name && file_exist_check (name) != 0) {
441            fp = fopen (name, "ab");
442            if (fp != NULL)
443                fclose (fp);
444        }
445        free_if_alloc (name);
446    }
447    
448    
449    /* Check if both keyrings are located in the gnupg home directory. */
450  int  int
451  gnupg_access_files (void)  gnupg_access_files (void)
452  {  {
# Line 430  gnupg_access_files (void) Line 455  gnupg_access_files (void)
455      int secrings = 0, pubrings = 0;      int secrings = 0, pubrings = 0;
456      char *optfile;      char *optfile;
457    
458        create_empty_keyring (1);
459      if (gnupg_access_keyring (1))      if (gnupg_access_keyring (1))
460          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
461      else      else
462          pubring_ok = 1;          pubring_ok = 1;
463    
464        create_empty_keyring (0);
465      if (gnupg_access_keyring (0))      if (gnupg_access_keyring (0))
466          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
467      else      else
# Line 446  gnupg_access_files (void) Line 473  gnupg_access_files (void)
473              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
474          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
475          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
476              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
477              if (!rc && secrings && pubrings) {              if (!rc && secrings > 0 && pubrings > 0) {
478                  free_if_alloc (optfile);                  free_if_alloc (optfile);
479                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
480              }              }
# Line 463  gnupg_access_files (void) Line 490  gnupg_access_files (void)
490          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
491      }      }
492      return rc;      return rc;
493  } /* gnupg_access_files */  }
   
   
 static int  
 create_gpg_options (void)  
 {  
     FILE *fp;  
     char *s, *optfile;  
   
     s = get_gnupg_path ();  
     if( s == NULL )  
         return WPTERR_FILE_CREAT;  
     optfile = make_filename (s, GPG_CONF, NULL);  
     fp = fopen( optfile, "wb" );  
     if( fp == NULL ) {    
         return WPTERR_FILE_CREAT;  
         goto fail;  
     }  
     fwrite( options_skel, 1, strlen( options_skel ), fp );  
     fclose( fp );  
494    
 fail:  
     free_if_alloc( s );  
     free_if_alloc( optfile );  
     return 0;  
 } /* create_gpg_options */  
495    
496    
497  /*  /* Return the contents of the options file as a char buf. */
498   * Return the contents of the options file as a char buf.  char*
  */  
 char *  
499  get_gnupg_config (void)  get_gnupg_config (void)
500  {  {
501      FILE * fp;      FILE *fp;
502      char * p = NULL, * optfile = NULL;      char *p = NULL, *optfile;
503      int fsize, rc = 0;      int fsize;
504                    
505      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
506      if( optfile == NULL )      if (!optfile)
507          return NULL;          return NULL;
508      fsize = get_file_size( optfile );      fsize = get_file_size (optfile);
509      if( !fsize ) {      if (fsize < 1 || fsize > 100000)
510          rc = create_gpg_options( );          goto leave; /* too large or does not exist */
511          if ( rc )      
512              return NULL;      fp = fopen (optfile, "rb");
513          fsize = get_file_size( optfile );      if (!fp)
514      }          goto leave;
     if( fsize > 100000 )  
         goto leave; /* too large */  
515      p = new char[fsize+1];      p = new char[fsize+1];
516      if( p == NULL )      if (!p)
517          BUG( NULL );          BUG (NULL);
518      fp = fopen( optfile, "rb" );      fread (p, 1, fsize, fp);
519      if( fp == NULL ) {      fclose (fp);
         free_if_alloc( p );  
         return NULL;  
     }  
     fread( p, 1, fsize, fp );  
     fclose( fp );  
520      p[fsize] = '\0';      p[fsize] = '\0';
521      free_if_alloc( optfile );      
   
522  leave:  leave:
523        free_if_alloc (optfile);
524      return p;      return p;
525  } /* get_gnupg_config */  }
526    
527    
528    /* Set the default key in the gpg.conf.
529       If @key is NULL, the entry will be deleted. */
530  int  int
531  set_gnupg_default_key (const char * key)  set_gnupg_default_key (const char *key)
532  {  {
533      gpg_optfile_t opt;      config_file_t opt;
534      gpg_option_t e;      conf_option_t e;
535      char *optfile = NULL;      char *optfile = NULL;
536      int rc = 0;      int rc = 0;
537    
538      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
539      if (!optfile)      if (!optfile)
540          return -1;          return WPTERR_FILE_OPEN;
541      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
542      if( rc ) {      if (rc) {
543          free_if_alloc (optfile);          free_if_alloc (optfile);
544          return -1;          return WPTERR_GENERAL;
545      }      }
546      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
547      if (e) {      if (e && !key)
548            e->used = 0;
549        else if (e) {
550          free_if_alloc (e->val);          free_if_alloc (e->val);
551          e->val = m_strdup (key);          e->val = m_strdup (key);
552          e->used = 1;          e->used = 1;
553      }      }
554      else      else if (key)
555          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
556      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
557    
558      free_if_alloc (optfile);      free_if_alloc (optfile);
559      release_gpg_options (opt);      release_config (opt);
   
560      return rc;      return rc;
561  } /* set_gnupg_default_key */  }
562    
563    
564  /*  /* Set the contents of the options file. */
  * Set the contents of the options file.  
  */  
565  int  int
566  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
567  {  {
568      FILE *fp;        FILE *fp;  
569      char *optfile = NULL;      char *optfile;
570    
571      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
572      if( optfile == NULL )      if (!optfile)
573          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
574    
575      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
576      if( fp == NULL ) {      if (!fp) {
577          free_if_alloc( optfile );          free_if_alloc (optfile);
578          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
579      }      }
580      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
581      fclose( fp );      fclose (fp);
582      free_if_alloc( optfile );      free_if_alloc (optfile);
583      return 0;      return 0;
584  } /* set_gnupg_options */  }
585    
586  /*  
587   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
588   */     Return value: 0 on success. */
589    static int
590    check_arg_file_exist (const char *buf)
591    {
592        const char *s = "load-extension ";
593    
594        /* XXX: this is a bit of a kludge because we just
595                detect errors for 'load-extension'. */
596        if (!strncmp (buf, s, strlen (s)))
597            buf += strlen (s);
598        else
599            return 0;
600        return file_exist_check (buf);
601    }
602    
603    
604    /* Check if the line contains a valid GPG argument. */
605  static int  static int
606  check_line( const char *buf )  check_line (const char *buf)
607  {  {
608      int j, len;      int j, len;
609      int rc = 0;      int rc = 0;
610    
611      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
612          return 1;          return 1;
613      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
614      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
615          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
616          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
617      }      }
   
618      return rc;      return rc;
619  } /* check_line */  }
620    
621    
622  int  int
623  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
624  {  {
625      char line[1024];      char line[1024];
626      int nbytes = 0;      int nbytes = 0, lineno=0;
627      unsigned j;      unsigned j;
628                    
629      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
630          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
631          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
632              line[nbytes] = '\0';              line[nbytes] = '\0';
633              if( !check_line( line ) ) {              lineno++;
634                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
635                    if (showerr)
636                        log_box ("GPG Config File", MB_ERR,
637                                 "gpg.conf:%d: invalid keyword '%s'",
638                                 lineno, line);
639                  return 1;                        return 1;      
640              }              }
641                if (check_arg_file_exist (line))
642                    return WPTERR_FILE_EXIST;
643              nbytes = 0;              nbytes = 0;
644          }                }
645      }      }
   
646      return 0;      return 0;
647  } /* check_gnupg_options */  }
648    
649    
650  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
651  static int  static int
652  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
653  {  {
654      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
655    
656      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
657      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
658      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);  
659          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
660      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
661      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
662      return 0;      return 0;
663  }  }
664    
665    
666  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
667  static void  static void
668  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
669  {                {              
670      ctx->modified = 0;      ctx->modified = 0;
671    
672      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
673          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
674          ctx->modified = 1;          ctx->modified = 1;
675        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
676      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
677          ctx->modified = 0;          ctx->modified = 0;
678    
# Line 677  check_last_gnupg_access (gpg_watcher_s * Line 681  check_last_gnupg_access (gpg_watcher_s *
681  }  }
682    
683    
684  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
685  void  void
686  init_gnupg_table (void)  init_gnupg_table (void)
687  {        {      
688      char *p;      char *path;
689      int j;      int j;
690    
691        path = get_gnupg_path ();
692      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
693          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
694          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
695          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
696          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
697          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
698      }      }
699        free_if_alloc (path);
700  }  }
701    
702    
703    /* Release the GPG monitor table. */
704  void  void
705  free_gnupg_table (void)  free_gnupg_table (void)
706  {  {
707      int j;      for (int j=0; j < gpg_table_count; j++) {
   
     for (j=0; j < gpg_table_count; j++)  
708          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
709            free_if_alloc (gpg_table[j].fpath_object);
710        }
711  }  }
712    
713    
714  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
715  int  int
716  keyring_check_last_access (void)  keyring_check_last_access (void)
717  {        {
718      int rc, j;      int nfiles;
719    
720      rc = 0;      nfiles = 0;
721      for (j = 0; j < gpg_table_count; j++) {      for (int pos = 0; pos < gpg_table_count; pos++) {
722          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
723          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
724          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
725              rc++;                    nfiles++;
726      }      }
727    
728      return rc;      return nfiles;
729  }  }
730    
731    
# Line 742  gnupg_check_file_ext (const char *fname, Line 748  gnupg_check_file_ext (const char *fname,
748              *r_type = PGP_SIG;              *r_type = PGP_SIG;
749          return "SIGNED";          return "SIGNED";
750      }      }
751      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
752                  !stricmp (file_ext, ".pgp")) {
753          if (r_type)          if (r_type)
754              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
755          return "ENCRYPTED";          return "ENCRYPTED";
# Line 751  gnupg_check_file_ext (const char *fname, Line 758  gnupg_check_file_ext (const char *fname,
758  }  }
759    
760    
761  char*  /* Check if the device where file @fname is stored on, is write-protected. */
 get_gnupg_keyring_from_options (const char * fname, int pub)  
 {  
     gpg_optfile_t opt;  
     gpg_option_t e;  
     char * kring = NULL;  
     int rc = 0;  
   
     rc = parse_gpg_options (fname, &opt);  
     if (rc)  
         return NULL;  
     if (pub)  
         e = find_option (opt, "keyring");  
     else  
         e = find_option (opt, "secret-keyring");  
     if (e)  
         kring = m_strdup (e->val);  
     release_gpg_options (opt);  
   
     return kring;  
 }  
   
   
   
 /* XXX: does not work with write-protected floppies */  
762  static int  static int
763  my_access (const char *fname)  check_file_access (const char *fname, int mode)
764  {  {
765      HANDLE hd;      HANDLE hd;
766      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,  
767        if (!mode)
768            mode = FILE_SHARE_WRITE;
769        hd = CreateFile (fname, GENERIC_WRITE, mode,
770                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
771      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
772          return -1;          return -1;
# Line 788  my_access (const char *fname) Line 774  my_access (const char *fname)
774      return 0;      return 0;
775  }  }
776    
777        
778    /* Check the device where the file @fname is stored on, is either
779       write-protected or if the file is already opened by another process
780       exclusively. And as a result, we cannot use the file for output. */
781    int
782    gpg_check_file_permissions (const char *fname, int mode)
783    {
784        int api_mode;
785        
786        switch (mode) {
787        case 0: api_mode = FILE_SHARE_READ; break;
788        case 1: api_mode = FILE_SHARE_WRITE; break;
789        case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
790        default: api_mode = FILE_SHARE_READ; break;
791        }
792    
793        return check_file_access (fname, api_mode);
794    }
795    
796    
797  /* Check the file permissions of the public keyring.  /* Check the file permissions of the public keyring.
798     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 801  gpg_check_permissions (int showmsg) Line 806  gpg_check_permissions (int showmsg)
806      int failed = 0, ans=0, attrs=0;      int failed = 0, ans=0, attrs=0;
807    
808      p = get_gnupg_path ();      p = get_gnupg_path ();
809      if (check_keyring (&p) && p) {      if (p && check_keyring (&p)) {
810          name = make_filename (p, "pubring", "gpg");          name = make_filename (p, "pubring", "gpg");
811          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
812              ans = msg_box (NULL,              ans = msg_box (NULL,
# Line 822  gpg_check_permissions (int showmsg) Line 827  gpg_check_permissions (int showmsg)
827                  failed = 1;                  failed = 1;
828              }              }
829          }          }
830          if (my_access (name)) {          if (gpg_check_file_permissions (name, 1)) {
831              if (showmsg)              if (showmsg)
832                  msg_box (NULL,                  msg_box (NULL,
833                  _("You do not have file access to modify the contents of\n"                  _("You do not have file access to modify the contents of\n"
# Line 845  gpg_check_permissions (int showmsg) Line 850  gpg_check_permissions (int showmsg)
850  int  int
851  gnupg_check_homedir (void)  gnupg_check_homedir (void)
852  {        {      
853      char *homedir = NULL;      char *homedir;
854      int val = 0;      int val;
855      int rc = 0;      int rc = 0;
856    
857      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
# Line 871  gnupg_check_homedir (void) Line 876  gnupg_check_homedir (void)
876    
877    
878  int  int
879    gnupg_import_keypair (void)
880    {
881        const char *file;
882        gpgme_error_t err;
883        GPGME gpgme;
884        HWND hwnd = GetDesktopWindow ();
885    
886        file = get_fileopen_dlg (hwnd, _("Please choose your Key Pair"),
887                                 "GPG Key File (*.gpg)\0*.gpg\0"
888                                 "GPG Armored Key File (*.asc)\0*.asc\0\0",
889                                 NULL);
890        if (file == NULL)
891            return WPTERR_FILE_OPEN;
892        err = gpgme.importFromFile (file);
893        if (err)
894            msg_box (hwnd, gpgme_strerror (err), _("WinPT Error"), MB_ERR);
895        else
896            msg_box (hwnd, _("Key pair successfully imported."), "WinPT", MB_OK);
897        return 0;
898    }
899    
900    int
901  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
902  {  {
903      const char * pring, * sring;      const char *pring, *sring;
904      char * file = NULL, * path = NULL;      char *file = NULL, *path;
905      int id = 0, rc = 0;      int id, rc = 0;
906      HWND hwnd;      HWND hwnd;
907            
908      path = get_gnupg_path ();      path = get_gnupg_path ();
# Line 883  gnupg_copy_keyrings (void) Line 910  gnupg_copy_keyrings (void)
910          return WPTERR_GENERAL;          return WPTERR_GENERAL;
911      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
912    
913      pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
914                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
915      if (!pring) {      if (!pring) {
916          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("No keyring was chosen. Exit."),
917                     _("WinPT Error"), MB_ERR);
918          free_if_alloc (path);          free_if_alloc (path);
919          return WPTERR_GENERAL;          return WPTERR_GENERAL;
920      }      }
921      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
922      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
923          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old public keyring?"),
924                          "WinPT", MB_INFO|MB_YESNO);
925          if (id == IDNO)          if (id == IDNO)
926              goto fail;              goto fail;
927      }      }
928      if (!CopyFile (pring, file, FALSE)) {      if (!CopyFile (pring, file, FALSE)) {
929          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("Could not copy public keyring."),
930                     _("WinPT Error"), MB_ERR);
931          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
932          goto fail;          goto fail;
933      }      }
934      free_if_alloc (file);      free_if_alloc (file);
935    
936      sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),      sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
937                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
938      if (!sring) {      if (!sring) {
939          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          msg_box (NULL, _("No keyring was chosen. Exit."),
940                     _("WinPT Error"), MB_ERR);
941          return WPTERR_GENERAL;          return WPTERR_GENERAL;
942      }      }
943      file = make_filename (path, "secring", "gpg");      file = make_filename (path, "secring", "gpg");
944      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
945          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old secret keyring?"),
946          if( id == IDNO )                        "WinPT", MB_INFO|MB_YESNO);
947            if (id == IDNO)
948              goto fail;              goto fail;
949      }      }
950      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
951          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy secret keyring."), _("WinPT Error"), MB_ERR);
952          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
953      }      }
954    
# Line 924  fail: Line 956  fail:
956      free_if_alloc (file);      free_if_alloc (file);
957      free_if_alloc (path);      free_if_alloc (path);
958      return rc;      return rc;
959  } /* gnupg_import_keyrings */  }
960    
961    
962  /* Backup the gpg.conf file. */  /* Backup the gpg.conf file. */
963  void  void
964  gnupg_backup_options (void)  gnupg_backup_options (void)
965  {  {
966      char *cfgfile = NULL;      char *cfgfile;
967      char bak[512];      char bak[MAX_PATH+32];
968    
969      cfgfile = get_gnupg_cfgfile ();      cfgfile = get_gnupg_cfgfile ();
970      if (!cfgfile)      if (!cfgfile)
# Line 947  static int Line 979  static int
979  backup_one_file (const char *srcpath, const char *srcn,  backup_one_file (const char *srcpath, const char *srcn,
980                   const char *dstpath, const char *dstn)                   const char *dstpath, const char *dstn)
981  {  {
982      char * src, * dst;      char *src, *dst;
983      BOOL rc;      BOOL rc;
984    
985      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
986      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
987      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
988      free_if_alloc (src);      free_if_alloc (src);
989      free_if_alloc (dst);      free_if_alloc (dst);
990      if (!rc)      if (!rc) {
     {  
991          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
992          return WPTERR_GENERAL;          return WPTERR_GENERAL;
993      }      }
994      return 0;      return 0;
995  } /* backup_one_file */  }
996    
997    
998  /* Figure out first public keyring which is not empty.  /* Figure out first public keyring which is not empty.
# Line 980  check_keyring (char **r_path) Line 1007  check_keyring (char **r_path)
1007      if (!*r_path)      if (!*r_path)
1008          return 0;          return 0;
1009      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
1010      if (!p || get_file_size (p) <= 0)      if (get_file_size (p) <= 0)
1011          return 0;          return 0;
1012    
1013      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
1014      if (!opt)      if (!opt)
1015          BUG (0);          BUG (0);
1016      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
1017      free_if_alloc (opt);      free_if_alloc (opt);
1018      free_if_alloc (p);      free_if_alloc (p);
1019      if (!name)      if (!name)
# Line 1010  static char* Line 1037  static char*
1037  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1038  {  {
1039      struct tm *tm;      struct tm *tm;
1040        const char *fmt;
1041      char *p;      char *p;
1042      time_t t;      time_t t;
1043    
1044      t = time (NULL);      t = time (NULL);
1045      tm = localtime (&t);      tm = localtime (&t);
1046      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1047        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1048      if (!p)      if (!p)
1049          BUG (0);          BUG (0);
1050      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1051      return p;      return p;
1052  }  }
1053    
1054    
1055  /* Make backups of all keyrings. The public key ring is  /* Make backups of all keyrings. The public key ring is rotated like
1056     rotated like this pubring-%d.gpg. */     this pubring-%d.gpg.
1057       If @auto_backup is false, no action is performed.
1058       @include_secr indicated if the backup includes the secret keyring. */
1059  void  void
1060  gnupg_backup_keyrings (void)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1061  {  {
1062      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1063      char *name=NULL;      char *name;
1064      int rc, bakmode=0;      int rc;
1065    
1066      if (!reg_prefs.auto_backup)      if (!auto_backup)
1067          return;          return;
     bakmode = reg_prefs.backup.mode;  
1068      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1069      check_keyring (&srcpath);      check_keyring (&srcpath);
1070      if (bakmode == 1) {      if (backup_mode == 1) {
1071          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1072               and destination folder will be the same. */
1073            dstpath = get_gnupg_path ();
1074          check_keyring (&dstpath);          check_keyring (&dstpath);
1075      }      }
1076      else if (bakmode == 2) {      else if (backup_mode == 2) {
1077          char *tmpfile;          char *tmpfile;
1078          FILE *fp;          FILE *fp;
1079    
1080          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1081          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1082          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1083          if (!fp)          if (!fp)
1084              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1085                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1086                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1087          else {          else {
1088              rc = 0;              rc = 0;
1089              fclose (fp);              fclose (fp);
1090              remove (tmpfile);              DeleteFile (tmpfile);
1091          }          }
1092          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1093          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1094                free_if_alloc (dstpath);
1095                free_if_alloc (srcpath);
1096              return;              return;
1097            }
1098      }      }
1099      else {      else {
1100          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1101            free_if_alloc (srcpath);
1102          return;          return;
1103      }      }
1104      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
1105      rc = backup_one_file (srcpath, "pubring", dstpath, name);      rc = backup_one_file (srcpath, "pubring", dstpath, name);
1106      if (!rc)      if (!rc && include_secr)
1107          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1108      free_if_alloc (name);      free_if_alloc (name);
1109      free_if_alloc (srcpath);      free_if_alloc (srcpath);
# Line 1077  gnupg_backup_keyrings (void) Line 1111  gnupg_backup_keyrings (void)
1111  }  }
1112    
1113    
 /* 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);  
 }  
   
   
   
1114  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1115     Return value: 0 for success. */     Return value: 0 for success. */
1116  int  int

Legend:
Removed from v.128  
changed lines
  Added in v.333

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26