/[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 214 by twoaday, Sun May 14 18:40:36 2006 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-2006 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    
# Line 65  static int check_keyring (char ** r_path Line 63  static int check_keyring (char ** r_path
63  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 92  get_gnupg_path (void) Line 90  get_gnupg_path (void)
90      char *path;      char *path;
91    
92      path = get_reg_entry_gpg (GPG_REG_HOME);      path = get_reg_entry_gpg (GPG_REG_HOME);
93      if (path) {      if (path && dir_exist_check (path) == 0)
94          if (dir_exist_check (path) == 0)          return path;
95              return path;      free_if_alloc (path);
96          free_if_alloc (path);      return multi_gnupg_path (1);
     }  
     path = multi_gnupg_path (1);  
     return path;  
97  }  }
98    
99    
# Line 106  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      nlen = strlen (path) + 64;      optfile = make_filename (path, GPG_CONF, NULL);
     optfile = new char[nlen + 1];  
     if (!optfile)  
         BUG (NULL);      
     _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
   
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)
# Line 148  get_gnupg_keyring (int pub, int strict) Line 159  get_gnupg_keyring (int pub, int 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 162  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 189  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;      gpgme_key_t key, pk;
# Line 198  default_key_from_cache (int *ret_no_usea Line 205  default_key_from_cache (int *ret_no_usea
205      char *keyid = NULL;      char *keyid = NULL;
206    
207      sec = keycache_get_ctx (0);      sec = keycache_get_ctx (0);
     if (!sec)  
         BUG (0);  
208      pub = keycache_get_ctx (1);      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)) {
# Line 211  default_key_from_cache (int *ret_no_usea Line 216  default_key_from_cache (int *ret_no_usea
216          }          }
217      }      }
218      if (!keyid)      if (!keyid)
219          *ret_no_useable = 1;              *ret_no_useable = 1;
220      return keyid;      return keyid;
221  }  }
222    
# Line 221  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;
     gpg_optfile_t opt;  
     gpg_option_t o;  
231      char *conf;      char *conf;
232        int rc = 0;
233            
234      conf = get_gnupg_cfgfile ();      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      }      }
241      o = find_option (opt, "ask-cert-level");      free_if_alloc (conf);
242      if (o)      if (conf_find_option (opt, "ask-cert-level"))
243          reg_prefs.gpg.ask_cert_level = 1;          reg_prefs.gpg.ask_cert_level = 1;
244      o = find_option (opt, "ask-cert-expire");      if (conf_find_option (opt, "ask-cert-expire"))
     if (o)  
245          reg_prefs.gpg.ask_cert_expire = 1;          reg_prefs.gpg.ask_cert_expire = 1;
246      release_gpg_options (opt);      /* The 'textmode' option for GPG is useful for text files
247      free_if_alloc (conf);         but it breaks the output of any binary data. Thus we return
248      return 0;         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    
# Line 253  extract_keyid (const char *val) Line 260  extract_keyid (const char *val)
260  {      {    
261      size_t len = strlen (val);      size_t len = strlen (val);
262    
263      if (len > 1 && val[len-1] == '!') {      if (len > 1 && val[len-1] == '!')
264          char *p = new char[len+1];          return substr (val, 0, len-1);
         if (!p)  
             BUG (0);  
         memset (p, 0, len+1);  
         memcpy (p, val, len-1);  
         return p;  
     }  
265      return m_strdup (val);      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        e = conf_find_option (opt, "default-key");
288      if (!e)      if (!e)
289          e = find_option (opt, "local-user");          e = conf_find_option (opt, "local-user");
290      if (e)      if (e)
291          keyid = extract_keyid (e->val);          keyid = extract_keyid (e->val);
292    
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;
# Line 377  check_gnupg_engine (const char *need_gpg Line 383  check_gnupg_engine (const char *need_gpg
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      safe_free (eng);      safe_free (eng);
# Line 404  check_gnupg_engine (const char *need_gpg Line 412  check_gnupg_engine (const char *need_gpg
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;
422    
423      *r_secrings = 0;      *r_secrings = 0;
424      *r_pubrings = 0;      *r_pubrings = 0;
     if (parse_gpg_options (fname, &opt))  
         return WPTERR_FILE_OPEN;  
425    
426        if (parse_config (fname, &opt))
427            return WPTERR_FILE_OPEN;
428      for (e = opt->list; e; e = e->next) {      for (e = opt->list; e; e = e->next) {
429          if (!strcmp( e->name, "secret-keyring")) {          if (!strcmp (e->name, "secret-keyring")) {
430              if (!file_exist_check (e->val))              if (!file_exist_check (e->val))
431                  r_secrings[0]++;                  r_secrings[0]++;
432          }          }
# Line 425  check_gnupg_cfgfile (const char *fname, Line 435  check_gnupg_cfgfile (const char *fname,
435                  r_pubrings[0]++;                  r_pubrings[0]++;
436          }          }
437      }      }
438      release_gpg_options (opt);      release_config (opt);
439      return 0;      return 0;
440  }  }
441    
# Line 476  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 > 0 && pubrings > 0) {              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 */
# Line 497  gnupg_access_files (void) Line 507  gnupg_access_files (void)
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;
# Line 527  get_gnupg_config (void) Line 537  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      }      }
# Line 564  leave: Line 573  leave:
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 WPTERR_FILE_OPEN;          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 WPTERR_GENERAL;          return WPTERR_GENERAL;
588      }      }
589      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
590      if (e && !key)      if (e && !key)
591          e->used = 0;          e->used = 0;
592      else if (e) {      else if (e) {
# Line 586  set_gnupg_default_key (const char *key) Line 595  set_gnupg_default_key (const char *key)
595          e->used = 1;          e->used = 1;
596      }      }
597      else if (key)      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  }  }
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,      if (fd == INVALID_HANDLE_VALUE)
                      OPEN_ALWAYS, 0, NULL);  
     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    
715      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
716          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
717          ctx->modified = 1;          ctx->modified = 1;
718        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
719      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
720          ctx->modified = 0;          ctx->modified = 0;
721    
# Line 708  check_last_gnupg_access (gpg_watcher_s * Line 724  check_last_gnupg_access (gpg_watcher_s *
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 773  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 782  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 819  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.  /* Check the file permissions of the public keyring.
844     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 853  gpg_check_permissions (int showmsg) Line 873  gpg_check_permissions (int showmsg)
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 876  gpg_check_permissions (int showmsg) Line 896  gpg_check_permissions (int showmsg)
896  int  int
897  gnupg_check_homedir (void)  gnupg_check_homedir (void)
898  {        {      
899      char *homedir = NULL;      char *homedir;
900      int val = 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);
908      if (!homedir)      if (!homedir)
909          homedir = multi_gnupg_path (0);          homedir = multi_gnupg_path (0);
# Line 904  gnupg_check_homedir (void) Line 928  gnupg_check_homedir (void)
928  int  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 966  fail: Line 990  fail:
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)      if (!cfgfile)
# Line 986  backup_one_file (const char *srcpath, co Line 1010  backup_one_file (const char *srcpath, co
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);
# Line 1014  check_keyring (char **r_path) Line 1034  check_keyring (char **r_path)
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)
# Line 1044  static char* Line 1064  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;      time_t t;
1070    
1071      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  /* Make backups of all keyrings. The public key ring is rotated like
1083     rotated like this pubring-%d.gpg. */     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 (int auto_backup, int backup_mode)  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;      int rc;
1092    
1093      if (!auto_backup)      if (!auto_backup)
# Line 1071  gnupg_backup_keyrings (int auto_backup, Line 1095  gnupg_backup_keyrings (int auto_backup,
1095      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1096      check_keyring (&srcpath);      check_keyring (&srcpath);
1097      if (backup_mode == 1) {      if (backup_mode == 1) {
1098          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1099               and destination folder will be the same. */
1100            dstpath = get_gnupg_path ();
1101          check_keyring (&dstpath);          check_keyring (&dstpath);
1102      }      }
1103      else if (backup_mode == 2) {      else if (backup_mode == 2) {
# Line 1079  gnupg_backup_keyrings (int auto_backup, Line 1105  gnupg_backup_keyrings (int auto_backup,
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"), backup_mode);          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);
# Line 1110  gnupg_backup_keyrings (int auto_backup, Line 1138  gnupg_backup_keyrings (int auto_backup,
1138  }  }
1139    
1140    
 /* Display GPG error from file if possible. */  
 void  
 gnupg_display_error (void)  
 {        
     char tmpath[512], *errstr;  
     size_t size = 0;  
     FILE *fp;  
   
     get_temp_name (tmpath, sizeof (tmpath), "gpg_stderr");  
     size = get_file_size (tmpath);  
     if (file_exist_check (tmpath) || size <= 0)  
         return;  
     fp = fopen( tmpath, "rb" );  
     if (!fp) {  
         msg_box (NULL, _("No GPG error description available."),  
                  _("GPG Error"), MB_INFO);  
         return;  
     }  
     errstr = new char[size+1];  
     if (!errstr)  
         BUG (0);  
     fread (errstr, 1, size, fp);  
     errstr[size] = '\0';  
     fclose (fp);  
     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);  
     free_if_alloc (errstr);  
 }  
   
   
   
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.214  
changed lines
  Added in v.304

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26