/[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 117 by twoaday, Thu Dec 8 09:26:32 2005 UTC revision 407 by twoaday, Mon Feb 6 19:26:03 2012 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 "wptGpgCmds.h"  #include "wptGPGME.h"
30  #include "wptGPGOptSkel.h"  #include "wptGPGCmds.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    
61    
62  /* Return the application data folder of the current user. */  /* Return the application data folder of the current user. */
63  static 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];
     BOOL ec;  
67    
68      /* MSDN: buf must be at least MAX_PATH=256 bytes */      /* MSDN: buf must be at least MAX_PATH=256 bytes */
69      memset (buf, 0, sizeof (buf));      memset (buf, 0, sizeof (buf));
70      /* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */      if (!SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE)) {
71      ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE);          log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed with: %d\r\n",
     if (ec != 1) {  
         log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed\r\n",  
72                     (int)GetLastError ());                     (int)GetLastError ());
73          return NULL;          return NULL;
74      }      }
# Line 84  multi_gnupg_path (int strict) Line 79  multi_gnupg_path (int strict)
79  }  }
80    
81    
82  /* 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
83     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. */
 */  
84  char*  char*
85  get_gnupg_path (void)  get_gnupg_path (void)
86  {  {
87      char *p = NULL;      char *path = get_reg_entry_gpg (GPG_REG_HOME);
88      char *path = NULL;      if (path && dir_exist_check (path) == 0)
       
     p = get_reg_entry_gpg (GPG_REG_HOME);  
     if (p) {  
         path = m_strdup (p);  
         free_if_alloc (p);  
89          return path;          return path;
90      }      free_if_alloc (path);
91      else      return multi_gnupg_path (1);
         return multi_gnupg_path (1);  
     return m_strdup ("c:\\gnupg");  
92  }  }
93    
94    
# Line 109  get_gnupg_path (void) Line 96  get_gnupg_path (void)
96     A value of NULL indicates an error. */     A value of NULL indicates an error. */
97  char*  char*
98  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
99  {      {
100      char *p = NULL;      char *path = get_gnupg_path ();
     char *optfile = NULL;  
     char *path = NULL;  
     size_t nlen = 0;  
   
     path = get_gnupg_path ();  
101      if (!path)      if (!path)
102          return NULL;          return NULL;
103      p = get_reg_entry_gpg ("OptFile");      char *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);  
     }  
104      free_if_alloc (path);      free_if_alloc (path);
105      free_if_alloc (p);  
106      return optfile;      return optfile;
107  }  }
108    
109    
110    static char*
111    get_keyring_from_conf (const char *fname, int pub)
112    {
113        config_file_t opt;
114        conf_option_t e;
115        char *kring = NULL;
116    
117        if (parse_config (fname, &opt))
118            return NULL;
119        if (pub)
120            e = conf_find_option (opt, "keyring");
121        else
122            e = conf_find_option (opt, "secret-keyring");
123        if (e != NULL)
124            kring = m_strdup (e->val);
125        release_config (opt);
126    
127        return kring;
128    }
129    
130    
131  /* 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
132     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
133  char*  char*
134  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
135  {      {    
136      char *optfile = NULL;      char *optfile;
137      char *path = NULL;      char *path;
138      char *keyring = NULL;      char *keyring;
139    
140      path = get_gnupg_path ();      path = get_gnupg_path ();
141      if (!path)      if (!path)
142          return NULL;          return NULL;
143      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
144      if (!strict && !file_exist_check (keyring)) {      if (strict && !file_exist_check (keyring)) {
145          free_if_alloc (path);          free_if_alloc (path);
146          return keyring;          return keyring;
147      }      }
148      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      else if (!strict) {
149            free_if_alloc (path);
150            return keyring;
151        }
152        if (file_exist_check (keyring) ||
153            (pub && get_file_size (keyring) == 0)) {
154          free_if_alloc (keyring);          free_if_alloc (keyring);
155          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
156          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
157            free_if_alloc (optfile);
158      }      }
159      free_if_alloc (path);      free_if_alloc (path);
160      free_if_alloc (optfile);      
161      return keyring;      return keyring;
162  }  }
163    
# Line 177  get_gnupg_keyring (int pub, int strict) Line 165  get_gnupg_keyring (int pub, int strict)
165  /* Return the full path (with the gpg exe name). First the registry is scanned  /* Return the full path (with the gpg exe name). First the registry is scanned
166     for the entry 'gpgProgram'. If it wasn't set, the default path is the     for the entry 'gpgProgram'. If it wasn't set, the default path is the
167     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
168  char*  char*
169  get_gnupg_prog (void)  get_gnupg_prog (void)
170  {      {    
171      char *p;      char *path;
172      char *pgm = NULL;      char *pgm;
173    
174      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
175      if (!p) {      if (pgm)
176          char *path = get_gnupg_path ();          return pgm;
177          if (!path)      path = get_gnupg_path ();
178              return NULL;      if (!path)
179          pgm = make_filename (path, "gpg", "exe");          return NULL;    
180          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
181      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
182      return pgm;      return pgm;
183  }  }
184    
# Line 204  get_gnupg_prog (void) Line 186  get_gnupg_prog (void)
186  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
187     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
188     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
189  static char *  static char*
190  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
191  {  {    
192        gpgme_key_t key, pk;
193        gpg_keycache_t sec, pub;
194      const char *s;      const char *s;
195      char *keyid = NULL;      char *keyid = NULL;
     gpgme_key_t key;  
     gpg_keycache_t sec = keycache_get_ctx (0);  
196    
197      if (!sec)      sec = keycache_get_ctx (0);
198          BUG (0);      pub = keycache_get_ctx (1);
199      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
200      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
201          if (key_is_useable (key)) {          if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
202              s = key->subkeys->keyid;              s = key->subkeys->keyid;
203              if (s)                  if (s)
204                  keyid = m_strdup (s+8);                  keyid = m_strdup (s+8);
205              break;              break;
206          }          }
207      }      }
# Line 234  default_key_from_cache (int *ret_no_usea Line 216  default_key_from_cache (int *ret_no_usea
216     Return value: 0 on success. */     Return value: 0 on success. */
217  int  int
218  gnupg_load_config (void)  gnupg_load_config (void)
219  {  {    
220      int rc;      config_file_t opt;
221      gpg_optfile_t opt;      char *conf;
222      gpg_option_t o;      int rc = 0;
223      char *conf = get_gnupg_cfgfile ();      
224        conf = get_gnupg_cfgfile ();
225      if (!conf)      if (!conf)
226          return -1;          return -1;
227      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
228          free_if_alloc (conf);          free_if_alloc (conf);
229          return -1;          return -1;
230      }      }
     o = find_option (opt, "ask-cert-level");  
     if (o)  
         reg_prefs.gpg.ask_cert_level = 1;  
     release_gpg_options (opt);  
231      free_if_alloc (conf);      free_if_alloc (conf);
232      return 0;      if (conf_find_option (opt, "ask-cert-level"))
233            reg_prefs.gpg.ask_cert_level = 1;
234        if (conf_find_option (opt, "ask-cert-expire"))
235            reg_prefs.gpg.ask_cert_expire = 1;
236        /* The 'textmode' option for GPG is useful for text files
237           but it breaks the output of any binary data. Thus we return
238           a warning here to inform the user that binary output is broken. */
239        if (conf_find_option (opt, "textmode"))
240            rc = -2;
241        release_config (opt);
242    
243        return rc;
244  }  }
245    
246    
247    /* handle the case the user added a '!' to force a subkey. */
248    static char*
249    extract_keyid (const char *val)
250    {    
251        size_t len = strlen (val);
252    
253        if (len > 1 && val[len-1] == '!')
254            return substr (val, 0, len-1);
255        return m_strdup (val);
256    }
257    
258    
259    /* Return the default key.
260       This can be either a substring or a key ID. */
261  char*  char*
262  get_gnupg_default_key (void)  get_gnupg_default_key (void)
263  {      {    
264      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
265      gpg_option_t e;      conf_option_t e;
266      char * keyid = NULL, * optfile = NULL;      char *keyid = NULL, *optfile = NULL;
267      int no_usable=0, rc = 0;      int no_usable=0;
268    
269      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
270      if (!optfile)      if (!optfile)
271          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
272      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
273          free_if_alloc (optfile);          free_if_alloc (optfile);
274          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
275      }      }
276      e = find_option( opt, "default-key" );      /* First we search for config entries which specify a default key. */
277      if ( e )      e = conf_find_option (opt, "default-key");
278          keyid = m_strdup( e->val );      if (!e)
279      if( !e ) {          e = conf_find_option (opt, "local-user");
280          e = find_option( opt, "local-user" );      if (e)
281          if( e )          keyid = extract_keyid (e->val);
282              keyid = m_strdup( e->val );  
     }  
     if( !e ) {  
         e = find_option( opt, "encrypt-to" );  
         if( e )  
             keyid = m_strdup( e->val );  
     }  
283      free_if_alloc (optfile);      free_if_alloc (optfile);
284      release_gpg_options (opt);      release_config (opt);
285    
286        /* If no entry in the config has been found, we get a key
287           from the key cache. */
288      if (!keyid)      if (!keyid)
289          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
290      return keyid;      return keyid;
291  } /* get_gnupg_default_key */  }
   
292    
 char* get_reg_entry_gpg4win (const char *path);  
293    
294  /* Check if GPG4WIN is available and if so, use the  /* Check if GPG4WIN is available and if so, use the
295     install path to figure out where the gpg.exe is. */     install path to figure out where the gpg.exe is. */
# Line 326  check_gnupg_prog (void) Line 322  check_gnupg_prog (void)
322    
323    
324  static int  static int
325  parse_version_nr (const char * buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
326  {  {  
327      char tmp[8];      char *p;
328      int i;      char *tmp = m_strdup(buf);
329            
330      i=0;      int pos = 0;
331      while (buf && *buf != '.' && i < 8)      while ((p = strsep(&tmp, ".")) != NULL) {
332          tmp[i++] = *buf++;          switch (++pos) {
333      tmp[i] = 0; buf++;          case 1: *major = atoi (p); break;
334      *major = atol( tmp );          case 2: *minor = atoi (p); break;
335      i=0;          case 3: *patch = atoi (p); break;
336      while (buf && *buf != '.' && i < 8)          }
337          tmp[i++] = *buf++;      }
338      tmp[i] = 0; buf++;      delete[] tmp;  
339      *minor = atol (tmp);      if (pos != 3)
340      i=0;          return -1;  
     while (buf && isdigit (*buf) && i < 8)  
         tmp[i++] = *buf++;  
     tmp[i] = 0;  
     *patch = atol (tmp);  
341      return 0;      return 0;
342  }  }
343    
# Line 354  parse_version_nr (const char * buf, int Line 346  parse_version_nr (const char * buf, int
346     version given in @r_major.@r_minor.@r_patch. On success these     version given in @r_major.@r_minor.@r_patch. On success these
347     variables contain the GPG version which is installed. */     variables contain the GPG version which is installed. */
348  int  int
349  check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)  check_gnupg_engine (const char *need_gpg_ver,
350                        int *r_major, int *r_minor, int *r_patch)
351  {  {
     gpgme_ctx_t ctx;  
352      gpgme_engine_info_t inf;      gpgme_engine_info_t inf;
353      char *eng = NULL;      char *eng = NULL;
354      int major=0, minor=0, patch=0;      int major=0, minor=0, patch=0;
355        int need_major = 0, need_minor = 0, need_patch = 0;
356      int rc = 1;      int rc = 1;
357            
358      gpgme_new (&ctx);      /* Convert the needed GPG version to the integer format. */
359      inf = gpgme_ctx_get_engine_info (ctx);      if (parse_version_nr (need_gpg_ver,
360      if (!inf) {                            &need_major, &need_minor, &need_patch))
361          gpgme_release (ctx);          return 1;
362          return -1;      
363      }      if (gpgme_get_engine_info (&inf))
364         return -1;
365    
366      /* 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. */
367      if (gpg_get_version (&eng))      if (gpg_get_version (&eng))
368          return -1;       return -1;
369      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
370          idea_available = 1;          idea_available = 1;
371      free (eng);      safe_free (eng);
372      rc = parse_version_nr (inf->version, &major, &minor, &patch);    
373      if (rc) {      if (parse_version_nr (inf->version, &major, &minor, &patch))
374          gpgme_release (ctx);          return 1;
         return rc;  
     }  
375    
376      if (major > *r_major)      if (major > need_major)
377          rc = 0;          rc = 0;
378      else if (major == *r_major && minor > *r_minor)                else if (major == need_major && minor > need_minor)      
379          rc = 0;          rc = 0;
380      else if (major == *r_major && minor == *r_minor &&      else if (major == need_major && minor == need_minor &&
381               patch >= *r_patch)               patch >= need_patch)
382          rc = 0;          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 396  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;          config_file_t opt;    
398      gpg_option_t e;      conf_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 = get_gnupg_keyring (_pub, 0);
427        if (name && file_exist_check (name) != 0) {
428            FILE *fp = fopen (name, "ab");
429            if (fp != NULL)
430                fclose (fp);
431        }
432        free_if_alloc (name);
433    }
434    
435    
436    /* Check if both keyrings are located in the gnupg home directory. */
437  int  int
438  gnupg_access_files (void)  gnupg_access_files (void)
439  {  {
# Line 435  gnupg_access_files (void) Line 442  gnupg_access_files (void)
442      int secrings = 0, pubrings = 0;      int secrings = 0, pubrings = 0;
443      char *optfile;      char *optfile;
444    
445        create_empty_keyring (1);
446      if (gnupg_access_keyring (1))      if (gnupg_access_keyring (1))
447          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
448      else      else
449          pubring_ok = 1;          pubring_ok = 1;
450    
451        create_empty_keyring (0);
452      if (gnupg_access_keyring (0))      if (gnupg_access_keyring (0))
453          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
454      else      else
# Line 451  gnupg_access_files (void) Line 460  gnupg_access_files (void)
460              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
461          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
462          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
463              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
464              if (!rc && secrings && pubrings) {              if (!rc && secrings > 0 && pubrings > 0) {
465                  free_if_alloc (optfile);                  free_if_alloc (optfile);
466                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
467              }              }
# Line 468  gnupg_access_files (void) Line 477  gnupg_access_files (void)
477          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
478      }      }
479      return rc;      return rc;
480  } /* 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 );  
481    
 fail:  
     free_if_alloc( s );  
     free_if_alloc( optfile );  
     return 0;  
 } /* create_gpg_options */  
482    
483    
484  /*  /* Return the contents of the options file as a char buf. */
485   * Return the contents of the options file as a char buf.  char*
  */  
 char *  
486  get_gnupg_config (void)  get_gnupg_config (void)
487  {  {
488      FILE * fp;      FILE *fp;
489      char * p = NULL, * optfile = NULL;      char *p = NULL, *optfile;
490      int fsize, rc = 0;      int fsize;
491                    
492      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
493      if( optfile == NULL )      if (!optfile)
494          return NULL;          return NULL;
495      fsize = get_file_size( optfile );      fsize = get_file_size (optfile);
496      if( !fsize ) {      if (fsize < 1 || fsize > 100000)
497          rc = create_gpg_options( );          goto leave; /* too large or does not exist */
498          if ( rc )      
499              return NULL;      fp = fopen (optfile, "rb");
500          fsize = get_file_size( optfile );      if (!fp)
501      }          goto leave;
     if( fsize > 100000 )  
         goto leave; /* too large */  
502      p = new char[fsize+1];      p = new char[fsize+1];
503      if( p == NULL )      if (!p)
504          BUG( NULL );          BUG (NULL);
505      fp = fopen( optfile, "rb" );      fread (p, 1, fsize, fp);
506      if( fp == NULL ) {      fclose (fp);
         free_if_alloc( p );  
         return NULL;  
     }  
     fread( p, 1, fsize, fp );  
     fclose( fp );  
507      p[fsize] = '\0';      p[fsize] = '\0';
508      free_if_alloc( optfile );      
   
509  leave:  leave:
510        free_if_alloc (optfile);
511      return p;      return p;
512  } /* get_gnupg_config */  }
513    
514    
515    /* Set the default key in the gpg.conf.
516       If @key is NULL, the entry will be deleted. */
517  int  int
518  set_gnupg_default_key (const char * key)  set_gnupg_default_key (const char *key)
519  {  {
520      gpg_optfile_t opt;      config_file_t opt;
521      gpg_option_t e;      conf_option_t e;
522      char *optfile = NULL;      char *optfile = NULL;
523      int rc = 0;      int rc = 0;
524    
525      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
526      if (!optfile)      if (!optfile)
527          return -1;          return WPTERR_FILE_OPEN;
528      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
529      if( rc ) {      if (rc) {
530          free_if_alloc (optfile);          free_if_alloc (optfile);
531          return -1;          return WPTERR_GENERAL;
532      }      }
533      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
534      if (e) {      if (e && !key)
535            e->used = 0;
536        else if (e) {
537          free_if_alloc (e->val);          free_if_alloc (e->val);
538          e->val = m_strdup (key);          e->val = m_strdup (key);
539          e->used = 1;          e->used = 1;
540      }      }
541      else      else if (key)
542          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
543      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
544    
545      free_if_alloc (optfile);      free_if_alloc (optfile);
546      release_gpg_options (opt);      release_config (opt);
   
547      return rc;      return rc;
548  } /* set_gnupg_default_key */  }
549    
550    
551  /*  /* Set the contents of the options file. */
  * Set the contents of the options file.  
  */  
552  int  int
553  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
554  {  {
555      FILE *fp;        FILE *fp;  
556      char *optfile = NULL;      char *optfile;
557    
558      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
559      if( optfile == NULL )      if (!optfile)
560          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
561    
562      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
563      if( fp == NULL ) {      if (!fp) {
564          free_if_alloc( optfile );          free_if_alloc (optfile);
565          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
566      }      }
567      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
568      fclose( fp );      fclose (fp);
569      free_if_alloc( optfile );      free_if_alloc (optfile);
570      return 0;      return 0;
571  } /* set_gnupg_options */  }
572    
573  /*  
574   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
575   */     Return value: 0 on success. */
576  static int  static int
577  check_line( const char *buf )  check_arg_file_exist (const char *buf)
578    {
579        const char *s = "load-extension ";
580    
581        /* XXX: this is a bit of a kludge because we just
582                detect errors for 'load-extension'. */
583        if (!strncmp (buf, s, strlen (s)))
584            buf += strlen (s);
585        else
586            return 0;
587        return file_exist_check (buf);
588    }
589    
590    
591    /* Check if the line contains a valid GPG argument. */
592    static int
593    check_line (const char *buf)
594  {  {
595      int j, len;      int j, len;
596      int rc = 0;      int rc = 0;
597    
598      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
599          return 1;          return 1;
600      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
601      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
602          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
603          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
604      }      }
   
605      return rc;      return rc;
606  } /* check_line */  }
607    
608    
609  int  int
610  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
611  {  {
612      char line[1024];      char line[1024];
613      int nbytes = 0;      int nbytes = 0, lineno=0;
614      unsigned j;      unsigned j;
615                    
616      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
617          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
618          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
619              line[nbytes] = '\0';              line[nbytes] = '\0';
620              if( !check_line( line ) ) {              lineno++;
621                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
622                    if (showerr)
623                        log_box ("GPG Config File", MB_ERR,
624                                 "gpg.conf:%d: invalid keyword '%s'",
625                                 lineno, line);
626                  return 1;                        return 1;      
627              }              }
628                if (check_arg_file_exist (line))
629                    return WPTERR_FILE_EXIST;
630              nbytes = 0;              nbytes = 0;
631          }                }
632      }      }
   
633      return 0;      return 0;
634  } /* check_gnupg_options */  }
635    
636    
637  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
638  static int  static int
639  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
640  {  {
641      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
642    
643      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
644      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
645      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);  
646          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
647      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
648      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
649      return 0;      return 0;
650  }  }
651    
652    
653  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
654  static void  static void
655  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
656  {                {              
657      ctx->modified = 0;      ctx->modified = 0;
658    
659      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
660          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
661          ctx->modified = 1;          ctx->modified = 1;
662        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
663      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
664          ctx->modified = 0;          ctx->modified = 0;
665    
# Line 682  check_last_gnupg_access (gpg_watcher_s * Line 668  check_last_gnupg_access (gpg_watcher_s *
668  }  }
669    
670    
671  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
672  void  void
673  init_gnupg_table (void)  init_gnupg_table (void)
674  {        {      
675      char *p;      char *path;
676      int j;      int j;
677    
678        path = get_gnupg_path ();
679      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
680          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
681          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
682          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
683          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
684          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
685      }      }
686        free_if_alloc (path);
687  }  }
688    
689    
690    /* Release the GPG monitor table. */
691  void  void
692  free_gnupg_table (void)  free_gnupg_table (void)
693  {  {
694      int j;      for (int j=0; j < gpg_table_count; j++) {
   
     for (j=0; j < gpg_table_count; j++)  
695          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
696            free_if_alloc (gpg_table[j].fpath_object);
697        }
698  }  }
699    
700    
701  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
702  int  int
703  keyring_check_last_access (void)  keyring_check_last_access (void)
704  {        {
705      int rc, j;      int nfiles;
706    
707      rc = 0;      nfiles = 0;
708      for (j = 0; j < gpg_table_count; j++) {      for (int pos = 0; pos < gpg_table_count; pos++) {
709          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
710          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
711          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
712              rc++;                    nfiles++;
713      }      }
714    
715      return rc;      return nfiles;
716  }  }
717    
718    
# Line 747  gnupg_check_file_ext (const char *fname, Line 735  gnupg_check_file_ext (const char *fname,
735              *r_type = PGP_SIG;              *r_type = PGP_SIG;
736          return "SIGNED";          return "SIGNED";
737      }      }
738      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
739                  !stricmp (file_ext, ".pgp")) {
740          if (r_type)          if (r_type)
741              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
742          return "ENCRYPTED";          return "ENCRYPTED";
# Line 756  gnupg_check_file_ext (const char *fname, Line 745  gnupg_check_file_ext (const char *fname,
745  }  }
746    
747    
748  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 */  
749  static int  static int
750  my_access (const char * fname)  check_file_access (const char *fname, int mode)
751  {  {
752      HANDLE hd;      HANDLE hd;
753      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,  
754        if (!mode)
755            mode = FILE_SHARE_WRITE;
756        hd = CreateFile (fname, GENERIC_WRITE, mode,
757                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
758      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
759          return -1;          return -1;
# Line 793  my_access (const char * fname) Line 761  my_access (const char * fname)
761      return 0;      return 0;
762  }  }
763    
764        
765    /* Check the device where the file @fname is stored on, is either
766       write-protected or if the file is already opened by another process
767       exclusively. And as a result, we cannot use the file for output. */
768    int
769    gpg_check_file_permissions (const char *fname, int mode)
770    {
771        int api_mode;
772        
773        switch (mode) {
774        case 0: api_mode = FILE_SHARE_READ; break;
775        case 1: api_mode = FILE_SHARE_WRITE; break;
776        case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
777        default: api_mode = FILE_SHARE_READ; break;
778        }
779    
780        return check_file_access (fname, api_mode);
781    }
782    
783    
784  /* Check the file permissions of the public keyring.  /* Check the file permissions of the public keyring.
785     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 801  my_access (const char * fname) Line 788  my_access (const char * fname)
788  int  int
789  gpg_check_permissions (int showmsg)  gpg_check_permissions (int showmsg)
790  {  {
791      char * p, * name = NULL;      char *p = NULL;
792        char *name = NULL;
793      int failed = 0, ans=0, attrs=0;      int failed = 0, ans=0, attrs=0;
794    
795      p = get_gnupg_path ();      p = get_gnupg_path ();
796      check_keyring (&p);      if (p && check_keyring (&p)) {
     if (p) {  
797          name = make_filename (p, "pubring", "gpg");          name = make_filename (p, "pubring", "gpg");
         free_if_alloc (p);  
798          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
799              ans = msg_box (NULL,              ans = msg_box (NULL,
800                             _("The selected keyring has the read-only file\n"                             _("The selected keyring has the read-only file\n"
# Line 828  gpg_check_permissions (int showmsg) Line 814  gpg_check_permissions (int showmsg)
814                  failed = 1;                  failed = 1;
815              }              }
816          }          }
817          if (my_access (name)) {          if (gpg_check_file_permissions (name, 1)) {
818              if (showmsg)              if (showmsg)
819                  msg_box (NULL,                  msg_box (NULL,
820                  _("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 840  gpg_check_permissions (int showmsg) Line 826  gpg_check_permissions (int showmsg)
826              failed = 2;              failed = 2;
827          }          }
828      }      }
829        free_if_alloc (p);
830      free_if_alloc (name);      free_if_alloc (name);
831      return failed;      return failed;
832  }  }
833    
834    
835  /* Check the GPG home dir. If all methods failed, try to  /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
836     create the default folder. */     then check for $APPDATA\gnupg. Create the dir if it does not exists. */
837  static int  int
838  check_homedir (void)  gnupg_check_homedir (void)
839  {        {      
840      char *homedir = NULL;      char *homedir;
841      int yes = 0, set_reg=0;      int val;
842      int rc = 0;      int rc = 0;
843    
844      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
     if (!homedir) {  
         set_reg = 1;  
         homedir = multi_gnupg_path (0);  
     }  
845      if (!homedir)      if (!homedir)
846          homedir = m_strdup ("c:\\gnupg");          homedir = multi_gnupg_path (0);
847      if (homedir) {      if (homedir) {
848          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
849              yes = log_box (_("Preferences"), MB_YESNO,              val = log_box (_("Preferences"), MB_YESNO,
850                             _("%s does not exit.\n"                             _("%s does not exit.\n"
851                               "Do you want to create this directory?"), homedir);                               "Do you want to create this directory?"), homedir);
852              if (yes == IDYES) {              if (val == IDYES) {
853                  if (!CreateDirectory (homedir, NULL))                  if (!CreateDirectory (homedir, NULL))
854                      rc = WPTERR_DIR_CREAT;                      rc = WPTERR_DIR_CREAT;
855              }              }
856              else              else
857                  rc = WPTERR_DIR_OPEN;                  rc = WPTERR_DIR_OPEN;
858          }          }
         if (set_reg)  
             set_reg_entry_gpg (GPG_REG_HOME, homedir);  
859          free_if_alloc (homedir);          free_if_alloc (homedir);
860      }      }
861      return rc;      return rc;
# Line 882  check_homedir (void) Line 863  check_homedir (void)
863    
864    
865  int  int
866  gnupg_check_homedir (void)  gnupg_import_keypair (void)
867  {        {
868      char *homedir = NULL;      const char *file;
869      char *prog = NULL;      gpgme_error_t err;
870      int rc = 0;      GPGME gpgme;
871            HWND hwnd = GetDesktopWindow ();
872      rc = check_homedir ();  
873      if (rc)      file = get_fileopen_dlg (hwnd, _("Please choose your Key Pair"),
874          return rc;                               "GPG Key File (*.gpg)\0*.gpg\0"
875      if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&                               "GPG Armored Key File (*.asc)\0*.asc\0\0",
876          !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {                               NULL);
877          prog = make_filename (homedir, "gpg", "exe");      if (file == NULL)
878          if (file_exist_check (prog) == 0) {          return WPTERR_FILE_OPEN;
879              rc = set_reg_entry_gpg (GPG_REG_EXE, prog);      err = gpgme.importFromFile (file);
880              if (rc)      if (err)
881                  goto fail;          msg_box (hwnd, gpgme_strerror (err), _("WinPT Error"), MB_ERR);
882          }      else
883          free_if_alloc (homedir);          msg_box (hwnd, _("Key pair successfully imported."), "WinPT", MB_OK);
884          free_if_alloc (prog);      return 0;
885          return rc;  }
     }  
     if ((prog = get_reg_entry_gpg (GPG_REG_EXE))  
         && file_exist_check (prog)) {  
         free_if_alloc (prog);  
         homedir = get_reg_entry_gpg (GPG_REG_HOME);  
         if (!homedir) {  
             rc = WPTERR_GENERAL;  
             goto fail;  
         }  
         prog = make_filename (homedir, "gpg", "exe");  
         if (file_exist_check (prog) == 0) {  
             rc = set_reg_entry_gpg (GPG_REG_EXE, prog);  
             if (rc)  
                 goto fail;  
             free_if_alloc (prog);  
             return rc;  
         }  
     }  
       
     /* 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);  
     return rc;  
 } /* gnupg_check_homedir */  
   
886    
887  int  int
888  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
889  {  {
890      const char * pring, * sring;      const char *pring, *sring;
891      char * file = NULL, * path = NULL;      char *file = NULL, *path;
892      int id = 0, rc = 0;      int id, rc = 0;
893      HWND hwnd;      HWND hwnd;
894            
895      path = get_gnupg_path ();      path = get_gnupg_path ();
# Line 946  gnupg_copy_keyrings (void) Line 897  gnupg_copy_keyrings (void)
897          return WPTERR_GENERAL;          return WPTERR_GENERAL;
898      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
899    
900      pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
901                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
902      if (!pring) {      if (!pring) {
903          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("No keyring was chosen. Exit."),
904                     _("WinPT Error"), MB_ERR);
905          free_if_alloc (path);          free_if_alloc (path);
906          return WPTERR_GENERAL;          return WPTERR_GENERAL;
907      }      }
908      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
909      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
910          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old public keyring?"),
911                          "WinPT", MB_INFO|MB_YESNO);
912          if (id == IDNO)          if (id == IDNO)
913              goto fail;              goto fail;
914      }      }
915      if (!CopyFile (pring, file, FALSE)) {      if (!CopyFile (pring, file, FALSE)) {
916          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("Could not copy public keyring."),
917                     _("WinPT Error"), MB_ERR);
918          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
919          goto fail;          goto fail;
920      }      }
921      free_if_alloc (file);      free_if_alloc (file);
922    
923      sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),      sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
924                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
925      if (!sring) {      if (!sring) {
926          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          msg_box (NULL, _("No keyring was chosen. Exit."),
927                     _("WinPT Error"), MB_ERR);
928          return WPTERR_GENERAL;          return WPTERR_GENERAL;
929      }      }
930      file = make_filename (path, "secring", "gpg");      file = make_filename (path, "secring", "gpg");
931      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
932          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old secret keyring?"),
933          if( id == IDNO )                        "WinPT", MB_INFO|MB_YESNO);
934            if (id == IDNO)
935              goto fail;              goto fail;
936      }      }
937      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
938          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy secret keyring."), _("WinPT Error"), MB_ERR);
939          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
940      }      }
941    
# Line 987  fail: Line 943  fail:
943      free_if_alloc (file);      free_if_alloc (file);
944      free_if_alloc (path);      free_if_alloc (path);
945      return rc;      return rc;
946  } /* gnupg_import_keyrings */  }
947    
948    
949    /* Backup the gpg.conf file. */
950  void  void
951  gnupg_backup_options (void)  gnupg_backup_options (void)
952  {  {
953      char *cfgfile = NULL;      char bak[MAX_PATH+32];
     char bak[512];  
954    
955      cfgfile = get_gnupg_cfgfile ();      char *cfgfile = get_gnupg_cfgfile ();
956      if (cfgfile == NULL)      if (!cfgfile)
957          return;          return;
958      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
959      CopyFile (cfgfile, bak, FALSE);      CopyFile (cfgfile, bak, FALSE);
960      free_if_alloc (cfgfile);      free_if_alloc (cfgfile);
961  } /* gnupg_backup_options */  }
   
962    
963    
964  static int  static int
965  backup_one_file (const char *srcpath, const char *srcn,  backup_one_file (const char *srcpath, const char *srcn,
966                   const char *dstpath, const char *dstn)                   const char *dstpath, const char *dstn)
967  {  {
968      char * src, * dst;      char *src, *dst;
969      BOOL rc;      BOOL rc;
970    
971      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
972      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
973      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
974      free_if_alloc (src);      free_if_alloc (src);
975      free_if_alloc (dst);      free_if_alloc (dst);
976      if (!rc)      if (!rc) {
     {  
977          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
978          return WPTERR_GENERAL;          return WPTERR_GENERAL;
979      }      }
980      return 0;      return 0;
981  } /* backup_one_file */  }
982    
983    
984    /* Figure out first public keyring which is not empty.
985       Return value: 1 on success. */
986  static int  static int
987  check_keyring (char ** r_path)  check_keyring (char **r_path)
988  {  {
989      char * p;      char *p;
990      char * opt, * name;      char *opt;
991        char *name;
992    
993      if (!*r_path)      if (!*r_path)
994          return 0;          return 0;
995      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
996      if (!p || get_file_size (p) > 0)      if (get_file_size (p) <= 0)
997          return 0;          return 0;
998    
999      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
1000      if (!opt)      if (!opt)
1001          BUG (0);          BUG (0);
1002      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
1003      free_if_alloc (opt);      free_if_alloc (opt);
1004      free_if_alloc (p);      free_if_alloc (p);
1005      if (!name)      if (!name)
1006          return 0;          return 0;
1007      p = strrchr (name, '\\');      p = strrchr (name, '\\');
1008      if (!p)      if (!p) {
     {  
1009          free_if_alloc (name);          free_if_alloc (name);
1010          return 0;                return 0;      
1011      }      }
# Line 1066  check_keyring (char ** r_path) Line 1018  check_keyring (char ** r_path)
1018  }  }
1019    
1020    
1021    /* Return a temp name based on the day of the week. */
1022  static char*  static char*
1023  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1024  {  {
1025      struct tm *tm;      struct tm *tm;
1026        const char *fmt;
1027      char *p;      char *p;
1028        time_t t;
1029    
1030      time_t t = time (NULL);      t = time (NULL);
1031      tm = localtime (&t);      tm = localtime (&t);
1032      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1033        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1034      if (!p)      if (!p)
1035          BUG (0);          BUG (0);
1036      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1037      return p;      return p;
1038  }  }
1039    
1040    
1041  /* Make backups of all keyrings. The public key ring is  /* Make backups of all keyrings. The public key ring is rotated like
1042     rotated like this pubring-%d.gpg. */     this pubring-%d.gpg.
1043       If @auto_backup is false, no action is performed.
1044       @include_secr indicated if the backup includes the secret keyring. */
1045  void  void
1046  gnupg_backup_keyrings (void)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1047  {  {
1048      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1049      char *name=NULL;      char *name;
1050      int rc, bakmode=0;      int rc;
1051    
1052      if (!reg_prefs.auto_backup)      if (!auto_backup)
1053          return;          return;
     bakmode = reg_prefs.backup.mode;  
1054      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1055      check_keyring (&srcpath);      check_keyring (&srcpath);
1056      if (bakmode == 1) {      if (backup_mode == 1) {
1057          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1058               and destination folder will be the same. */
1059            dstpath = get_gnupg_path ();
1060          check_keyring (&dstpath);          check_keyring (&dstpath);
1061      }      }
1062      else if (bakmode == 2) {      else if (backup_mode == 2) {
1063          char *tmpfile;          char *tmpfile;
1064          FILE *fp;          FILE *fp;
1065    
1066          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1067          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1068          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1069          if (!fp)          if (!fp)
1070              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1071                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1072                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1073          else {          else {
1074              rc = 0;              rc = 0;
1075              fclose (fp);              fclose (fp);
1076              remove (tmpfile);              DeleteFile (tmpfile);
1077          }          }
1078          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1079          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1080                free_if_alloc (dstpath);
1081                free_if_alloc (srcpath);
1082              return;              return;
1083            }
1084      }      }
1085      else {      else {
1086          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1087            free_if_alloc (srcpath);
1088          return;          return;
1089      }      }
1090      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
1091      rc = backup_one_file (srcpath, "pubring", dstpath, name);      rc = backup_one_file (srcpath, "pubring", dstpath, name);
1092      if (!rc)      if (!rc && include_secr)
1093          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1094      free_if_alloc (name);      free_if_alloc (name);
1095      free_if_alloc (srcpath);      free_if_alloc (srcpath);
# Line 1136  gnupg_backup_keyrings (void) Line 1097  gnupg_backup_keyrings (void)
1097  }  }
1098    
1099    
 /* 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);  
 }  
   
   
   
1100  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1101     Return value: 0 for success. */     Return value: 0 for success. */
1102  int  int

Legend:
Removed from v.117  
changed lines
  Added in v.407

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26