/[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 222 by twoaday, Thu Jun 1 08:30:46 2006 UTC revision 328 by twoaday, Fri Sep 25 16:07:38 2009 UTC
# Line 1  Line 1 
1  /* wptGPG.cpp - GnuPG configuration  /* wptGPG.cpp - GnuPG configuration
2   *      Copyright (C) 2001-2006 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 31  Line 27 
27    
28  #include "wptGPG.h"  #include "wptGPG.h"
29  #include "wptGpgCmds.h"  #include "wptGpgCmds.h"
 #include "wptGPGOptSkel.h"  
30  #include "wptTypes.h"  #include "wptTypes.h"
31  #include "wptNLS.h"  #include "wptNLS.h"
32  #include "wptRegistry.h"  #include "wptRegistry.h"
# Line 43  Line 38 
38  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
39  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
40    
41  struct gpg_watcher_s {  /* Context to monitor GPG file changes. */
42      FILETIME    last_access;  struct gpg_monitor_s {
43        FILETIME    last_access;    /* last write access. */
44      FILETIME    access;      FILETIME    access;
45      char        *object;      char        *object;        /* name of the object. */
46      int         modified;      char        *fpath_object;  /* full path to the object. */
47        int         modified;       /* 1 = modified. */
48  };  };
49    typedef struct gpg_monitor_s *gpg_monitor_t;
50    
51    static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
52  /* 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];  
53  static int gpg_table_count = DIM (gpg_table);  static int gpg_table_count = DIM (gpg_table);
54    
55  int idea_available = 0;  int idea_available = 0; /* if the IDEA extension is available. */
56    
57    
58  static int check_keyring (char ** r_path);  static int check_keyring (char ** r_path);
59    
# Line 65  static int check_keyring (char ** r_path Line 62  static int check_keyring (char ** r_path
62  char*  char*
63  multi_gnupg_path (int strict)  multi_gnupg_path (int strict)
64  {  {
65      static char buf[256+64];      static char buf[MAX_PATH+64];
66      BOOL ec;      BOOL ec;
67    
68      /* 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 89  get_gnupg_path (void)
89      char *path;      char *path;
90    
91      path = get_reg_entry_gpg (GPG_REG_HOME);      path = get_reg_entry_gpg (GPG_REG_HOME);
92      if (path) {      if (path && dir_exist_check (path) == 0)
93          if (dir_exist_check (path) == 0)          return path;
94              return path;      free_if_alloc (path);
95          free_if_alloc (path);      return multi_gnupg_path (1);
     }  
     path = multi_gnupg_path (1);  
     return path;  
96  }  }
97    
98    
# Line 106  get_gnupg_path (void) Line 100  get_gnupg_path (void)
100     A value of NULL indicates an error. */     A value of NULL indicates an error. */
101  char*  char*
102  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
103  {      {
104      char *p = NULL;      char *optfile;
105      char *optfile = NULL;      char *path;
     char *path = NULL;  
     size_t nlen = 0;  
106    
107      path = get_gnupg_path ();      path = get_gnupg_path ();
108      if (!path)      if (!path)
109          return NULL;          return NULL;
110      nlen = strlen (path) + 64;      optfile = make_filename (path, GPG_CONF, NULL);
     optfile = new char[nlen + 1];  
     if (!optfile)  
         BUG (NULL);      
     _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
   
111      free_if_alloc (path);      free_if_alloc (path);
112      free_if_alloc (p);  
113      return optfile;      return optfile;
114  }  }
115    
116    
117    static char*
118    get_keyring_from_conf (const char *fname, int pub)
119    {
120        config_file_t opt;
121        conf_option_t e;
122        char *kring = NULL;
123        int rc;
124    
125        rc = parse_config (fname, &opt);
126        if (rc)
127            return NULL;
128        if (pub)
129            e = conf_find_option (opt, "keyring");
130        else
131            e = conf_find_option (opt, "secret-keyring");
132        if (e != NULL)
133            kring = m_strdup (e->val);
134        release_config (opt);
135    
136        return kring;
137    }
138    
139    
140  /* 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
141     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
142  char*  char*
143  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
144  {      {    
145      char *optfile = NULL;      char *optfile;
146      char *path = NULL;      char *path;
147      char *keyring = NULL;      char *keyring;
148    
149      path = get_gnupg_path ();      path = get_gnupg_path ();
150      if (!path)      if (!path)
# Line 148  get_gnupg_keyring (int pub, int strict) Line 158  get_gnupg_keyring (int pub, int strict)
158          free_if_alloc (path);          free_if_alloc (path);
159          return keyring;          return keyring;
160      }      }
161      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      if (file_exist_check (keyring) ||
162            (pub && get_file_size (keyring) == 0)) {
163          free_if_alloc (keyring);          free_if_alloc (keyring);
164          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
165          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
166            free_if_alloc (optfile);
167      }      }
168      free_if_alloc (path);      free_if_alloc (path);
169      free_if_alloc (optfile);      
170      return keyring;      return keyring;
171  }  }
172    
# Line 162  get_gnupg_keyring (int pub, int strict) Line 174  get_gnupg_keyring (int pub, int strict)
174  /* 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
175     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
176     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
177  char*  char*
178  get_gnupg_prog (void)  get_gnupg_prog (void)
179  {      {    
180      char *p;      char *path;
181      char *pgm = NULL;      char *pgm;
182    
183      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
184      if (!p) {      if (pgm)
185          char *path = get_gnupg_path ();          return pgm;
186          if (!path)      path = get_gnupg_path ();
187              return NULL;      if (!path)
188          pgm = make_filename (path, "gpg", "exe");          return NULL;    
189          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
190      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
191      return pgm;      return pgm;
192  }  }
193    
# Line 189  get_gnupg_prog (void) Line 195  get_gnupg_prog (void)
195  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
196     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
197     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
198  static char *  static char*
199  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
200  {      {    
201      gpgme_key_t key, pk;      gpgme_key_t key, pk;
# Line 198  default_key_from_cache (int *ret_no_usea Line 204  default_key_from_cache (int *ret_no_usea
204      char *keyid = NULL;      char *keyid = NULL;
205    
206      sec = keycache_get_ctx (0);      sec = keycache_get_ctx (0);
     if (!sec)  
         BUG (0);  
207      pub = keycache_get_ctx (1);      pub = keycache_get_ctx (1);
208      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
209      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
# Line 211  default_key_from_cache (int *ret_no_usea Line 215  default_key_from_cache (int *ret_no_usea
215          }          }
216      }      }
217      if (!keyid)      if (!keyid)
218          *ret_no_useable = 1;              *ret_no_useable = 1;
219      return keyid;      return keyid;
220  }  }
221    
# Line 221  default_key_from_cache (int *ret_no_usea Line 225  default_key_from_cache (int *ret_no_usea
225     Return value: 0 on success. */     Return value: 0 on success. */
226  int  int
227  gnupg_load_config (void)  gnupg_load_config (void)
228  {  {    
229      int rc;      config_file_t opt;
     gpg_optfile_t opt;  
     gpg_option_t o;  
230      char *conf;      char *conf;
231        int rc = 0;
232            
233      conf = get_gnupg_cfgfile ();      conf = get_gnupg_cfgfile ();
234      if (!conf)      if (!conf)
235          return -1;          return -1;
236      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
237          free_if_alloc (conf);          free_if_alloc (conf);
238          return -1;          return -1;
239      }      }
240      o = find_option (opt, "ask-cert-level");      free_if_alloc (conf);
241      if (o)      if (conf_find_option (opt, "ask-cert-level"))
242          reg_prefs.gpg.ask_cert_level = 1;          reg_prefs.gpg.ask_cert_level = 1;
243      o = find_option (opt, "ask-cert-expire");      if (conf_find_option (opt, "ask-cert-expire"))
     if (o)  
244          reg_prefs.gpg.ask_cert_expire = 1;          reg_prefs.gpg.ask_cert_expire = 1;
245      release_gpg_options (opt);      /* The 'textmode' option for GPG is useful for text files
246      free_if_alloc (conf);         but it breaks the output of any binary data. Thus we return
247      return 0;         a warning here to inform the user that binary output is broken. */
248        if (conf_find_option (opt, "textmode"))
249            rc = -2;
250        release_config (opt);
251    
252        return rc;
253  }  }
254    
255    
# Line 253  extract_keyid (const char *val) Line 259  extract_keyid (const char *val)
259  {      {    
260      size_t len = strlen (val);      size_t len = strlen (val);
261    
262      if (len > 1 && val[len-1] == '!') {      if (len > 1 && val[len-1] == '!')
263          char *p = new char[len+1];          return substr (val, 0, len-1);
         if (!p)  
             BUG (0);  
         memset (p, 0, len+1);  
         memcpy (p, val, len-1);  
         return p;  
     }  
264      return m_strdup (val);      return m_strdup (val);
265  }  }
266    
267    
268    /* Return the default key.
269       This can be either a substring or a key ID. */
270  char*  char*
271  get_gnupg_default_key (void)  get_gnupg_default_key (void)
272  {      {    
273      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
274      gpg_option_t e;      conf_option_t e;
275      char *keyid = NULL, *optfile = NULL;      char *keyid = NULL, *optfile = NULL;
276      int no_usable=0, rc = 0;      int no_usable=0;
277    
278      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
279      if (!optfile)      if (!optfile)
280          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
281      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
282          free_if_alloc (optfile);          free_if_alloc (optfile);
283          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
284      }      }
285      e = find_option (opt, "default-key");      /* First we search for config entries which specify a default key. */
286        e = conf_find_option (opt, "default-key");
287      if (!e)      if (!e)
288          e = find_option (opt, "local-user");          e = conf_find_option (opt, "local-user");
289      if (e)      if (e)
290          keyid = extract_keyid (e->val);          keyid = extract_keyid (e->val);
291    
292      free_if_alloc (optfile);      free_if_alloc (optfile);
293      release_gpg_options (opt);      release_config (opt);
294    
295        /* If no entry in the config has been found, we get a key
296           from the key cache. */
297      if (!keyid)      if (!keyid)
298          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
299      return keyid;      return keyid;
# Line 327  check_gnupg_prog (void) Line 332  check_gnupg_prog (void)
332    
333  static int  static int
334  parse_version_nr (const char *buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
335  {  {  
336      char tmp[8];      char *p;
337      int i;      char *tmp = m_strdup(buf);
338            
339      i=0;      int pos=0;
340      while (buf && *buf != '.' && i < 8)      while ((p = strsep(&tmp, ".")) != NULL) {
341          tmp[i++] = *buf++;          switch (++pos) {
342      tmp[i] = 0; buf++;          case 1: *major = atoi (p); break;
343      *major = atoi (tmp);          case 2: *minor = atoi (p); break;
344      i=0;          case 3: *patch = atoi (p); break;
345      while (buf && *buf != '.' && i < 8)          }
346          tmp[i++] = *buf++;      }
347      tmp[i] = 0; buf++;      delete[] tmp;  
348      *minor = atoi (tmp);      if (pos != 3)
349      i=0;          return -1;  
     while (buf && isdigit (*buf) && i < 8)  
         tmp[i++] = *buf++;  
     tmp[i] = 0;  
     *patch = atoi (tmp);  
350      return 0;      return 0;
351  }  }
352    
# Line 357  int Line 358  int
358  check_gnupg_engine (const char *need_gpg_ver,  check_gnupg_engine (const char *need_gpg_ver,
359                      int *r_major, int *r_minor, int *r_patch)                      int *r_major, int *r_minor, int *r_patch)
360  {  {
     gpgme_ctx_t ctx;  
361      gpgme_engine_info_t inf;      gpgme_engine_info_t inf;
362      char *eng = NULL;      char *eng = NULL;
363      int major=0, minor=0, patch=0;      int major=0, minor=0, patch=0;
# Line 369  check_gnupg_engine (const char *need_gpg Line 369  check_gnupg_engine (const char *need_gpg
369                            &need_major, &need_minor, &need_patch))                            &need_major, &need_minor, &need_patch))
370          return 1;          return 1;
371            
372      gpgme_new (&ctx);      if (gpgme_get_engine_info (&inf))
373      inf = gpgme_ctx_get_engine_info (ctx);       return -1;
     if (!inf) {  
         gpgme_release (ctx);  
         return -1;  
     }  
374    
375      /* 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. */
376      if (gpg_get_version (&eng))      if (gpg_get_version (&eng))
377          return -1;       return -1;
378      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
379          idea_available = 1;          idea_available = 1;
380      safe_free (eng);      safe_free (eng);
381      if (parse_version_nr (inf->version, &major, &minor, &patch)) {    
382          gpgme_release (ctx);      if (parse_version_nr (inf->version, &major, &minor, &patch))
383          return 1;          return 1;
     }  
     gpgme_release (ctx);  
384    
385      if (major > need_major)      if (major > need_major)
386          rc = 0;          rc = 0;
# Line 404  check_gnupg_engine (const char *need_gpg Line 398  check_gnupg_engine (const char *need_gpg
398  }  }
399    
400    
401  int  /* Count the keyring entries in the gpg.conf file.
402  check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)     Return value: 0 on success. */
403    static int
404    cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
405  {  {
406      gpg_optfile_t opt;          config_file_t opt;    
407      gpg_option_t e;      conf_option_t e;
408    
409      *r_secrings = 0;      *r_secrings = 0;
410      *r_pubrings = 0;      *r_pubrings = 0;
     if (parse_gpg_options (fname, &opt))  
         return WPTERR_FILE_OPEN;  
411    
412        if (parse_config (fname, &opt))
413            return WPTERR_FILE_OPEN;
414      for (e = opt->list; e; e = e->next) {      for (e = opt->list; e; e = e->next) {
415          if (!strcmp( e->name, "secret-keyring")) {          if (!strcmp (e->name, "secret-keyring")) {
416              if (!file_exist_check (e->val))              if (!file_exist_check (e->val))
417                  r_secrings[0]++;                  r_secrings[0]++;
418          }          }
# Line 425  check_gnupg_cfgfile (const char *fname, Line 421  check_gnupg_cfgfile (const char *fname,
421                  r_pubrings[0]++;                  r_pubrings[0]++;
422          }          }
423      }      }
424      release_gpg_options (opt);      release_config (opt);
425      return 0;      return 0;
426  }  }
427    
# Line 476  gnupg_access_files (void) Line 472  gnupg_access_files (void)
472              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
473          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
474          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
475              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
476              if (!rc && secrings > 0 && pubrings > 0) {              if (!rc && secrings > 0 && pubrings > 0) {
477                  free_if_alloc (optfile);                  free_if_alloc (optfile);
478                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
# Line 496  gnupg_access_files (void) Line 492  gnupg_access_files (void)
492  }  }
493    
494    
 static int  
 create_gpg_options (void)  
 {  
     FILE *fp;  
     char *s, *optfile;  
   
     s = get_gnupg_path ();  
     if (!s)  
         return WPTERR_FILE_CREAT;  
     optfile = make_filename (s, GPG_CONF, NULL);  
     fp = fopen (optfile, "wb");  
     if (!fp) {  
         return WPTERR_FILE_CREAT;  
         goto fail;  
     }  
     fwrite (options_skel, 1, strlen (options_skel), fp);  
     fclose (fp);  
   
 fail:  
     free_if_alloc (s);  
     free_if_alloc (optfile);  
     return 0;  
 }  
   
495    
496  /* Return the contents of the options file as a char buf. */  /* Return the contents of the options file as a char buf. */
497  char*  char*
498  get_gnupg_config (void)  get_gnupg_config (void)
499  {  {
500      FILE *fp;      FILE *fp;
501      char *p = NULL, *optfile = NULL;      char *p = NULL, *optfile;
502      int fsize, rc = 0;      int fsize;
503                    
504      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
505      if (optfile == NULL)      if (!optfile)
506          return NULL;          return NULL;
507      fsize = get_file_size (optfile);      fsize = get_file_size (optfile);
508      if (!fsize) {      if (fsize < 1 || fsize > 100000)
509          rc = create_gpg_options ();          goto leave; /* too large or does not exist */
510          if (rc)      
511              return NULL;      fp = fopen (optfile, "rb");
512          fsize = get_file_size (optfile);      if (!fp)
513      }          goto leave;
     if (fsize > 100000)  
         goto leave; /* too large */  
514      p = new char[fsize+1];      p = new char[fsize+1];
515      if (!p)      if (!p)
516          BUG (NULL);          BUG (NULL);
     fp = fopen( optfile, "rb" );  
     if (!fp) {  
         free_if_alloc (p);  
         return NULL;  
     }  
517      fread (p, 1, fsize, fp);      fread (p, 1, fsize, fp);
518      fclose (fp);      fclose (fp);
519      p[fsize] = '\0';      p[fsize] = '\0';
520      free_if_alloc (optfile);      
   
521  leave:  leave:
522        free_if_alloc (optfile);
523      return p;      return p;
524  }  }
525    
# Line 564  leave: Line 529  leave:
529  int  int
530  set_gnupg_default_key (const char *key)  set_gnupg_default_key (const char *key)
531  {  {
532      gpg_optfile_t opt;      config_file_t opt;
533      gpg_option_t e;      conf_option_t e;
534      char *optfile = NULL;      char *optfile = NULL;
535      int rc = 0;      int rc = 0;
536    
537      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
538      if (!optfile)      if (!optfile)
539          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
540      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
541      if (rc) {      if (rc) {
542          free_if_alloc (optfile);          free_if_alloc (optfile);
543          return WPTERR_GENERAL;          return WPTERR_GENERAL;
544      }      }
545      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
546      if (e && !key)      if (e && !key)
547          e->used = 0;          e->used = 0;
548      else if (e) {      else if (e) {
# Line 586  set_gnupg_default_key (const char *key) Line 551  set_gnupg_default_key (const char *key)
551          e->used = 1;          e->used = 1;
552      }      }
553      else if (key)      else if (key)
554          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
555      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
556    
557      free_if_alloc (optfile);      free_if_alloc (optfile);
558      release_gpg_options (opt);      release_config (opt);
   
559      return rc;      return rc;
560  }  }
561    
562    
563  /* Set the contents of the options file. */  /* Set the contents of the options file. */
564  int  int
565  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
566  {  {
567      FILE *fp;        FILE *fp;  
568      char *optfile = NULL;      char *optfile;
569    
570      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
571      if( optfile == NULL )      if (!optfile)
572          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
573    
574      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
575      if( fp == NULL ) {      if (!fp) {
576          free_if_alloc( optfile );          free_if_alloc (optfile);
577          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
578      }      }
579      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
580      fclose( fp );      fclose (fp);
581      free_if_alloc( optfile );      free_if_alloc (optfile);
582      return 0;      return 0;
583  } /* set_gnupg_options */  }
584    
585  /*  
586   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
587   */     Return value: 0 on success. */
588    static int
589    check_arg_file_exist (const char *buf)
590    {
591        const char *s = "load-extension ";
592    
593        /* XXX: this is a bit of a kludge because we just
594                detect errors for 'load-extension'. */
595        if (!strncmp (buf, s, strlen (s)))
596            buf += strlen (s);
597        else
598            return 0;
599        return file_exist_check (buf);
600    }
601    
602    
603    /* Check if the line contains a valid GPG argument. */
604  static int  static int
605  check_line( const char *buf )  check_line (const char *buf)
606  {  {
607      int j, len;      int j, len;
608      int rc = 0;      int rc = 0;
609    
610      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
611          return 1;          return 1;
612      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
613      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
614          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
615          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
616      }      }
   
617      return rc;      return rc;
618  } /* check_line */  }
619    
620    
621  int  int
622  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
623  {  {
624      char line[1024];      char line[1024];
625      int nbytes = 0;      int nbytes = 0, lineno=0;
626      unsigned j;      unsigned j;
627                    
628      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
629          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
630          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
631              line[nbytes] = '\0';              line[nbytes] = '\0';
632              if( !check_line( line ) ) {              lineno++;
633                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
634                    if (showerr)
635                        log_box ("GPG Config File", MB_ERR,
636                                 "gpg.conf:%d: invalid keyword '%s'",
637                                 lineno, line);
638                  return 1;                        return 1;      
639              }              }
640                if (check_arg_file_exist (line))
641                    return WPTERR_FILE_EXIST;
642              nbytes = 0;              nbytes = 0;
643          }                }
644      }      }
   
645      return 0;      return 0;
646  } /* check_gnupg_options */  }
647    
648    
649  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
650  static int  static int
651  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
652  {  {
653      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
654    
655      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
656      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
657      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,      if (fd == INVALID_HANDLE_VALUE)
                      OPEN_ALWAYS, 0, NULL);  
     if (fd == INVALID_HANDLE_VALUE) {  
         free_if_alloc (path);  
         free_if_alloc (file);  
658          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
659      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
660      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
661      return 0;      return 0;
662  }  }
663    
664    
665  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
666  static void  static void
667  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
668  {                {              
669      ctx->modified = 0;      ctx->modified = 0;
670    
671      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
672          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
673          ctx->modified = 1;          ctx->modified = 1;
674        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
675      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
676          ctx->modified = 0;          ctx->modified = 0;
677    
# Line 708  check_last_gnupg_access (gpg_watcher_s * Line 680  check_last_gnupg_access (gpg_watcher_s *
680  }  }
681    
682    
683  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
684  void  void
685  init_gnupg_table (void)  init_gnupg_table (void)
686  {        {      
687      char *p;      char *path;
688      int j;      int j;
689    
690        path = get_gnupg_path ();
691      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
692          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
693          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
694          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
695          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
696          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
697      }      }
698        free_if_alloc (path);
699  }  }
700    
701    
702    /* Release the GPG monitor table. */
703  void  void
704  free_gnupg_table (void)  free_gnupg_table (void)
705  {  {
706      int j;      for (int j=0; j < gpg_table_count; j++) {
   
     for (j=0; j < gpg_table_count; j++)  
707          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
708            free_if_alloc (gpg_table[j].fpath_object);
709        }
710  }  }
711    
712    
713  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
714  int  int
715  keyring_check_last_access (void)  keyring_check_last_access (void)
716  {        {
717      int rc, j;      int nfiles;
718    
719      rc = 0;      nfiles = 0;
720      for (j = 0; j < gpg_table_count; j++) {      for (int pos = 0; pos < gpg_table_count; pos++) {
721          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
722          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
723          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
724              rc++;                    nfiles++;
725      }      }
726    
727      return rc;      return nfiles;
728  }  }
729    
730    
# Line 773  gnupg_check_file_ext (const char *fname, Line 747  gnupg_check_file_ext (const char *fname,
747              *r_type = PGP_SIG;              *r_type = PGP_SIG;
748          return "SIGNED";          return "SIGNED";
749      }      }
750      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
751                  !stricmp (file_ext, ".pgp")) {
752          if (r_type)          if (r_type)
753              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
754          return "ENCRYPTED";          return "ENCRYPTED";
# Line 782  gnupg_check_file_ext (const char *fname, Line 757  gnupg_check_file_ext (const char *fname,
757  }  }
758    
759    
760  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 */  
761  static int  static int
762  my_access (const char *fname)  check_file_access (const char *fname, int mode)
763  {  {
764      HANDLE hd;      HANDLE hd;
765      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,  
766        if (!mode)
767            mode = FILE_SHARE_WRITE;
768        hd = CreateFile (fname, GENERIC_WRITE, mode,
769                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
770      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
771          return -1;          return -1;
# Line 819  my_access (const char *fname) Line 773  my_access (const char *fname)
773      return 0;      return 0;
774  }  }
775    
776        
777    /* Check the device where the file @fname is stored on, is either
778       write-protected or if the file is already opened by another process
779       exclusively. And as a result, we cannot use the file for output. */
780    int
781    gpg_check_file_permissions (const char *fname, int mode)
782    {
783        int api_mode;
784        
785        switch (mode) {
786        case 0: api_mode = FILE_SHARE_READ; break;
787        case 1: api_mode = FILE_SHARE_WRITE; break;
788        case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
789        default: api_mode = FILE_SHARE_READ; break;
790        }
791    
792        return check_file_access (fname, api_mode);
793    }
794    
795    
796  /* Check the file permissions of the public keyring.  /* Check the file permissions of the public keyring.
797     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 853  gpg_check_permissions (int showmsg) Line 826  gpg_check_permissions (int showmsg)
826                  failed = 1;                  failed = 1;
827              }              }
828          }          }
829          if (my_access (name)) {          if (gpg_check_file_permissions (name, 1)) {
830              if (showmsg)              if (showmsg)
831                  msg_box (NULL,                  msg_box (NULL,
832                  _("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 876  gpg_check_permissions (int showmsg) Line 849  gpg_check_permissions (int showmsg)
849  int  int
850  gnupg_check_homedir (void)  gnupg_check_homedir (void)
851  {        {      
852      char *homedir = NULL;      char *homedir;
853      int val = 0;      int val;
854      int rc = 0;      int rc = 0;
855    
856      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
# Line 904  gnupg_check_homedir (void) Line 877  gnupg_check_homedir (void)
877  int  int
878  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
879  {  {
880      const char * pring, * sring;      const char *pring, *sring;
881      char * file = NULL, * path = NULL;      char *file = NULL, *path;
882      int id = 0, rc = 0;      int id, rc = 0;
883      HWND hwnd;      HWND hwnd;
884            
885      path = get_gnupg_path ();      path = get_gnupg_path ();
# Line 915  gnupg_copy_keyrings (void) Line 888  gnupg_copy_keyrings (void)
888      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
889    
890      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
891                                "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
892      if (!pring) {      if (!pring) {
893          msg_box (hwnd, _("No keyring was chosen. Exit."),          msg_box (hwnd, _("No keyring was chosen. Exit."),
894                   _("WinPT Error"), MB_ERR);                   _("WinPT Error"), MB_ERR);
895          free_if_alloc (path);          free_if_alloc (path);
896          return WPTERR_GENERAL;          return WPTERR_GENERAL;
897      }      }
898      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
899      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
900          id = msg_box (hwnd, _("Overwrite old public keyring?"),          id = msg_box (hwnd, _("Overwrite old public keyring?"),
901                        "WinPT", MB_INFO|MB_YESNO);                        "WinPT", MB_INFO|MB_YESNO);
902          if (id == IDNO)          if (id == IDNO)
903              goto fail;              goto fail;
904      }      }
905      if (!CopyFile (pring, file, FALSE)) {      if (!CopyFile (pring, file, FALSE)) {
906          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("Could not copy public keyring."),
907                     _("WinPT Error"), MB_ERR);
908          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
909          goto fail;          goto fail;
910      }      }
# Line 951  gnupg_copy_keyrings (void) Line 925  gnupg_copy_keyrings (void)
925              goto fail;              goto fail;
926      }      }
927      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
928          msg_box (NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy secret keyring."), _("WinPT Error"), MB_ERR);
929          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
930      }      }
931    
# Line 966  fail: Line 940  fail:
940  void  void
941  gnupg_backup_options (void)  gnupg_backup_options (void)
942  {  {
943      char *cfgfile = NULL;      char *cfgfile;
944      char bak[512];      char bak[MAX_PATH+32];
945    
946      cfgfile = get_gnupg_cfgfile ();      cfgfile = get_gnupg_cfgfile ();
947      if (!cfgfile)      if (!cfgfile)
# Line 986  backup_one_file (const char *srcpath, co Line 960  backup_one_file (const char *srcpath, co
960      BOOL rc;      BOOL rc;
961    
962      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
963      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
964      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
965      free_if_alloc (src);      free_if_alloc (src);
966      free_if_alloc (dst);      free_if_alloc (dst);
# Line 1014  check_keyring (char **r_path) Line 984  check_keyring (char **r_path)
984      if (!*r_path)      if (!*r_path)
985          return 0;          return 0;
986      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
987      if (!p || get_file_size (p) <= 0)      if (get_file_size (p) <= 0)
988          return 0;          return 0;
989    
990      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
991      if (!opt)      if (!opt)
992          BUG (0);          BUG (0);
993      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
994      free_if_alloc (opt);      free_if_alloc (opt);
995      free_if_alloc (p);      free_if_alloc (p);
996      if (!name)      if (!name)
# Line 1044  static char* Line 1014  static char*
1014  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1015  {  {
1016      struct tm *tm;      struct tm *tm;
1017        const char *fmt;
1018      char *p;      char *p;
1019      time_t t;      time_t t;
1020    
1021      t = time (NULL);      t = time (NULL);
1022      tm = localtime (&t);      tm = localtime (&t);
1023      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1024        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1025      if (!p)      if (!p)
1026          BUG (0);          BUG (0);
1027      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1028      return p;      return p;
1029  }  }
1030    
# Line 1064  get_backup_name (const char *templ) Line 1036  get_backup_name (const char *templ)
1036  void  void
1037  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1038  {  {
1039      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1040      char *name=NULL;      char *name;
1041      int rc;      int rc;
1042    
1043      if (!auto_backup)      if (!auto_backup)
# Line 1073  gnupg_backup_keyrings (int auto_backup, Line 1045  gnupg_backup_keyrings (int auto_backup,
1045      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1046      check_keyring (&srcpath);      check_keyring (&srcpath);
1047      if (backup_mode == 1) {      if (backup_mode == 1) {
1048          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1049               and destination folder will be the same. */
1050            dstpath = get_gnupg_path ();
1051          check_keyring (&dstpath);          check_keyring (&dstpath);
1052      }      }
1053      else if (backup_mode == 2) {      else if (backup_mode == 2) {
# Line 1081  gnupg_backup_keyrings (int auto_backup, Line 1055  gnupg_backup_keyrings (int auto_backup,
1055          FILE *fp;          FILE *fp;
1056    
1057          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1058          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1059          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1060          if (!fp)          if (!fp)
1061              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1062                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1063                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1064          else {          else {
1065              rc = 0;              rc = 0;
1066              fclose (fp);              fclose (fp);
1067              remove (tmpfile);              DeleteFile (tmpfile);
1068          }          }
1069          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1070          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1071                free_if_alloc (dstpath);
1072                free_if_alloc (srcpath);
1073              return;              return;
1074            }
1075      }      }
1076      else {      else {
1077          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1078            free_if_alloc (srcpath);
1079          return;          return;
1080      }      }
1081      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
# Line 1112  gnupg_backup_keyrings (int auto_backup, Line 1088  gnupg_backup_keyrings (int auto_backup,
1088  }  }
1089    
1090    
 /* Display GPG error from file if possible. */  
 void  
 gnupg_display_error (void)  
 {        
     char tmpath[512], *errstr;  
     size_t size = 0;  
     FILE *fp;  
   
     get_temp_name (tmpath, sizeof (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);  
 }  
   
   
   
1091  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1092     Return value: 0 for success. */     Return value: 0 for success. */
1093  int  int

Legend:
Removed from v.222  
changed lines
  Added in v.328

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26