/[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 42 by werner, Fri Oct 28 08:25:30 2005 UTC revision 222 by twoaday, Thu Jun 1 08:30:46 2006 UTC
# Line 1  Line 1 
1  /* wptGPG.cpp - GnuPG configuration  /* wptGPG.cpp - GnuPG configuration
2   *      Copyright (C) 2001-2005 Timo Schulz   *      Copyright (C) 2001-2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 22  Line 22 
22  #endif  #endif
23    
24  #include <windows.h>  #include <windows.h>
 #include <windows.h>  
25  #include <string.h>  #include <string.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <shlobj.h>  #include <shlobj.h>
# Line 31  Line 30 
30  #include <time.h>  #include <time.h>
31    
32  #include "wptGPG.h"  #include "wptGPG.h"
33  #include "wptGPGCmds.h"  #include "wptGpgCmds.h"
34  #include "wptGPGOptSkel.h"  #include "wptGPGOptSkel.h"
35  #include "wptTypes.h"  #include "wptTypes.h"
36  #include "wptNLS.h"  #include "wptNLS.h"
# Line 40  Line 39 
39  #include "wptW32API.h"  #include "wptW32API.h"
40  #include "wptCrypto.h"  #include "wptCrypto.h"
41    
42  #define GPG_CONF "gpg.conf"  #define GPG_CONF        "gpg.conf"
43    #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
44    #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
45    
46  struct gpg_watcher_s {  struct gpg_watcher_s {
47      FILETIME    last_access;      FILETIME    last_access;
# Line 61  static int check_keyring (char ** r_path Line 62  static int check_keyring (char ** r_path
62    
63    
64  /* Return the application data folder of the current user. */  /* Return the application data folder of the current user. */
65  static char*  char*
66  multi_gnupg_path (void)  multi_gnupg_path (int strict)
67  {  {
68      static char buf[256+64];      static char buf[256+64];
69      BOOL ec;      BOOL ec;
# Line 71  multi_gnupg_path (void) Line 72  multi_gnupg_path (void)
72      memset (buf, 0, sizeof (buf));      memset (buf, 0, sizeof (buf));
73      /* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */      /* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */
74      ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE);      ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE);
75      if (ec != 1)      if (ec != 1) {
76            log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed\r\n",
77                       (int)GetLastError ());
78          return NULL;          return NULL;
79        }
80      strcat (buf, "\\gnupg");      strcat (buf, "\\gnupg");
81      if (access (buf, 00))      if (strict && access (buf, 00))
82          return NULL;          return NULL;
83      return m_strdup (buf);      return m_strdup (buf);
84  }  }
85    
86    
87  /* 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
88     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. */
 */  
89  char*  char*
90  get_gnupg_path (void)  get_gnupg_path (void)
91  {  {
92      char *p = NULL, *path = NULL;      char *path;
93        
94      p = get_reg_entry_gpg ("HomeDir");      path = get_reg_entry_gpg (GPG_REG_HOME);
95      if (p) {      if (path) {
96          path = m_strdup (p);          if (dir_exist_check (path) == 0)
97          free_if_alloc (p);              return path;
98          return path;          free_if_alloc (path);
99      }      }
100      else      path = multi_gnupg_path (1);
101          return multi_gnupg_path ();      return path;
     return m_strdup ("c:\\gnupg");  
102  }  }
103    
104    
# Line 105  get_gnupg_path (void) Line 107  get_gnupg_path (void)
107  char*  char*
108  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
109  {      {    
110      char *p = NULL, *optfile = NULL, *path = NULL;      char *p = NULL;
111        char *optfile = NULL;
112        char *path = NULL;
113      size_t nlen = 0;      size_t nlen = 0;
114    
115      path = get_gnupg_path ();      path = get_gnupg_path ();
116      if (!path)      if (!path)
117          return NULL;          return NULL;
118      p = get_reg_entry_gpg ("OptFile");      nlen = strlen (path) + 64;
119      if (p && !strcmp (p, "")) {      optfile = new char[nlen + 1];
120          nlen = strlen (path) + 64;      if (!optfile)
121          optfile = new char[nlen + 1];          BUG (NULL);    
122          if (!optfile)      _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);
123              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);  
     }  
124      free_if_alloc (path);      free_if_alloc (path);
125      free_if_alloc (p);      free_if_alloc (p);
126      return optfile;      return optfile;
# Line 152  get_gnupg_keyring (int pub, int strict) Line 140  get_gnupg_keyring (int pub, int strict)
140      if (!path)      if (!path)
141          return NULL;          return NULL;
142      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
143      if (!strict && !file_exist_check (keyring)) {      if (strict && !file_exist_check (keyring)) {
144            free_if_alloc (path);
145            return keyring;
146        }
147        else if (!strict) {
148          free_if_alloc (path);          free_if_alloc (path);
149          return keyring;          return keyring;
150      }      }
151      if (file_exist_check (keyring) || get_file_size (keyring) == 0) {      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {
152          free_if_alloc (keyring);          free_if_alloc (keyring);
153          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
154          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_gnupg_keyring_from_options (optfile, pub);
# Line 170  get_gnupg_keyring (int pub, int strict) Line 162  get_gnupg_keyring (int pub, int strict)
162  /* 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
163     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
164     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
165    
166    /* FIXME:  Use gpgme's engine info here. */
167  char*  char*
168  get_gnupg_prog (void)  get_gnupg_prog (void)
169  {      {    
170      char *p;      char *p;
171      char *pgm = NULL;      char *pgm = NULL;
     size_t nlen = 0;  
172    
173      p = get_reg_entry_gpg ("gpgProgram");      p = get_reg_entry_gpg (GPG_REG_EXE);
174      if (!p) {      if (!p) {
175          char *path = get_gnupg_path ();          char *path = get_gnupg_path ();
176          if (!path)          if (!path)
# Line 198  get_gnupg_prog (void) Line 191  get_gnupg_prog (void)
191     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
192  static char *  static char *
193  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
194  {  {    
195      const char * s;      gpgme_key_t key, pk;
196      char * keyid = NULL;      gpg_keycache_t sec, pub;
197      gpgme_key_t key;      const char *s;
198      gpg_keycache_t sec = keycache_get_ctx (0);      char *keyid = NULL;
199    
200        sec = keycache_get_ctx (0);
201      if (!sec)      if (!sec)
202          BUG (0);          BUG (0);
203        pub = keycache_get_ctx (1);
204      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
205      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
206          if (key_is_useable (key)) {          if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
207              s = key->subkeys->keyid;              s = key->subkeys->keyid;
208              if (s)                  if (s)
209                  keyid = m_strdup (s+8);                  keyid = m_strdup (s+8);
210              break;              break;
211          }          }
212      }      }
213      if (!keyid) {      if (!keyid)
214          *ret_no_useable = 1;          *ret_no_useable = 1;    
         msg_box (NULL, _("No useable secret key found."), _("GPG Error"), MB_ERR);  
     }  
215      return keyid;      return keyid;
216  }  }
217    
# Line 232  gnupg_load_config (void) Line 225  gnupg_load_config (void)
225      int rc;      int rc;
226      gpg_optfile_t opt;      gpg_optfile_t opt;
227      gpg_option_t o;      gpg_option_t o;
228      char *conf = get_gnupg_cfgfile ();      char *conf;
229        
230        conf = get_gnupg_cfgfile ();
231      if (!conf)      if (!conf)
232          return -1;          return -1;
233      rc = parse_gpg_options (conf, &opt);      rc = parse_gpg_options (conf, &opt);
# Line 243  gnupg_load_config (void) Line 238  gnupg_load_config (void)
238      o = find_option (opt, "ask-cert-level");      o = find_option (opt, "ask-cert-level");
239      if (o)      if (o)
240          reg_prefs.gpg.ask_cert_level = 1;          reg_prefs.gpg.ask_cert_level = 1;
241        o = find_option (opt, "ask-cert-expire");
242        if (o)
243            reg_prefs.gpg.ask_cert_expire = 1;
244      release_gpg_options (opt);      release_gpg_options (opt);
245      free_if_alloc (conf);      free_if_alloc (conf);
246      return 0;      return 0;
247  }  }
248    
249    
250    /* handle the case the user added a '!' to force a subkey. */
251    static char*
252    extract_keyid (const char *val)
253    {    
254        size_t len = strlen (val);
255    
256        if (len > 1 && val[len-1] == '!') {
257            char *p = new char[len+1];
258            if (!p)
259                BUG (0);
260            memset (p, 0, len+1);
261            memcpy (p, val, len-1);
262            return p;
263        }
264        return m_strdup (val);
265    }
266    
267    
268  char*  char*
269  get_gnupg_default_key (void)  get_gnupg_default_key (void)
270  {      {    
271      gpg_optfile_t opt = NULL;      gpg_optfile_t opt = NULL;
272      gpg_option_t e;      gpg_option_t e;
273      char * keyid = NULL, * optfile = NULL;      char *keyid = NULL, *optfile = NULL;
274      int no_usable=0, rc = 0;      int no_usable=0, rc = 0;
275    
276      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
# Line 262  get_gnupg_default_key (void) Line 278  get_gnupg_default_key (void)
278          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
279      rc = parse_gpg_options (optfile, &opt);      rc = parse_gpg_options (optfile, &opt);
280      if (rc) {      if (rc) {
281          free_if_alloc( optfile );          free_if_alloc (optfile);
282          return default_key_from_cache( &no_usable );          return default_key_from_cache (&no_usable);
     }  
     e = find_option( opt, "default-key" );  
     if ( e )  
         keyid = m_strdup( e->val );  
     if( !e ) {  
         e = find_option( opt, "local-user" );  
         if( e )  
             keyid = m_strdup( e->val );  
     }  
     if( !e ) {  
         e = find_option( opt, "encrypt-to" );  
         if( e )  
             keyid = m_strdup( e->val );  
283      }      }
284        e = find_option (opt, "default-key");
285        if (!e)
286            e = find_option (opt, "local-user");
287        if (e)
288            keyid = extract_keyid (e->val);
289    
290      free_if_alloc (optfile);      free_if_alloc (optfile);
291      release_gpg_options (opt);      release_gpg_options (opt);
   
292      if (!keyid)      if (!keyid)
293          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
294      return keyid;      return keyid;
295  } /* get_gnupg_default_key */  }
296    
297    
298    /* Check if GPG4WIN is available and if so, use the
299       install path to figure out where the gpg.exe is. */
300    char*
301    check_for_gpg4win (void)
302    {
303        return get_reg_entry_gpg4win ("gpg.exe");
304    }
305    
306    
307  /* Check if the gpg application (exe file) is available. */  /* Check if the gpg application (exe file) is available. */
308  int  int
309  check_gnupg_prog (void)  check_gnupg_prog (void)
310  {  {
311      char *pgm = NULL;      char *gpgexe = NULL;
312      int rc = 0;      int rc = 0;
313    
314      pgm = get_gnupg_prog ();      gpgexe = get_gnupg_prog ();
315      if (!pgm)      if (!gpgexe || file_exist_check (gpgexe)) {
316          rc = WPTERR_GPG_EXEFILE;          free_if_alloc (gpgexe);
317      if (file_exist_check (pgm))          gpgexe = check_for_gpg4win ();
318          rc = WPTERR_GPG_EXEFILE;          if (!gpgexe || file_exist_check (gpgexe))
319      free_if_alloc (pgm);              rc = WPTERR_GPG_EXEFILE;
320            else
321                set_reg_entry_gpg (GPG_REG_EXE, gpgexe);
322        }
323        free_if_alloc (gpgexe);
324      return rc;      return rc;
325  }  }
326    
327    
328  static int  static int
329  parse_version_nr (const char * buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
330  {  {
331      char tmp[8];      char tmp[8];
332      int i;      int i;
# Line 314  parse_version_nr (const char * buf, int Line 335  parse_version_nr (const char * buf, int
335      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
336          tmp[i++] = *buf++;          tmp[i++] = *buf++;
337      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
338      *major = atol( tmp );      *major = atoi (tmp);
339      i=0;      i=0;
340      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
341          tmp[i++] = *buf++;          tmp[i++] = *buf++;
342      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
343      *minor = atol (tmp);      *minor = atoi (tmp);
344      i=0;      i=0;
345      while (buf && isdigit( *buf ) && i < 8)      while (buf && isdigit (*buf) && i < 8)
346          tmp[i++] = *buf++;          tmp[i++] = *buf++;
347      tmp[i] = 0;      tmp[i] = 0;
348      *patch = atol (tmp);      *patch = atoi (tmp);
349      return 0;      return 0;
350  }  }
351    
# Line 333  parse_version_nr (const char * buf, int Line 354  parse_version_nr (const char * buf, int
354     version given in @r_major.@r_minor.@r_patch. On success these     version given in @r_major.@r_minor.@r_patch. On success these
355     variables contain the GPG version which is installed. */     variables contain the GPG version which is installed. */
356  int  int
357  check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)  check_gnupg_engine (const char *need_gpg_ver,
358                        int *r_major, int *r_minor, int *r_patch)
359  {  {
360      gpgme_ctx_t ctx;      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;
364      int rc;      int need_major = 0, need_minor = 0, need_patch = 0;
365                int rc = 1;
366    
367        /* Convert the needed GPG version to the integer format. */
368        if (parse_version_nr (need_gpg_ver,
369                              &need_major, &need_minor, &need_patch))
370            return 1;
371        
372      gpgme_new (&ctx);      gpgme_new (&ctx);
373      inf = gpgme_ctx_get_engine_info (ctx);      inf = gpgme_ctx_get_engine_info (ctx);
374      if (!inf) {      if (!inf) {
375          gpgme_release (ctx);          gpgme_release (ctx);
376          return -1;          return -1;
377      }      }
378    
379      /* 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. */
380      if (gpg_get_version (&eng))      if (gpg_get_version (&eng))
381          return -1;          return -1;
382      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
383          idea_available = 1;          idea_available = 1;
384      free (eng);      safe_free (eng);
385      rc = parse_version_nr( inf->version, &major, &minor, &patch );      if (parse_version_nr (inf->version, &major, &minor, &patch)) {
     if( rc ) {  
386          gpgme_release (ctx);          gpgme_release (ctx);
387          return rc;          return 1;
388      }      }
389      if (major < *r_major || minor < *r_minor)      gpgme_release (ctx);
390          rc = 1;  
391      else {      if (major > need_major)
         if (patch < *r_patch)  
             rc = 1;  
392          rc = 0;          rc = 0;
393      }      else if (major == need_major && minor > need_minor)      
394            rc = 0;
395        else if (major == need_major && minor == need_minor &&
396                 patch >= need_patch)
397            rc = 0;
398    
399        /* Return the current GPG version. */
400      *r_major = major;      *r_major = major;
401      *r_minor = minor;      *r_minor = minor;
402      *r_patch = patch;      *r_patch = patch;
# Line 377  check_gnupg_cfgfile (const char *fname, Line 409  check_gnupg_cfgfile (const char *fname,
409  {  {
410      gpg_optfile_t opt;          gpg_optfile_t opt;    
411      gpg_option_t e;      gpg_option_t e;
     int rc = 0;  
412    
413      *r_secrings = 0;      *r_secrings = 0;
414      *r_pubrings = 0;      *r_pubrings = 0;
415      rc = parse_gpg_options( fname, &opt );      if (parse_gpg_options (fname, &opt))
     if( rc )  
416          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
417    
418      for( e = opt->list; e; e = e->next ) {      for (e = opt->list; e; e = e->next) {
419          if( !strcmp( e->name, "secret-keyring" ) ) {          if (!strcmp( e->name, "secret-keyring")) {
420              if( !file_exist_check( e->val ) )              if (!file_exist_check (e->val))
421                  r_secrings[0]++;                  r_secrings[0]++;
422          }          }
423          else if( !strcmp( e->name, "keyring" ) ) {          else if (!strcmp (e->name, "keyring")) {
424              if( !file_exist_check( e->val ) )              if (!file_exist_check (e->val))
425                  r_pubrings[0]++;                  r_pubrings[0]++;
426          }          }
427      }      }
428      release_gpg_options( opt );      release_gpg_options (opt);
429      return 0;      return 0;
430  } /* check_gnupg_cfgfile */  }
431    
432    
433  /*  /* Usually GPG creates the pubring.gpg, secring.gpg on
434   * Check if both keyrings are located in the gnupg home directory.     the first start, but to make sure they always exist
435   */     create them empty if needed. */
436    static void
437    create_empty_keyring (int _pub)
438    {
439        char *name;
440        FILE *fp;
441    
442        name = get_gnupg_keyring (_pub, 0);
443        if (name && file_exist_check (name) != 0) {
444            fp = fopen (name, "ab");
445            if (fp != NULL)
446                fclose (fp);
447        }
448        free_if_alloc (name);
449    }
450    
451    
452    /* Check if both keyrings are located in the gnupg home directory. */
453  int  int
454  gnupg_access_files (void)  gnupg_access_files (void)
455  {  {
# Line 411  gnupg_access_files (void) Line 458  gnupg_access_files (void)
458      int secrings = 0, pubrings = 0;      int secrings = 0, pubrings = 0;
459      char *optfile;      char *optfile;
460    
461        create_empty_keyring (1);
462      if (gnupg_access_keyring (1))      if (gnupg_access_keyring (1))
463          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
464      else      else
465          pubring_ok = 1;          pubring_ok = 1;
466    
467        create_empty_keyring (0);
468      if (gnupg_access_keyring (0))      if (gnupg_access_keyring (0))
469          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
470      else      else
471          secring_ok = 1;          secring_ok = 1;
472    
473      if (!pubring_ok || !secring_ok) {      if (!pubring_ok || !secring_ok) {
474          optfile = get_gnupg_cfgfile ();          optfile = get_gnupg_cfgfile ();
475          if (!optfile)          if (!optfile)
476              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
477          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
478          if (!rc && get_file_size(optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
479              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);
480              if (!rc && secrings && pubrings) {              if (!rc && secrings > 0 && pubrings > 0) {
481                  free_if_alloc (optfile);                  free_if_alloc (optfile);
482                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
483              }              }
# Line 443  gnupg_access_files (void) Line 493  gnupg_access_files (void)
493          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
494      }      }
495      return rc;      return rc;
496  } /* gnupg_access_files */  }
497    
498    
499  static int  static int
# Line 452  create_gpg_options (void) Line 502  create_gpg_options (void)
502      FILE *fp;      FILE *fp;
503      char *s, *optfile;      char *s, *optfile;
504    
505      s = get_gnupg_path( );      s = get_gnupg_path ();
506      if( s == NULL )      if (!s)
507          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
508      optfile = make_filename( s, GPG_CONF, NULL );      optfile = make_filename (s, GPG_CONF, NULL);
509      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
510      if( fp == NULL ) {        if (!fp) {
511          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
512          goto fail;          goto fail;
513      }      }
514      fwrite( options_skel, 1, strlen( options_skel ), fp );      fwrite (options_skel, 1, strlen (options_skel), fp);
515      fclose( fp );      fclose (fp);
516    
517  fail:  fail:
518      free_if_alloc( s );      free_if_alloc (s);
519      free_if_alloc( optfile );      free_if_alloc (optfile);
520      return 0;      return 0;
521  } /* create_gpg_options */  }
522    
523    
524  /*  /* Return the contents of the options file as a char buf. */
525   * Return the contents of the options file as a char buf.  char*
  */  
 char *  
526  get_gnupg_config (void)  get_gnupg_config (void)
527  {  {
528      FILE * fp;      FILE *fp;
529      char * p = NULL, * optfile = NULL;      char *p = NULL, *optfile = NULL;
530      int fsize, rc = 0;      int fsize, rc = 0;
531                    
532      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
533      if( optfile == NULL )      if (optfile == NULL)
534          return NULL;          return NULL;
535      fsize = get_file_size( optfile );      fsize = get_file_size (optfile);
536      if( !fsize ) {      if (!fsize) {
537          rc = create_gpg_options( );          rc = create_gpg_options ();
538          if ( rc )          if (rc)
539              return NULL;              return NULL;
540          fsize = get_file_size( optfile );          fsize = get_file_size (optfile);
541      }      }
542      if( fsize > 100000 )      if (fsize > 100000)
543          goto leave; /* too large */          goto leave; /* too large */
544      p = new char[fsize+1];      p = new char[fsize+1];
545      if( p == NULL )      if (!p)
546          BUG( NULL );          BUG (NULL);
547      fp = fopen( optfile, "rb" );      fp = fopen( optfile, "rb" );
548      if( fp == NULL ) {      if (!fp) {
549          free_if_alloc( p );          free_if_alloc (p);
550          return NULL;          return NULL;
551      }      }
552      fread( p, 1, fsize, fp );      fread (p, 1, fsize, fp);
553      fclose( fp );      fclose (fp);
554      p[fsize] = '\0';      p[fsize] = '\0';
555      free_if_alloc( optfile );      free_if_alloc (optfile);
556    
557  leave:  leave:
558      return p;      return p;
559  } /* get_gnupg_config */  }
560    
561    
562    /* Set the default key in the gpg.conf.
563       If @key is NULL, the entry will be deleted. */
564  int  int
565  set_gnupg_default_key (const char * key)  set_gnupg_default_key (const char *key)
566  {  {
567      gpg_optfile_t opt;      gpg_optfile_t opt;
568      gpg_option_t e;      gpg_option_t e;
# Line 521  set_gnupg_default_key (const char * key) Line 571  set_gnupg_default_key (const char * key)
571    
572      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
573      if (!optfile)      if (!optfile)
574          return -1;          return WPTERR_FILE_OPEN;
575      rc = parse_gpg_options (optfile, &opt);      rc = parse_gpg_options (optfile, &opt);
576      if( rc ) {      if (rc) {
577          free_if_alloc (optfile);          free_if_alloc (optfile);
578          return -1;          return WPTERR_GENERAL;
579      }      }
580      e = find_option (opt, "default-key");      e = find_option (opt, "default-key");
581      if (e) {      if (e && !key)
582            e->used = 0;
583        else if (e) {
584          free_if_alloc (e->val);          free_if_alloc (e->val);
585          e->val = m_strdup (key);          e->val = m_strdup (key);
586          e->used = 1;          e->used = 1;
587      }      }
588      else      else if (key)
589          add_entry (opt, ENTRY_MULTI, "default-key", key);          add_entry (opt, ENTRY_MULTI, "default-key", key);
590      rc = commit_gpg_options (optfile, opt);      rc = commit_gpg_options (optfile, opt);
591    
# Line 541  set_gnupg_default_key (const char * key) Line 593  set_gnupg_default_key (const char * key)
593      release_gpg_options (opt);      release_gpg_options (opt);
594    
595      return rc;      return rc;
596  } /* set_gnupg_default_key */  }
597    
598    
599  /*  /* Set the contents of the options file. */
  * Set the contents of the options file.  
  */  
600  int  int
601  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options( const char *buf, size_t buflen )
602  {  {
# Line 623  get_last_gnupg_access (gpg_watcher_s *ct Line 673  get_last_gnupg_access (gpg_watcher_s *ct
673    
674      path = get_gnupg_path ();      path = get_gnupg_path ();
675      file =  make_filename (path, ctx->object, NULL);      file =  make_filename (path, ctx->object, NULL);
676      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,
677                         OPEN_ALWAYS, 0, NULL);
678      if (fd == INVALID_HANDLE_VALUE) {      if (fd == INVALID_HANDLE_VALUE) {
679          free_if_alloc (path);          free_if_alloc (path);
680          free_if_alloc (file);          free_if_alloc (file);
# Line 646  check_last_gnupg_access (gpg_watcher_s * Line 697  check_last_gnupg_access (gpg_watcher_s *
697      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
698          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
699          ctx->modified = 1;          ctx->modified = 1;
700        
701        /* XXX: find a better way. without it, winpt --keymanager loads
702                the key cache twice. */
703        if (ctx->last_access.dwLowDateTime == 0)
704            ctx->modified = 0;
705    
706      ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;      ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
707      ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;      ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
# Line 752  get_gnupg_keyring_from_options (const ch Line 808  get_gnupg_keyring_from_options (const ch
808    
809  /* XXX: does not work with write-protected floppies */  /* XXX: does not work with write-protected floppies */
810  static int  static int
811  my_access (const char * fname)  my_access (const char *fname)
812  {  {
813      HANDLE hd;      HANDLE hd;
814      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
# Line 764  my_access (const char * fname) Line 820  my_access (const char * fname)
820  }  }
821    
822    
823    /* Check the file permissions of the public keyring.
824       If @showmsg is 1 output a message in case of errors.
825       Return value: 1 if read-only attribute
826                     2 if file is opened by another process exclusively. */
827  int  int
828  gpg_check_permissions (int showmsg)  gpg_check_permissions (int showmsg)
829  {  {
830      char * p, * name = NULL;      char *p = NULL;
831        char *name = NULL;
832      int failed = 0, ans=0, attrs=0;      int failed = 0, ans=0, attrs=0;
833    
834      p = get_gnupg_path ();      p = get_gnupg_path ();
835      check_keyring (&p);      if (p && check_keyring (&p)) {
     if (p) {  
836          name = make_filename (p, "pubring", "gpg");          name = make_filename (p, "pubring", "gpg");
         free_if_alloc (p);  
837          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
838              ans = msg_box (NULL,              ans = msg_box (NULL,
839                             _("The selected keyring has the read-only file\n"                             _("The selected keyring has the read-only file\n"
# Line 790  gpg_check_permissions (int showmsg) Line 849  gpg_check_permissions (int showmsg)
849                  }                  }
850              }              }
851              else if (ans == IDNO) {              else if (ans == IDNO) {
852                  /*                  /* All commands with write access will be disabled. */
                 msg_box (NULL, _("All commands with write access to the keyring\n"  
                                  "will be disabled."), _("GPG Information"), MB_INFO);  
                 */  
853                  failed = 1;                  failed = 1;
854              }              }
855          }          }
# Line 809  gpg_check_permissions (int showmsg) Line 865  gpg_check_permissions (int showmsg)
865              failed = 2;              failed = 2;
866          }          }
867      }      }
868        free_if_alloc (p);
869      free_if_alloc (name);      free_if_alloc (name);
870      return failed;      return failed;
871  } /* gpg_check_permissions */  }
872    
873    
874  /* Check the GPG home dir. If all methods failed, try to  /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
875     create the default folder. */     then check for $APPDATA\gnupg. Create the dir if it does not exists. */
876  static int  int
877  check_homedir (void)  gnupg_check_homedir (void)
878  {        {      
879      char *homedir = NULL;      char *homedir = NULL;
880      int yes = 0;      int val = 0;
881        int rc = 0;
882    
883      homedir = get_reg_entry_gpg ("HomeDir");      homedir = get_reg_entry_gpg (GPG_REG_HOME);
     if (!homedir)  
         homedir = multi_gnupg_path ();  
884      if (!homedir)      if (!homedir)
885          homedir = m_strdup ("c:\\gnupg");          homedir = multi_gnupg_path (0);
886      if (homedir) {      if (homedir) {
887          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
888              yes = log_box (_("Preferences"), MB_YESNO,              val = log_box (_("Preferences"), MB_YESNO,
889                             _("%s does not exit.\n"                             _("%s does not exit.\n"
890                               "Do you want to create this directory?"), homedir);                               "Do you want to create this directory?"), homedir);
891              if (yes == IDYES) {              if (val == IDYES) {
892                  BOOL ec = CreateDirectory (homedir, NULL);                  if (!CreateDirectory (homedir, NULL))
893                  free_if_alloc (homedir);                      rc = WPTERR_DIR_CREAT;
                 if (ec == FALSE)  
                     return WPTERR_DIR_CREAT;  
                 return 0;  
894              }              }
895              return WPTERR_DIR_OPEN;              else
896          }                  rc = WPTERR_DIR_OPEN;
         free_if_alloc (homedir);  
     }  
     return 0;  
 }  
   
   
 int  
 gnupg_check_homedir (void)  
 {        
     char *homedir = NULL;  
     char *prog = NULL;  
     int rc = 0, ec = 0;  
       
     rc = check_homedir ();  
     if (rc)  
         return rc;  
     if ((homedir = get_reg_entry_gpg ("HomeDir")) &&  
         !(prog = get_reg_entry_gpg ("gpgProgram" ))) {  
         prog = make_filename (homedir, "gpg", "exe");  
         if (file_exist_check (prog) == 0) {  
             rc = set_reg_entry_gpg ("gpgProgram", prog);  
             if (rc)  
                 goto fail;  
897          }          }
898          free_if_alloc (homedir);          free_if_alloc (homedir);
         free_if_alloc (prog);  
         return rc;  
     }  
     if ((prog = get_reg_entry_gpg ("gpgProgram"))  
         && file_exist_check (prog)) {  
         free_if_alloc (prog);  
         homedir = get_reg_entry_gpg ("HomeDir");  
         if (!homedir) {  
             rc = WPTERR_GENERAL;  
             goto fail;  
         }  
         prog = make_filename (homedir, "gpg", "exe");  
         if (file_exist_check (prog) == 0) {  
             rc = set_reg_entry_gpg ("gpgProgram", prog);  
             if (rc)  
                 goto fail;  
             free_if_alloc (prog);  
             return rc;  
         }  
899      }      }
       
     /* Change the return code if homedir doesn't exist or if the program  
        doesn't exist. Note that exist_checks return 0 to suggest existance. */  
     if ((!homedir || dir_exist_check (homedir)))  
         rc = WPTERR_GENERAL;  
       
 fail:  
     free_if_alloc (homedir);  
     free_if_alloc (prog);  
900      return rc;      return rc;
901  } /* gnupg_check_homedir */  }
902    
903    
904  int  int
# Line 912  gnupg_copy_keyrings (void) Line 914  gnupg_copy_keyrings (void)
914          return WPTERR_GENERAL;          return WPTERR_GENERAL;
915      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
916    
917      pring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your public keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
918                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);
919      if (!pring) {      if (!pring) {
920          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("No keyring was chosen. Exit."),
921                     _("WinPT Error"), MB_ERR);
922          free_if_alloc (path);          free_if_alloc (path);
923          return WPTERR_GENERAL;          return WPTERR_GENERAL;
924      }      }
925      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
926      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
927          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old public keyring?"),
928                          "WinPT", MB_INFO|MB_YESNO);
929          if (id == IDNO)          if (id == IDNO)
930              goto fail;              goto fail;
931      }      }
# Line 932  gnupg_copy_keyrings (void) Line 936  gnupg_copy_keyrings (void)
936      }      }
937      free_if_alloc (file);      free_if_alloc (file);
938    
939      sring = get_filename_dlg (hwnd, FILE_OPEN, _("Please choose your secret keyring"),      sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
940                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
941      if (!sring) {      if (!sring) {
942          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          msg_box (NULL, _("No keyring was chosen. Exit."),
943                     _("WinPT Error"), MB_ERR);
944          return WPTERR_GENERAL;          return WPTERR_GENERAL;
945      }      }
946      file = make_filename (path, "secring", "gpg");      file = make_filename (path, "secring", "gpg");
947      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
948          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old secret keyring?"),
949          if( id == IDNO )                        "WinPT", MB_INFO|MB_YESNO);
950            if (id == IDNO)
951              goto fail;              goto fail;
952      }      }
953      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
954          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
955          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
956      }      }
957    
# Line 953  fail: Line 959  fail:
959      free_if_alloc (file);      free_if_alloc (file);
960      free_if_alloc (path);      free_if_alloc (path);
961      return rc;      return rc;
962  } /* gnupg_import_keyrings */  }
963    
964    
965    /* Backup the gpg.conf file. */
966  void  void
967  gnupg_backup_options (void)  gnupg_backup_options (void)
968  {  {
# Line 963  gnupg_backup_options (void) Line 970  gnupg_backup_options (void)
970      char bak[512];      char bak[512];
971    
972      cfgfile = get_gnupg_cfgfile ();      cfgfile = get_gnupg_cfgfile ();
973      if (cfgfile == NULL)      if (!cfgfile)
974          return;          return;
975      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
976      CopyFile (cfgfile, bak, FALSE);      CopyFile (cfgfile, bak, FALSE);
977      free_if_alloc (cfgfile);      free_if_alloc (cfgfile);
978  } /* gnupg_backup_options */  }
   
979    
980    
981  static int  static int
982  backup_one_file (const char *srcpath, const char *srcn,  backup_one_file (const char *srcpath, const char *srcn,
983                   const char *dstpath, const char *dstn)                   const char *dstpath, const char *dstn)
984  {  {
985      char * src, * dst;      char *src, *dst;
986      BOOL rc;      BOOL rc;
987    
988      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
# Line 988  backup_one_file (const char *srcpath, co Line 994  backup_one_file (const char *srcpath, co
994      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
995      free_if_alloc (src);      free_if_alloc (src);
996      free_if_alloc (dst);      free_if_alloc (dst);
997      if (!rc)      if (!rc) {
     {  
998          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
999          return WPTERR_GENERAL;          return WPTERR_GENERAL;
1000      }      }
1001      return 0;      return 0;
1002  } /* backup_one_file */  }
1003    
1004    
1005    /* Figure out first public keyring which is not empty.
1006       Return value: 1 on success. */
1007  static int  static int
1008  check_keyring (char ** r_path)  check_keyring (char **r_path)
1009  {  {
1010      char * p;      char *p;
1011      char * opt, * name;      char *opt;
1012        char *name;
1013    
1014      if (!*r_path)      if (!*r_path)
1015          return 0;          return 0;
1016      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
1017      if (!p || get_file_size (p) > 0)      if (!p || get_file_size (p) <= 0)
1018          return 0;          return 0;
1019    
1020      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
# Line 1018  check_keyring (char ** r_path) Line 1026  check_keyring (char ** r_path)
1026      if (!name)      if (!name)
1027          return 0;          return 0;
1028      p = strrchr (name, '\\');      p = strrchr (name, '\\');
1029      if (!p)      if (!p) {
     {  
1030          free_if_alloc (name);          free_if_alloc (name);
1031          return 0;                return 0;      
1032      }      }
# Line 1032  check_keyring (char ** r_path) Line 1039  check_keyring (char ** r_path)
1039  }  }
1040    
1041    
1042    /* Return a temp name based on the day of the week. */
1043  static char*  static char*
1044  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1045  {  {
1046      struct tm *tm;      struct tm *tm;
1047      char *p;      char *p;
1048        time_t t;
1049    
1050      time_t t = time (NULL);      t = time (NULL);
1051      tm = localtime (&t);      tm = localtime (&t);
1052      p = new char [strlen (templ) + 8 + 1];      p = new char [strlen (templ) + 8 + 1];
1053      if (!p)      if (!p)
# Line 1048  get_backup_name (const char *templ) Line 1057  get_backup_name (const char *templ)
1057  }  }
1058    
1059    
1060    /* Make backups of all keyrings. The public key ring is rotated like
1061       this pubring-%d.gpg.
1062       If @auto_backup is false, no action is performed.
1063       @include_secr indicated if the backup includes the secret keyring. */
1064  void  void
1065  gnupg_backup_keyrings (void)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1066  {  {
1067      char *srcpath = NULL, *dstpath = NULL;      char *srcpath = NULL, *dstpath = NULL;
1068      char *name=NULL;      char *name=NULL;
1069      int rc, bakmode=0;      int rc;
1070    
1071      if (!reg_prefs.auto_backup)      if (!auto_backup)
1072          return;          return;
1073      bakmode = reg_prefs.backup.mode;      srcpath = get_gnupg_path ();
     srcpath =  get_gnupg_path ();  
1074      check_keyring (&srcpath);      check_keyring (&srcpath);
1075      if (bakmode == 1) {      if (backup_mode == 1) {
1076          dstpath = get_gnupg_path ();          dstpath = multi_gnupg_path (1);
1077          check_keyring (&dstpath);          check_keyring (&dstpath);
1078      }      }
1079      else if (bakmode == 2) {      else if (backup_mode == 2) {
1080          char * tmpfile;          char *tmpfile;
1081          FILE * fp;          FILE *fp;
1082    
1083          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
1084          if (!dstpath)          if (!dstpath)
# Line 1080  gnupg_backup_keyrings (void) Line 1092  gnupg_backup_keyrings (void)
1092          else {          else {
1093              rc = 0;              rc = 0;
1094              fclose (fp);              fclose (fp);
1095              unlink (tmpfile);              remove (tmpfile);
1096          }          }
1097          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1098          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL)
1099              return;              return;
1100      }      }
1101      else {      else {
1102          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1103          return;          return;
1104      }      }
1105      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
1106      rc = backup_one_file (srcpath, "pubring", dstpath, name);      rc = backup_one_file (srcpath, "pubring", dstpath, name);
1107      if (!rc)      if (!rc && include_secr)
1108          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1109      free_if_alloc (name);      free_if_alloc (name);
1110      free_if_alloc (srcpath);      free_if_alloc (srcpath);
1111      free_if_alloc (dstpath);      free_if_alloc (dstpath);
1112  } /* gnupg_backup_keyrings */  }
1113    
1114    
1115  /* Display GPG error from file if possible. */  /* Display GPG error from file if possible. */
1116  void  void
1117  gnupg_display_error (void)  gnupg_display_error (void)
1118  {        {      
1119      char tmpath[512], * errstr;      char tmpath[512], *errstr;
1120      size_t size = 0;      size_t size = 0;
1121      FILE * fp;      FILE *fp;
1122    
1123      GetTempPath (sizeof tmpath - 32, (tmpath));      get_temp_name (tmpath, sizeof (tmpath), "gpg_stderr");
     strcat (tmpath, "gpg_stderr");  
1124      size = get_file_size (tmpath);      size = get_file_size (tmpath);
1125      if (file_exist_check (tmpath) || size <= 0)      if (file_exist_check (tmpath) || size <= 0)
1126          return;          return;
1127      fp = fopen( tmpath, "rb" );      fp = fopen( tmpath, "rb" );
1128      if (!fp) {      if (!fp) {
1129          msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );          msg_box (NULL, _("No GPG error description available."),
1130                     _("GPG Error"), MB_INFO);
1131          return;          return;
1132      }      }
1133      errstr = new char[size+1];      errstr = new char[size+1];

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26