/[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 58 by werner, Wed Nov 2 13:36:03 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 <shlobj.h>  
25  #include <string.h>  #include <string.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <shlobj.h>  #include <shlobj.h>
# Line 40  Line 39 
39  #include "wptW32API.h"  #include "wptW32API.h"
40  #include "wptCrypto.h"  #include "wptCrypto.h"
41    
42  #define GPG_CONF "gpg.conf"  #define GPG_CONF        "gpg.conf"
43    #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
44    #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 177  get_gnupg_prog (void) Line 169  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 200  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 234  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 245  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 264  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 316  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 335  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        gpgme_release (ctx);
390    
391      /* FIXME: This check is wrong! */      if (major > need_major)
     if (major < *r_major || minor < *r_minor)  
         rc = 1;  
     else {  
         if (patch < *r_patch)  
             rc = 1;  
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 381  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 415  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 447  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 456  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 525  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 545  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 627  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 650  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 756  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 768  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 794  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 813  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 916  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 936  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 957  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 967  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 992  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 1022  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 1036  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 1052  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 1084  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.58  
changed lines
  Added in v.222

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26