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

Legend:
Removed from v.73  
changed lines
  Added in v.304

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26