/[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 85 by twoaday, Fri Nov 18 07:20:40 2005 UTC revision 295 by twoaday, Tue Mar 13 18:53:40 2007 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 43  Line 43 
43  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
44  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
45    
46  struct gpg_watcher_s {  /* Context to monitor GPG file changes. */
47      FILETIME    last_access;  struct gpg_monitor_s {
48        FILETIME    last_access;    /* last write access. */
49      FILETIME    access;      FILETIME    access;
50      char        *object;      char        *object;        /* name of the object. */
51      int         modified;      char        *fpath_object;  /* full path to the object. */
52        int         modified;       /* 1 = modified. */
53  };  };
54    typedef struct gpg_monitor_s *gpg_monitor_t;
55    
56    static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
57  /* XXX need to watch for gpg.conf due to the fact keyring entries could be changed */  static gpg_monitor_s gpg_table[3];
 static const char * gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};  
 static gpg_watcher_s gpg_table[3];  
58  static int gpg_table_count = DIM (gpg_table);  static int gpg_table_count = DIM (gpg_table);
59    
60  int idea_available = 0;  int idea_available = 0; /* if the IDEA extension is available. */
61    
62    
63  static int check_keyring (char ** r_path);  static int check_keyring (char ** r_path);
64    
65    
66  /* Return the application data folder of the current user. */  /* Return the application data folder of the current user. */
67  static char*  char*
68  multi_gnupg_path (int strict)  multi_gnupg_path (int strict)
69  {  {
70      static char buf[256+64];      static char buf[MAX_PATH+64];
71      BOOL ec;      BOOL ec;
72    
73      /* MSDN: buf must be at least MAX_PATH=256 bytes */      /* MSDN: buf must be at least MAX_PATH=256 bytes */
# Line 84  multi_gnupg_path (int strict) Line 86  multi_gnupg_path (int strict)
86  }  }
87    
88    
89  /* 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
90     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. */
 */  
91  char*  char*
92  get_gnupg_path (void)  get_gnupg_path (void)
93  {  {
94      char *p = NULL;      char *path;
95      char *path = NULL;  
96            path = get_reg_entry_gpg (GPG_REG_HOME);
97      p = get_reg_entry_gpg (GPG_REG_HOME);      if (path && dir_exist_check (path) == 0)
     if (p) {  
         path = m_strdup (p);  
         free_if_alloc (p);  
98          return path;          return path;
99      }      free_if_alloc (path);
100      else      return multi_gnupg_path (1);
         return multi_gnupg_path (1);  
     return m_strdup ("c:\\gnupg");  
101  }  }
102    
103    
# Line 109  get_gnupg_path (void) Line 105  get_gnupg_path (void)
105     A value of NULL indicates an error. */     A value of NULL indicates an error. */
106  char*  char*
107  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
108  {      {
109      char *p = NULL;      char *optfile;
110      char *optfile = NULL;      char *path;
     char *path = NULL;  
     size_t nlen = 0;  
111    
112      path = get_gnupg_path ();      path = get_gnupg_path ();
113      if (!path)      if (!path)
114          return NULL;          return NULL;
115      p = get_reg_entry_gpg ("OptFile");      optfile = make_filename (path, GPG_CONF, NULL);
     if (p && !strcmp (p, "")) {  
         nlen = strlen (path) + 64;  
         optfile = new char[nlen + 1];  
         if (!optfile)  
             BUG (0);  
         _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
     }  
     else if (p) {  
         nlen = strlen( p ) + 4;  
         optfile = new char[nlen + 1];  
         if (!optfile)  
             BUG (NULL);  
         _snprintf (optfile, nlen, "%s", p);  
     }  
     else {  
         nlen = strlen (path) + 64;  
         optfile = new char[nlen + 1];  
         if( !optfile)  
             BUG (NULL);  
         _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
     }  
116      free_if_alloc (path);      free_if_alloc (path);
117      free_if_alloc (p);  
118      return optfile;      return optfile;
119  }  }
120    
121    
122    static char*
123    get_keyring_from_conf (const char *fname, int pub)
124    {
125        config_file_t opt;
126        conf_option_t e;
127        char *kring = NULL;
128        int rc;
129    
130        rc = parse_config (fname, &opt);
131        if (rc)
132            return NULL;
133        if (pub)
134            e = conf_find_option (opt, "keyring");
135        else
136            e = conf_find_option (opt, "secret-keyring");
137        if (e != NULL)
138            kring = m_strdup (e->val);
139        release_config (opt);
140    
141        return kring;
142    }
143    
144    
145  /* Return the full path of the keyring. If @pub is 1, the public  /* Return the full path of the keyring. If @pub is 1, the public
146     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
147  char*  char*
148  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
149  {      {    
150      char *optfile = NULL;      char *optfile;
151      char *path = NULL;      char *path;
152      char *keyring = NULL;      char *keyring;
153    
154      path = get_gnupg_path ();      path = get_gnupg_path ();
155      if (!path)      if (!path)
156          return NULL;          return NULL;
157      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");      keyring = make_filename (path, pub? "pubring" : "secring", "gpg");
158      if (!strict && !file_exist_check (keyring)) {      if (strict && !file_exist_check (keyring)) {
159            free_if_alloc (path);
160            return keyring;
161        }
162        else if (!strict) {
163          free_if_alloc (path);          free_if_alloc (path);
164          return keyring;          return keyring;
165      }      }
166      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      if (file_exist_check (keyring) ||
167            pub && get_file_size (keyring) == 0) {
168          free_if_alloc (keyring);          free_if_alloc (keyring);
169          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
170          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
171            free_if_alloc (optfile);
172      }      }
173      free_if_alloc (path);      free_if_alloc (path);
174      free_if_alloc (optfile);      
175      return keyring;      return keyring;
176  }  }
177    
# Line 177  get_gnupg_keyring (int pub, int strict) Line 179  get_gnupg_keyring (int pub, int strict)
179  /* 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
180     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
181     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
182  char*  char*
183  get_gnupg_prog (void)  get_gnupg_prog (void)
184  {      {    
185      char *p;      char *path;
186      char *pgm = NULL;      char *pgm;
187    
188      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
189      if (!p) {      if (pgm)
190          char *path = get_gnupg_path ();          return pgm;
191          if (!path)      path = get_gnupg_path ();
192              return NULL;      if (!path)
193          pgm = make_filename (path, "gpg", "exe");          return NULL;    
194          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
195      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
196      return pgm;      return pgm;
197  }  }
198    
# Line 204  get_gnupg_prog (void) Line 200  get_gnupg_prog (void)
200  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
201     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
202     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
203  static char *  static char*
204  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
205  {  {    
206        gpgme_key_t key, pk;
207        gpg_keycache_t sec, pub;
208      const char *s;      const char *s;
209      char *keyid = NULL;      char *keyid = NULL;
     gpgme_key_t key;  
     gpg_keycache_t sec = keycache_get_ctx (0);  
210    
211      if (!sec)      sec = keycache_get_ctx (0);
212          BUG (0);      pub = keycache_get_ctx (1);
213      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
214      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
215          if (key_is_useable (key)) {          if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
216              s = key->subkeys->keyid;              s = key->subkeys->keyid;
217              if (s)                  if (s)
218                  keyid = m_strdup (s+8);                  keyid = m_strdup (s+8);
219              break;              break;
220          }          }
221      }      }
# Line 234  default_key_from_cache (int *ret_no_usea Line 230  default_key_from_cache (int *ret_no_usea
230     Return value: 0 on success. */     Return value: 0 on success. */
231  int  int
232  gnupg_load_config (void)  gnupg_load_config (void)
233  {  {    
234      int rc;      config_file_t opt;
235      gpg_optfile_t opt;      char *conf;
236      gpg_option_t o;      int rc = 0;
237      char *conf = get_gnupg_cfgfile ();      
238        conf = get_gnupg_cfgfile ();
239      if (!conf)      if (!conf)
240          return -1;          return -1;
241      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
242          free_if_alloc (conf);          free_if_alloc (conf);
243          return -1;          return -1;
244      }      }
     o = find_option (opt, "ask-cert-level");  
     if (o)  
         reg_prefs.gpg.ask_cert_level = 1;  
     release_gpg_options (opt);  
245      free_if_alloc (conf);      free_if_alloc (conf);
246      return 0;      if (conf_find_option (opt, "ask-cert-level"))
247            reg_prefs.gpg.ask_cert_level = 1;
248        if (conf_find_option (opt, "ask-cert-expire"))
249            reg_prefs.gpg.ask_cert_expire = 1;
250        /* The 'textmode' option for GPG is useful for text files
251           but it breaks the output of any binary data. Thus we return
252           a warning here to inform the user that binary output is broken. */
253        if (conf_find_option (opt, "textmode"))
254            rc = -2;
255        release_config (opt);
256    
257        return rc;
258  }  }
259    
260    
261    /* handle the case the user added a '!' to force a subkey. */
262    static char*
263    extract_keyid (const char *val)
264    {    
265        size_t len = strlen (val);
266    
267        if (len > 1 && val[len-1] == '!')
268            return substr (val, 0, len-1);
269        return m_strdup (val);
270    }
271    
272    
273    /* Return the default key.
274       This can be either a substring or a key ID. */
275  char*  char*
276  get_gnupg_default_key (void)  get_gnupg_default_key (void)
277  {      {    
278      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
279      gpg_option_t e;      conf_option_t e;
280      char * keyid = NULL, * optfile = NULL;      char *keyid = NULL, *optfile = NULL;
281      int no_usable=0, rc = 0;      int no_usable=0;
282    
283      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
284      if (!optfile)      if (!optfile)
285          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
286      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
287          free_if_alloc (optfile);          free_if_alloc (optfile);
288          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
289      }      }
290      e = find_option( opt, "default-key" );      /* First we search for config entries which specify a default key. */
291      if ( e )      e = conf_find_option (opt, "default-key");
292          keyid = m_strdup( e->val );      if (!e)
293      if( !e ) {          e = conf_find_option (opt, "local-user");
294          e = find_option( opt, "local-user" );      if (e)
295          if( e )          keyid = extract_keyid (e->val);
296              keyid = m_strdup( e->val );  
     }  
     if( !e ) {  
         e = find_option( opt, "encrypt-to" );  
         if( e )  
             keyid = m_strdup( e->val );  
     }  
297      free_if_alloc (optfile);      free_if_alloc (optfile);
298      release_gpg_options (opt);      release_config (opt);
299    
300        /* If no entry in the config has been found, we get a key
301           from the key cache. */
302      if (!keyid)      if (!keyid)
303          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
304      return keyid;      return keyid;
305  } /* get_gnupg_default_key */  }
   
306    
 char* get_reg_entry_gpg4win (const char *path);  
307    
308  /* Check if GPG4WIN is available and if so, use the  /* Check if GPG4WIN is available and if so, use the
309     install path to figure out where the gpg.exe is. */     install path to figure out where the gpg.exe is. */
# Line 326  check_gnupg_prog (void) Line 336  check_gnupg_prog (void)
336    
337    
338  static int  static int
339  parse_version_nr (const char * buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
340  {  {
341      char tmp[8];      char tmp[8];
342      int i;      int i;
# Line 335  parse_version_nr (const char * buf, int Line 345  parse_version_nr (const char * buf, int
345      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
346          tmp[i++] = *buf++;          tmp[i++] = *buf++;
347      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
348      *major = atol( tmp );      *major = atoi (tmp);
349      i=0;      i=0;
350      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
351          tmp[i++] = *buf++;          tmp[i++] = *buf++;
352      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
353      *minor = atol (tmp);      *minor = atoi (tmp);
354      i=0;      i=0;
355      while (buf && isdigit (*buf) && i < 8)      while (buf && isdigit (*buf) && i < 8)
356          tmp[i++] = *buf++;          tmp[i++] = *buf++;
357      tmp[i] = 0;      tmp[i] = 0;
358      *patch = atol (tmp);      *patch = atoi (tmp);
359      return 0;      return 0;
360  }  }
361    
# Line 354  parse_version_nr (const char * buf, int Line 364  parse_version_nr (const char * buf, int
364     version given in @r_major.@r_minor.@r_patch. On success these     version given in @r_major.@r_minor.@r_patch. On success these
365     variables contain the GPG version which is installed. */     variables contain the GPG version which is installed. */
366  int  int
367  check_gnupg_engine (int *r_major, int *r_minor, int *r_patch)  check_gnupg_engine (const char *need_gpg_ver,
368                        int *r_major, int *r_minor, int *r_patch)
369  {  {
370      gpgme_ctx_t ctx;      gpgme_ctx_t ctx;
371      gpgme_engine_info_t inf;      gpgme_engine_info_t inf;
372      char *eng = NULL;      char *eng = NULL;
373      int major=0, minor=0, patch=0;      int major=0, minor=0, patch=0;
374        int need_major = 0, need_minor = 0, need_patch = 0;
375      int rc = 1;      int rc = 1;
376            
377        /* Convert the needed GPG version to the integer format. */
378        if (parse_version_nr (need_gpg_ver,
379                              &need_major, &need_minor, &need_patch))
380            return 1;
381        
382      gpgme_new (&ctx);      gpgme_new (&ctx);
383      inf = gpgme_ctx_get_engine_info (ctx);      inf = gpgme_ctx_get_engine_info (ctx);
384      if (!inf) {      if (!inf) {
# Line 370  check_gnupg_engine (int *r_major, int *r Line 387  check_gnupg_engine (int *r_major, int *r
387      }      }
388    
389      /* 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. */
390      if (gpg_get_version (&eng))      if (gpg_get_version (&eng)) {
391            gpgme_release (ctx);
392          return -1;          return -1;
393        }
394      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
395          idea_available = 1;          idea_available = 1;
396      free (eng);      safe_free (eng);
397      rc = parse_version_nr (inf->version, &major, &minor, &patch);      if (parse_version_nr (inf->version, &major, &minor, &patch)) {
     if (rc) {  
398          gpgme_release (ctx);          gpgme_release (ctx);
399          return rc;          return 1;
400      }      }
401        gpgme_release (ctx);
402    
403      if (major > *r_major)      if (major > need_major)
404          rc = 0;          rc = 0;
405      else if (major == *r_major && minor > *r_minor)                else if (major == need_major && minor > need_minor)      
406          rc = 0;          rc = 0;
407      else if (major == *r_major && minor == *r_minor &&      else if (major == need_major && minor == need_minor &&
408               patch >= *r_patch)               patch >= need_patch)
409          rc = 0;          rc = 0;
410    
411        /* Return the current GPG version. */
412      *r_major = major;      *r_major = major;
413      *r_minor = minor;      *r_minor = minor;
414      *r_patch = patch;      *r_patch = patch;
# Line 396  check_gnupg_engine (int *r_major, int *r Line 416  check_gnupg_engine (int *r_major, int *r
416  }  }
417    
418    
419  int  /* Count the keyring entries in the gpg.conf file.
420  check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)     Return value: 0 on success. */
421    static int
422    cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
423  {  {
424      gpg_optfile_t opt;          config_file_t opt;    
425      gpg_option_t e;      conf_option_t e;
     int rc = 0;  
426    
427      *r_secrings = 0;      *r_secrings = 0;
428      *r_pubrings = 0;      *r_pubrings = 0;
     rc = parse_gpg_options( fname, &opt );  
     if( rc )  
         return WPTERR_FILE_OPEN;  
429    
430      for( e = opt->list; e; e = e->next ) {      if (parse_config (fname, &opt))
431          if( !strcmp( e->name, "secret-keyring" ) ) {          return WPTERR_FILE_OPEN;
432              if( !file_exist_check( e->val ) )      for (e = opt->list; e; e = e->next) {
433            if (!strcmp (e->name, "secret-keyring")) {
434                if (!file_exist_check (e->val))
435                  r_secrings[0]++;                  r_secrings[0]++;
436          }          }
437          else if( !strcmp( e->name, "keyring" ) ) {          else if (!strcmp (e->name, "keyring")) {
438              if( !file_exist_check( e->val ) )              if (!file_exist_check (e->val))
439                  r_pubrings[0]++;                  r_pubrings[0]++;
440          }          }
441      }      }
442      release_gpg_options( opt );      release_config (opt);
443      return 0;      return 0;
444  } /* check_gnupg_cfgfile */  }
445    
446    
447  /*  /* Usually GPG creates the pubring.gpg, secring.gpg on
448   * Check if both keyrings are located in the gnupg home directory.     the first start, but to make sure they always exist
449   */     create them empty if needed. */
450    static void
451    create_empty_keyring (int _pub)
452    {
453        char *name;
454        FILE *fp;
455    
456        name = get_gnupg_keyring (_pub, 0);
457        if (name && file_exist_check (name) != 0) {
458            fp = fopen (name, "ab");
459            if (fp != NULL)
460                fclose (fp);
461        }
462        free_if_alloc (name);
463    }
464    
465    
466    /* Check if both keyrings are located in the gnupg home directory. */
467  int  int
468  gnupg_access_files (void)  gnupg_access_files (void)
469  {  {
# Line 435  gnupg_access_files (void) Line 472  gnupg_access_files (void)
472      int secrings = 0, pubrings = 0;      int secrings = 0, pubrings = 0;
473      char *optfile;      char *optfile;
474    
475        create_empty_keyring (1);
476      if (gnupg_access_keyring (1))      if (gnupg_access_keyring (1))
477          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
478      else      else
479          pubring_ok = 1;          pubring_ok = 1;
480    
481        create_empty_keyring (0);
482      if (gnupg_access_keyring (0))      if (gnupg_access_keyring (0))
483          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
484      else      else
# Line 451  gnupg_access_files (void) Line 490  gnupg_access_files (void)
490              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
491          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
492          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
493              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
494              if (!rc && secrings && pubrings) {              if (!rc && secrings > 0 && pubrings > 0) {
495                  free_if_alloc (optfile);                  free_if_alloc (optfile);
496                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
497              }              }
# Line 468  gnupg_access_files (void) Line 507  gnupg_access_files (void)
507          rc = WPTERR_GPG_KEYRINGS;          rc = WPTERR_GPG_KEYRINGS;
508      }      }
509      return rc;      return rc;
510  } /* gnupg_access_files */  }
511    
512    
513  static int  static int
514  create_gpg_options (void)  create_gpg_conf (void)
515  {  {
516      FILE *fp;      FILE *fp;
517      char *s, *optfile;      char *s, *optfile;
518    
519      s = get_gnupg_path ();      s = get_gnupg_path ();
520      if( s == NULL )      if (!s)
521          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
522      optfile = make_filename (s, GPG_CONF, NULL);      optfile = make_filename (s, GPG_CONF, NULL);
523      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
524      if( fp == NULL ) {        if (!fp) {
525          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
526          goto fail;          goto fail;
527      }      }
528      fwrite( options_skel, 1, strlen( options_skel ), fp );      fwrite (options_skel, 1, strlen (options_skel), fp);
529      fclose( fp );      fclose (fp);
530    
531  fail:  fail:
532      free_if_alloc( s );      free_if_alloc (s);
533      free_if_alloc( optfile );      free_if_alloc (optfile);
534      return 0;      return 0;
535  } /* create_gpg_options */  }
536    
537    
538  /*  /* Return the contents of the options file as a char buf. */
539   * Return the contents of the options file as a char buf.  char*
  */  
 char *  
540  get_gnupg_config (void)  get_gnupg_config (void)
541  {  {
542      FILE * fp;      FILE *fp;
543      char * p = NULL, * optfile = NULL;      char *p = NULL, *optfile = NULL;
544      int fsize, rc = 0;      int fsize;
545                    
546      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
547      if( optfile == NULL )      if (!optfile)
548          return NULL;          return NULL;
549      fsize = get_file_size( optfile );      fsize = get_file_size (optfile);
550      if( !fsize ) {      if (!fsize) {
551          rc = create_gpg_options( );          if (create_gpg_conf ())
         if ( rc )  
552              return NULL;              return NULL;
553          fsize = get_file_size( optfile );          fsize = get_file_size (optfile);
554      }      }
555      if( fsize > 100000 )      if (fsize > 100000)
556          goto leave; /* too large */          goto leave; /* too large */
557      p = new char[fsize+1];      p = new char[fsize+1];
558      if( p == NULL )      if (!p)
559          BUG( NULL );          BUG (NULL);
560      fp = fopen( optfile, "rb" );      fp = fopen( optfile, "rb" );
561      if( fp == NULL ) {      if (!fp) {
562          free_if_alloc( p );          free_if_alloc (p);
563          return NULL;          return NULL;
564      }      }
565      fread( p, 1, fsize, fp );      fread (p, 1, fsize, fp);
566      fclose( fp );      fclose (fp);
567      p[fsize] = '\0';      p[fsize] = '\0';
568      free_if_alloc( optfile );      free_if_alloc (optfile);
569    
570  leave:  leave:
571      return p;      return p;
572  } /* get_gnupg_config */  }
573    
574    
575    /* Set the default key in the gpg.conf.
576       If @key is NULL, the entry will be deleted. */
577  int  int
578  set_gnupg_default_key (const char * key)  set_gnupg_default_key (const char *key)
579  {  {
580      gpg_optfile_t opt;      config_file_t opt;
581      gpg_option_t e;      conf_option_t e;
582      char *optfile = NULL;      char *optfile = NULL;
583      int rc = 0;      int rc = 0;
584    
585      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
586      if (!optfile)      if (!optfile)
587          return -1;          return WPTERR_FILE_OPEN;
588      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
589      if( rc ) {      if (rc) {
590          free_if_alloc (optfile);          free_if_alloc (optfile);
591          return -1;          return WPTERR_GENERAL;
592      }      }
593      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
594      if (e) {      if (e && !key)
595            e->used = 0;
596        else if (e) {
597          free_if_alloc (e->val);          free_if_alloc (e->val);
598          e->val = m_strdup (key);          e->val = m_strdup (key);
599          e->used = 1;          e->used = 1;
600      }      }
601      else      else if (key)
602          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
603      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
604    
605      free_if_alloc (optfile);      free_if_alloc (optfile);
606      release_gpg_options (opt);      release_config (opt);
   
607      return rc;      return rc;
608  } /* set_gnupg_default_key */  }
609    
610    
611  /*  /* Set the contents of the options file. */
  * Set the contents of the options file.  
  */  
612  int  int
613  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
614  {  {
615      FILE *fp;        FILE *fp;  
616      char *optfile = NULL;      char *optfile;
617    
618      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
619      if( optfile == NULL )      if (!optfile)
620          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
621    
622      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
623      if( fp == NULL ) {      if (!fp) {
624          free_if_alloc( optfile );          free_if_alloc (optfile);
625          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
626      }      }
627      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
628      fclose( fp );      fclose (fp);
629      free_if_alloc( optfile );      free_if_alloc (optfile);
630      return 0;      return 0;
631  } /* set_gnupg_options */  }
632    
633  /*  
634   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
635   */     Return value: 0 on success. */
636    static int
637    check_arg_file_exist (const char *buf)
638    {
639        const char *s = "load-extension ";
640    
641        /* XXX: this is a bit of a kludge because we just
642                detect errors for 'load-extension'. */
643        if (!strncmp (buf, s, strlen (s)))
644            buf += strlen (s);
645        else
646            return 0;
647        return file_exist_check (buf);
648    }
649    
650    
651    /* Check if the line contains a valid GPG argument. */
652  static int  static int
653  check_line( const char *buf )  check_line (const char *buf)
654  {  {
655      int j, len;      int j, len;
656      int rc = 0;      int rc = 0;
657    
658      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
659          return 1;          return 1;
660      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
661      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
662          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
663          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
664      }      }
   
665      return rc;      return rc;
666  } /* check_line */  }
667    
668    
669  int  int
670  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
671  {  {
672      char line[1024];      char line[1024];
673      int nbytes = 0;      int nbytes = 0, lineno=0;
674      unsigned j;      unsigned j;
675                    
676      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
677          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
678          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
679              line[nbytes] = '\0';              line[nbytes] = '\0';
680              if( !check_line( line ) ) {              lineno++;
681                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
682                    if (showerr)
683                        log_box ("GPG Config File", MB_ERR,
684                                 "gpg.conf:%d: invalid keyword '%s'",
685                                 lineno, line);
686                  return 1;                        return 1;      
687              }              }
688                if (check_arg_file_exist (line))
689                    return WPTERR_FILE_EXIST;
690              nbytes = 0;              nbytes = 0;
691          }                }
692      }      }
   
693      return 0;      return 0;
694  } /* check_gnupg_options */  }
695    
696    
697  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
698  static int  static int
699  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
700  {  {
701      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
702    
703      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
704      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
705      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);      if (fd == INVALID_HANDLE_VALUE)
     if (fd == INVALID_HANDLE_VALUE) {  
         free_if_alloc (path);  
         free_if_alloc (file);  
706          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
707      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
708      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
709      return 0;      return 0;
710  }  }
711    
712    
713  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
714  static void  static void
715  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
716  {                {              
717      ctx->modified = 0;      ctx->modified = 0;
718    
719      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
720          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
721          ctx->modified = 1;          ctx->modified = 1;
722        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice otherwise. */  
723      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
724          ctx->modified = 0;          ctx->modified = 0;
725        
726      ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;      ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime;
727      ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;      ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime;
728  }  }
729    
730    
731  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
732  void  void
733  init_gnupg_table (void)  init_gnupg_table (void)
734  {        {      
735      char *p;      char *path;
736      int j;      int j;
737    
738        path = get_gnupg_path ();
739      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
740          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
741          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
742          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
743          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
744          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
745      }      }
746        free_if_alloc (path);
747  }  }
748    
749    
750    /* Release the GPG monitor table. */
751  void  void
752  free_gnupg_table (void)  free_gnupg_table (void)
753  {  {
754      int j;      int j;
755    
756      for (j=0; j < gpg_table_count; j++)      for (j=0; j < gpg_table_count; j++) {
757          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
758            free_if_alloc (gpg_table[j].fpath_object);
759        }
760  }  }
761    
762    
763  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
764  int  int
765  keyring_check_last_access (void)  keyring_check_last_access (void)
766  {        {
767      int rc, j;      int nfiles;
768        int pos;
769    
770      rc = 0;      nfiles = 0;
771      for (j = 0; j < gpg_table_count; j++) {      for (pos = 0; pos < gpg_table_count; pos++) {
772          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
773          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
774          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
775              rc++;                    nfiles++;
776      }      }
777    
778      return rc;      return nfiles;
779  }  }
780    
781    
# Line 747  gnupg_check_file_ext (const char *fname, Line 798  gnupg_check_file_ext (const char *fname,
798              *r_type = PGP_SIG;              *r_type = PGP_SIG;
799          return "SIGNED";          return "SIGNED";
800      }      }
801      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
802                  !stricmp (file_ext, ".pgp")) {
803          if (r_type)          if (r_type)
804              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
805          return "ENCRYPTED";          return "ENCRYPTED";
# Line 756  gnupg_check_file_ext (const char *fname, Line 808  gnupg_check_file_ext (const char *fname,
808  }  }
809    
810    
811  char*  /* Check if the device where file @fname is stored on, is write-protected. */
 get_gnupg_keyring_from_options (const char * fname, int pub)  
 {  
     gpg_optfile_t opt;  
     gpg_option_t e;  
     char * kring = NULL;  
     int rc = 0;  
   
     rc = parse_gpg_options (fname, &opt);  
     if (rc)  
         return NULL;  
     if (pub)  
         e = find_option (opt, "keyring");  
     else  
         e = find_option (opt, "secret-keyring");  
     if (e)  
         kring = m_strdup (e->val);  
     release_gpg_options (opt);  
   
     return kring;  
 }  
   
   
   
 /* XXX: does not work with write-protected floppies */  
812  static int  static int
813  my_access (const char * fname)  check_file_access (const char *fname, int mode)
814  {  {
815      HANDLE hd;      HANDLE hd;
816      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,  
817        if (!mode)
818            mode = FILE_SHARE_WRITE;
819        hd = CreateFile (fname, GENERIC_WRITE, mode,
820                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
821      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
822          return -1;          return -1;
# Line 793  my_access (const char * fname) Line 824  my_access (const char * fname)
824      return 0;      return 0;
825  }  }
826    
827        
828    /* Check the device where the file @fname is stored on, is either
829       write-protected or if the file is already opened by another process
830       exclusively. And as a result, we cannot use the file for output. */
831    int
832    gpg_check_file_permissions (const char *fname, int mode)
833    {
834        int api_mode;
835        
836        switch (mode) {
837        case 0: api_mode = FILE_SHARE_READ; break;
838        case 1: api_mode = FILE_SHARE_WRITE; break;
839        case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
840        }
841    
842        return check_file_access (fname, api_mode);
843    }
844    
845    
846  /* Check the file permissions of the public keyring.  /* Check the file permissions of the public keyring.
847     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 801  my_access (const char * fname) Line 850  my_access (const char * fname)
850  int  int
851  gpg_check_permissions (int showmsg)  gpg_check_permissions (int showmsg)
852  {  {
853      char * p, * name = NULL;      char *p = NULL;
854        char *name = NULL;
855      int failed = 0, ans=0, attrs=0;      int failed = 0, ans=0, attrs=0;
856    
857      p = get_gnupg_path ();      p = get_gnupg_path ();
858      check_keyring (&p);      if (p && check_keyring (&p)) {
     if (p) {  
859          name = make_filename (p, "pubring", "gpg");          name = make_filename (p, "pubring", "gpg");
         free_if_alloc (p);  
860          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
861              ans = msg_box (NULL,              ans = msg_box (NULL,
862                             _("The selected keyring has the read-only file\n"                             _("The selected keyring has the read-only file\n"
# Line 828  gpg_check_permissions (int showmsg) Line 876  gpg_check_permissions (int showmsg)
876                  failed = 1;                  failed = 1;
877              }              }
878          }          }
879          if (my_access (name)) {          if (gpg_check_file_permissions (name, 1)) {
880              if (showmsg)              if (showmsg)
881                  msg_box (NULL,                  msg_box (NULL,
882                  _("You do not have file access to modify the contents of\n"                  _("You do not have file access to modify the contents of\n"
# Line 840  gpg_check_permissions (int showmsg) Line 888  gpg_check_permissions (int showmsg)
888              failed = 2;              failed = 2;
889          }          }
890      }      }
891        free_if_alloc (p);
892      free_if_alloc (name);      free_if_alloc (name);
893      return failed;      return failed;
894  }  }
895    
896    
897  /* Check the GPG home dir. If all methods failed, try to  /* Check the GPG home dir. First try to read the 'HomeDir' registry entry,
898     create the default folder. */     then check for $APPDATA\gnupg. Create the dir if it does not exists. */
899  static int  int
900  check_homedir (void)  gnupg_check_homedir (void)
901  {        {      
902      char *homedir = NULL;      char *homedir;
903      int yes = 0, set_reg=0;      int val;
904      int rc = 0;      int rc = 0;
905    
906    #ifdef WINPT_MOBILE
907        return 0;
908    #endif
909    
910      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
     if (!homedir) {  
         set_reg = 1;  
         homedir = multi_gnupg_path (0);  
     }  
911      if (!homedir)      if (!homedir)
912          homedir = m_strdup ("c:\\gnupg");          homedir = multi_gnupg_path (0);
913      if (homedir) {      if (homedir) {
914          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {          if (GetFileAttributes (homedir) == 0xFFFFFFFF) {
915              yes = log_box (_("Preferences"), MB_YESNO,              val = log_box (_("Preferences"), MB_YESNO,
916                             _("%s does not exit.\n"                             _("%s does not exit.\n"
917                               "Do you want to create this directory?"), homedir);                               "Do you want to create this directory?"), homedir);
918              if (yes == IDYES) {              if (val == IDYES) {
919                  if (!CreateDirectory (homedir, NULL))                  if (!CreateDirectory (homedir, NULL))
920                      rc = WPTERR_DIR_CREAT;                      rc = WPTERR_DIR_CREAT;
921              }              }
922              else              else
923                  rc = WPTERR_DIR_OPEN;                  rc = WPTERR_DIR_OPEN;
924          }          }
         if (set_reg)  
             set_reg_entry_gpg (GPG_REG_HOME, homedir);  
925          free_if_alloc (homedir);          free_if_alloc (homedir);
926      }      }
927      return rc;      return rc;
# Line 882  check_homedir (void) Line 929  check_homedir (void)
929    
930    
931  int  int
 gnupg_check_homedir (void)  
 {        
     char *homedir = NULL;  
     char *prog = NULL;  
     int rc = 0;  
       
     rc = check_homedir ();  
     if (rc)  
         return rc;  
     if ((homedir = get_reg_entry_gpg (GPG_REG_HOME)) &&  
         !(prog = get_reg_entry_gpg (GPG_REG_EXE ))) {  
         prog = make_filename (homedir, "gpg", "exe");  
         if (file_exist_check (prog) == 0) {  
             rc = set_reg_entry_gpg (GPG_REG_EXE, prog);  
             if (rc)  
                 goto fail;  
         }  
         free_if_alloc (homedir);  
         free_if_alloc (prog);  
         return rc;  
     }  
     if ((prog = get_reg_entry_gpg (GPG_REG_EXE))  
         && file_exist_check (prog)) {  
         free_if_alloc (prog);  
         homedir = get_reg_entry_gpg (GPG_REG_HOME);  
         if (!homedir) {  
             rc = WPTERR_GENERAL;  
             goto fail;  
         }  
         prog = make_filename (homedir, "gpg", "exe");  
         if (file_exist_check (prog) == 0) {  
             rc = set_reg_entry_gpg (GPG_REG_EXE, prog);  
             if (rc)  
                 goto fail;  
             free_if_alloc (prog);  
             return rc;  
         }  
     }  
       
     /* Change the return code if homedir doesn't exist or if the program  
        doesn't exist. Note that exist_checks return 0 to suggest existance. */  
     if ((!homedir || dir_exist_check (homedir)))  
         rc = WPTERR_GENERAL;  
       
 fail:  
     free_if_alloc (homedir);  
     free_if_alloc (prog);  
     return rc;  
 } /* gnupg_check_homedir */  
   
   
 int  
932  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
933  {  {
934      const char * pring, * sring;      const char *pring, *sring;
935      char * file = NULL, * path = NULL;      char *file = NULL, *path = NULL;
936      int id = 0, rc = 0;      int id = 0, rc = 0;
937      HWND hwnd;      HWND hwnd;
938            
# Line 946  gnupg_copy_keyrings (void) Line 941  gnupg_copy_keyrings (void)
941          return WPTERR_GENERAL;          return WPTERR_GENERAL;
942      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
943    
944      pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
945                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);
946      if (!pring) {      if (!pring) {
947          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("No keyring was chosen. Exit."),
948                     _("WinPT Error"), MB_ERR);
949          free_if_alloc (path);          free_if_alloc (path);
950          return WPTERR_GENERAL;          return WPTERR_GENERAL;
951      }      }
952      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
953      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
954          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old public keyring?"),
955                          "WinPT", MB_INFO|MB_YESNO);
956          if (id == IDNO)          if (id == IDNO)
957              goto fail;              goto fail;
958      }      }
# Line 966  gnupg_copy_keyrings (void) Line 963  gnupg_copy_keyrings (void)
963      }      }
964      free_if_alloc (file);      free_if_alloc (file);
965    
966      sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),      sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
967                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
968      if (!sring) {      if (!sring) {
969          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          msg_box (NULL, _("No keyring was chosen. Exit."),
970                     _("WinPT Error"), MB_ERR);
971          return WPTERR_GENERAL;          return WPTERR_GENERAL;
972      }      }
973      file = make_filename (path, "secring", "gpg");      file = make_filename (path, "secring", "gpg");
974      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
975          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old secret keyring?"),
976          if( id == IDNO )                        "WinPT", MB_INFO|MB_YESNO);
977            if (id == IDNO)
978              goto fail;              goto fail;
979      }      }
980      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
981          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
982          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
983      }      }
984    
# Line 987  fail: Line 986  fail:
986      free_if_alloc (file);      free_if_alloc (file);
987      free_if_alloc (path);      free_if_alloc (path);
988      return rc;      return rc;
989  } /* gnupg_import_keyrings */  }
990    
991    
992    /* Backup the gpg.conf file. */
993  void  void
994  gnupg_backup_options (void)  gnupg_backup_options (void)
995  {  {
996      char *cfgfile = NULL;      char *cfgfile;
997      char bak[512];      char bak[MAX_PATH+32];
998    
999      cfgfile = get_gnupg_cfgfile ();      cfgfile = get_gnupg_cfgfile ();
1000      if (cfgfile == NULL)      if (!cfgfile)
1001          return;          return;
1002      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
1003      CopyFile (cfgfile, bak, FALSE);      CopyFile (cfgfile, bak, FALSE);
1004      free_if_alloc (cfgfile);      free_if_alloc (cfgfile);
1005  } /* gnupg_backup_options */  }
   
1006    
1007    
1008  static int  static int
1009  backup_one_file (const char *srcpath, const char *srcn,  backup_one_file (const char *srcpath, const char *srcn,
1010                   const char *dstpath, const char *dstn)                   const char *dstpath, const char *dstn)
1011  {  {
1012      char * src, * dst;      char *src, *dst;
1013      BOOL rc;      BOOL rc;
1014    
1015      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
1016      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
1017      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
1018      free_if_alloc (src);      free_if_alloc (src);
1019      free_if_alloc (dst);      free_if_alloc (dst);
1020      if (!rc)      if (!rc) {
     {  
1021          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1022          return WPTERR_GENERAL;          return WPTERR_GENERAL;
1023      }      }
1024      return 0;      return 0;
1025  } /* backup_one_file */  }
1026    
1027    
1028    /* Figure out first public keyring which is not empty.
1029       Return value: 1 on success. */
1030  static int  static int
1031  check_keyring (char ** r_path)  check_keyring (char **r_path)
1032  {  {
1033      char * p;      char *p;
1034      char * opt, * name;      char *opt;
1035        char *name;
1036    
1037      if (!*r_path)      if (!*r_path)
1038          return 0;          return 0;
1039      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
1040      if (!p || get_file_size (p) > 0)      if (get_file_size (p) <= 0)
1041          return 0;          return 0;
1042    
1043      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
1044      if (!opt)      if (!opt)
1045          BUG (0);          BUG (0);
1046      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
1047      free_if_alloc (opt);      free_if_alloc (opt);
1048      free_if_alloc (p);      free_if_alloc (p);
1049      if (!name)      if (!name)
1050          return 0;          return 0;
1051      p = strrchr (name, '\\');      p = strrchr (name, '\\');
1052      if (!p)      if (!p) {
     {  
1053          free_if_alloc (name);          free_if_alloc (name);
1054          return 0;                return 0;      
1055      }      }
# Line 1066  check_keyring (char ** r_path) Line 1062  check_keyring (char ** r_path)
1062  }  }
1063    
1064    
1065    /* Return a temp name based on the day of the week. */
1066  static char*  static char*
1067  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1068  {  {
1069      struct tm *tm;      struct tm *tm;
1070        const char *fmt;
1071      char *p;      char *p;
1072        time_t t;
1073    
1074      time_t t = time (NULL);      t = time (NULL);
1075      tm = localtime (&t);      tm = localtime (&t);
1076      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1077        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1078      if (!p)      if (!p)
1079          BUG (0);          BUG (0);
1080      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1081      return p;      return p;
1082  }  }
1083    
1084    
1085    /* Make backups of all keyrings. The public key ring is rotated like
1086       this pubring-%d.gpg.
1087       If @auto_backup is false, no action is performed.
1088       @include_secr indicated if the backup includes the secret keyring. */
1089  void  void
1090  gnupg_backup_keyrings (void)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1091  {  {
1092      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1093      char *name=NULL;      char *name;
1094      int rc, bakmode=0;      int rc;
1095    
1096      if (!reg_prefs.auto_backup)      if (!auto_backup)
1097          return;          return;
1098      bakmode = reg_prefs.backup.mode;      srcpath = get_gnupg_path ();
     srcpath =  get_gnupg_path ();  
1099      check_keyring (&srcpath);      check_keyring (&srcpath);
1100      if (bakmode == 1) {      if (backup_mode == 1) {
1101            /* If the backup mode uses the home directory the source
1102               and destination folder will be the same. */
1103          dstpath = get_gnupg_path ();          dstpath = get_gnupg_path ();
1104          check_keyring (&dstpath);          check_keyring (&dstpath);
1105      }      }
1106      else if (bakmode == 2) {      else if (backup_mode == 2) {
1107          char * tmpfile;          char *tmpfile;
1108          FILE * fp;          FILE *fp;
1109    
1110          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1111          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1112          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1113          if (!fp)          if (!fp)
1114              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1115                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1116                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1117          else {          else {
1118              rc = 0;              rc = 0;
1119              fclose (fp);              fclose (fp);
1120              remove (tmpfile);              DeleteFile (tmpfile);
1121          }          }
1122          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1123          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1124                free_if_alloc (dstpath);
1125                free_if_alloc (srcpath);
1126              return;              return;
1127            }
1128      }      }
1129      else {      else {
1130          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1131            free_if_alloc (srcpath);
1132          return;          return;
1133      }      }
1134      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
1135      rc = backup_one_file (srcpath, "pubring", dstpath, name);      rc = backup_one_file (srcpath, "pubring", dstpath, name);
1136      if (!rc)      if (!rc && include_secr)
1137          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1138      free_if_alloc (name);      free_if_alloc (name);
1139      free_if_alloc (srcpath);      free_if_alloc (srcpath);
1140      free_if_alloc (dstpath);      free_if_alloc (dstpath);
 } /* gnupg_backup_keyrings */  
   
   
 /* Display GPG error from file if possible. */  
 void  
 gnupg_display_error (void)  
 {        
     char tmpath[512], * errstr;  
     size_t size = 0;  
     FILE * fp;  
   
     GetTempPath (sizeof tmpath - 32, (tmpath));  
     strcat (tmpath, "gpg_stderr");  
     size = get_file_size (tmpath);  
     if (file_exist_check (tmpath) || size <= 0)  
         return;  
     fp = fopen( tmpath, "rb" );  
     if (!fp) {  
         msg_box( NULL, _("No GPG error description available."), _("GPG Error"), MB_INFO );  
         return;  
     }  
     errstr = new char[size+1];  
     if (!errstr)  
         BUG (0);  
     fread (errstr, 1, size, fp);  
     errstr[size] = '\0';  
     fclose (fp);  
     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);  
     free_if_alloc (errstr);  
1141  }  }
1142    
1143    
   
1144  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1145     Return value: 0 for success. */     Return value: 0 for success. */
1146  int  int

Legend:
Removed from v.85  
changed lines
  Added in v.295

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26