/[winpt]/trunk/Src/WinPT.cpp
ViewVC logotype

Diff of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 32 by twoaday, Mon Oct 24 08:03:48 2005 UTC revision 271 by twoaday, Sun Nov 5 08:57:45 2006 UTC
# Line 1  Line 1 
1  /* WinPT.cpp - Windows Privacy Tray (WinPT)  /* WinPT.cpp - Windows Privacy Tray (WinPT)
2   *      Copyright (C) 2000-2005 Timo Schulz   *      Copyright (C) 2000-2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
6   * WinPT is free software; you can redistribute it and/or modify   * WinPT is free software; you can redistribute it and/or modify
7   * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
8   * the Free Software Foundation; either version 2 of the License, or   * the Free Software Foundation; either version 2 of the License, or
9   * (at your option) any later version.   * (at your option) any later version.
10   *   *
11   * WinPT is distributed in the hope that it will be useful,   * WinPT is distributed in the hope that it will be useful,
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   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.   * GNU General Public License for more details.
15   *   *
16   * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
17   * along with WinPT; if not, write to the Free Software Foundation,   * along with WinPT; if not, write to the Free Software Foundation,
18   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19   */   */
20  #include <windows.h>  #ifdef HAVE_CONFIG_H
21    #include <config.h>
22  #include "../resource.h"  #endif
23  #include "wptTypes.h"  
24  #include "wptW32API.h"  #include <windows.h>
25  #include "wptVersion.h"  #include <shlobj.h>
26  #include "wptErrors.h"  
27  #include "wptGPG.h"  #include "resource.h"
28  #include "wptRegistry.h"  #include "wptTypes.h"
29  #include "wptCommonCtl.h"  #include "wptW32API.h"
30  #include "wptDlgs.h"  #include "wptVersion.h"
31  #include "wptNLS.h"  #include "wptErrors.h"
32  #include "wptKeyserver.h"  #include "wptGPG.h"
33  #include "wptCard.h"  #include "wptRegistry.h"
34  #include "wptFileManager.h"  #include "wptCommonCtl.h"
35  #include "wptContext.h"  #include "wptDlgs.h"
36  #include "wptCardEdit.h"  #include "wptNLS.h"
37    #include "wptKeyserver.h"
38    #include "wptCard.h"
39  #define MIN_GPG_VER   "1.4.3"   /* Minimal GPG version. */  #include "wptFileManager.h"
40  #define MIN_GPGME_VER "1.2.0"   /* Minimal GPGME version. */  #include "wptContext.h"
41  #define MIN_PTD_VER   "0.8.1"   /* Minimal PTD version. */  #include "wptCardEdit.h"
42    #include "wptCrypto.h"
43    #include "wptUTF8.h"
44  HINSTANCE glob_hinst;   /* global instance for the dialogs */  
45  HWND glob_hwnd;         /* global window handle for the dialogs */  void remove_crit_file_attrs (const char *fname, int force);
46  HWND activ_hwnd;  BOOL user_is_admin (void);
47  LOCK mo_file;  extern "C" int  pcsc_available (void);
48  int scard_support = 0;  
49  int debug = 0;  /* Global variables. */
50  int mobile = 0;  HINSTANCE glob_hinst;   /* global instance for the dialogs */
51  int gpg_read_only = 0;  HWND glob_hwnd;         /* global window handle for the dialogs */
52  char gpgver[3];  int scard_support = 0;
53    int debug = 0;
54    int gpg_read_only = 0;
55  /* Load the key cache and rebuild the signature cache. */  int admin_user = 0;
56  static void  char gpgver[3];
57  update_keycache (HWND hwnd)  /* End */
58  {  
59      refresh_cache_s rcs = {0};  
60      rcs.kr_reload = 0;  /* Load the key cache and rebuild the signature cache. */
61      rcs.kr_update = 1;  int
62      rcs.tr_update = 1;  update_keycache (HWND hwnd)
63      DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,  {
64                      keycache_dlg_proc, (LPARAM)&rcs);      int err;
65  }  
66        refresh_cache_s rcs = {0};
67        rcs.kr_reload = 0;
68  /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */      rcs.kr_update = 1;
69  void      rcs.tr_update = 1;
70  gpg_set_debug_mode (int val)      err = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,
71  {                            keycache_dlg_proc, (LPARAM)&rcs);
72      if (val)      if (err) {
73          putenv ("GPGME_DEBUG=5:gpgme.dbg");          char *cfgf = get_gnupg_config ();
74      else          if (cfgf && check_gnupg_options (cfgf, 0) == WPTERR_FILE_EXIST)
75          putenv ("GPGME_DEBUG=");              msg_box (NULL, _("The gpg.conf contains at least one argument which points to a non-existing file."), "WinPT", MB_ERR);
76  }          free_if_alloc (cfgf);
77            return -1;
78        }
79  /* Return the name of the gettext language file. */      return 0;
80  static char*  }
81  get_gettext_lang (void)  
82  {      
83      char *fname;  /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
84      fname = get_reg_entry_mo ();  void
85      if (!fname)  gpg_set_debug_mode (int val)
86          return NULL;  {
87      return fname;      static char buf[256];
88  }      char tmp[128];
89        
90        /* XXX: no gpgme.dbg is created. */
91  /* Initialize the gettext sub system. */      if (val > 0) {
92  static void          GetTempPath (DIM (tmp)-1, tmp);
93  load_gettext (void)          _snprintf (buf, DIM (buf)-1, "GPGME_DEBUG=5:%sgpgme.dbg", tmp);
94  {          putenv (buf);
95      char *nls = NULL;      }
96      char *file = NULL;      else
97            putenv ("GPGME_DEBUG=");
98      nls = get_gettext_lang ();  }
99      if (nls) {  
100          set_gettext_file ("winpt", nls);  
101          file = make_filename (nls, "winpt", "mo");  /* Initialize the gettext sub system. */
102          if (!file_exist_check (nls) && init_file_lock (&mo_file, file))  {  static void
103              msg_box (NULL, _("Could not initizalize file lock.\n"  load_gettext (void)
104                               "Native Language Support"),  {
105                       _("WinPT Error"), MB_ERR);      char *nls;
106          }  
107          free_if_alloc (nls);      /* Return the name of the gettext language file. */
108          free_if_alloc (file);      nls = get_reg_entry_mo ();
109      }      if (nls != NULL) {
110  }          set_gettext_file ("winpt", nls);
111            free_if_alloc (nls);
112        }
113  /* check if the default key from the gpg.conf file is available in the  }
114     keyring. if not, bail out because encryption won't work properly then. */  
115  static int  
116  check_default_key (gpg_keycache_t kc)  /* Return true if the GPG environment is useable. */
117  {  static bool
118      gpgme_key_t key;  gpg_prefs_ok (void)
119      gpgme_error_t err = GPG_ERR_NO_ERROR;  {
120      char * defkey;      char *p;
121    
122      defkey = get_gnupg_default_key ();      p = get_reg_entry_gpg4win ("gpg.exe");
123      if (defkey)      if (!p || file_exist_check (p) != 0) {
124          err = gpg_keycache_find_key (kc, defkey, 0, &key);          free_if_alloc (p);
125      free_if_alloc (defkey);          p = get_reg_entry_gpg ("gpgProgram");
126      return err? -1 : 0;          if (!p || file_exist_check (p) != 0) {
127  }              free_if_alloc (p);
128                log_debug ("gpg_prefs_ok: could not locate gpg.exe");
129                return false;
130  /* Return the WinPT program file name (with full pathname). */          }
131  static const char *      }
132  get_prog_part (const char * fname, int use_cwd)      free_if_alloc (p);
133  {      p = get_reg_entry_gpg4win (NULL);
134      static char program[512];      if (!p || dir_exist_check (p) != 0) {
135      char currdir[256];          free_if_alloc (p);
136      char *cmd = NULL;          p = get_reg_entry_gpg ("HomeDir");
137      int j;          if (!p || dir_exist_check (p) != 0) {
138                        free_if_alloc (p);
139      memset (currdir, 0, DIM (currdir));              log_debug ("gpg_prefs_ok: could not determine home directory");
140      memset (program, 0, DIM (program));              return false;
141                    }
142      if (use_cwd) {      }
143          GetCurrentDirectory (DIM (currdir)-1, currdir);      free_if_alloc (p);
144          _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);      return true;
145      }  }
146      else {  
147          cmd = GetCommandLine ();  
148          if (cmd == NULL)  /* Check gpg files if they are read-only and ask the user
149              return NULL;     if this should be corrected. */
150          strncpy (currdir, cmd, sizeof (currdir)-1);  static void
151          j = strlen (currdir);  check_readonly_attr (const char *homedir)
152          while (j--) {  {
153              if (currdir[j] == '\\')      const char *files[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg", NULL};
154                  break;      char *file;
155          }      int i;
156          currdir[j] = 0;  
157          _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);      for (i=0; files[i] != NULL; i++) {
158      }          file = make_filename (homedir, files[i], NULL);
159      return program;          remove_crit_file_attrs (file, 0);
160  }          free_if_alloc (file);
161        }
162    }
163  /* Check that the underlying crypto engine fullfills the minimal  
164     requirements so all commands work properly. */  
165  static int  /* Load the GPG environment. On the first start, some
166  check_crypto_engine (void)     checks are performed to find out in what state GPG is.
167  {     Return value: 0  everything OK.
168      int ma=1, mi=4, pa=3; /* GPG 1.4.3 */                   >0  fatal error.
169      int rc;                   -1 public keyring is empty or does not exist. */
170    static int
171      rc = check_gnupg_engine (&ma, &mi, &pa);  load_gpg_env (void)
172      if (rc == -1) {  {
173          msg_box (NULL, _("Could not read GnuPG version."),      SECURITY_ATTRIBUTES sec_attr;
174                   _("WinPT Error"), MB_ERR);      char *p;
175          return rc;      char *pkr;
176      }      int err = 0;
177      else if (rc) {  
178          log_box (_("WinPT Error"), MB_ERR,      p = get_reg_entry_gpg4win ("gpg.exe");
179                   _("Sorry, you need a newer GPG version.\n"      if (!p)
180                     "GPG version %d.%d.%d required GPG version "MIN_GPG_VER),          return (1);
181                     ma, mi, pa);      if (file_exist_check (p)) {
182          return rc;          free_if_alloc (p);
183      }          return (1);
184      /* We enable smartcard support for GPG: 1.9 or >= 1.4 */      }
185      if (ma >= 1 && mi >= 4)      free_if_alloc (p);
186          scard_support = 1;  
187        p = get_reg_entry_gpg ("HomeDir");
188      gpgver[0] = ma;      if (!p || dir_exist_check (p) != 0) {
189      gpgver[1] = mi;          free_if_alloc (p);
190      gpgver[2] = pa;          p = multi_gnupg_path (0);
191      return rc;      }
192  }      if (p && dir_exist_check (p)) {
193            memset (&sec_attr, 0, sizeof (sec_attr));
194            sec_attr.nLength = sizeof (sec_attr);
195  /* Try to load the keyserver config file. If @quiet is 1          if (!CreateDirectory (p, &sec_attr)) {
196     do not show any errors. */              msg_box (NULL, _("Could not create GPG home directory"),
197  static int                       _("WinPT Error"), MB_ERR);
198  load_keyserver_conf (int quiet)              free_if_alloc (p);
199  {              return (2);
200      const char * t;          }
201      int rc;      }
202        check_readonly_attr (p);
203      if (reg_prefs.kserv_conf)      pkr = make_filename (p, "pubring", "gpg");
204          t = reg_prefs.kserv_conf;      free_if_alloc (p);
205      else if (!file_exist_check (get_prog_part ("keyserver.conf", 0)))      if (get_file_size (pkr) == 0)
206          t = get_prog_part ("keyserver.conf", 0);          err = -1;
207      else      free_if_alloc (pkr);
208          t = "keyserver.conf";      return err;
209      rc = kserver_load_conf (t);  }
210      if (rc && !quiet)  
211          msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);  
212      return rc;  /* check if the default key from the gpg.conf file is available in the
213  }     keyring. if not, bail out because encryption won't work properly then. */
214    static int
215    check_default_key (gpg_keycache_t kc)
216  /* Enable the mobility mode. */  {
217  static void      gpgme_key_t key;
218  enable_mobile_mode (void)      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
219  {      char *defkey;
220      memset (&reg_prefs, 0, sizeof (reg_prefs));  
221      reg_prefs.always_trust = 0;      defkey = get_gnupg_default_key ();
222      reg_prefs.auto_backup = 0;      if (defkey)
223      reg_prefs.cache_time = 0;          err = gpg_keycache_find_key (kc, defkey, 0, &key);
224      reg_prefs.expert = 0;      else
225      reg_prefs.keylist_mode = 1;          msg_box (NULL, _("No useable secret key found."),
226      reg_prefs.kserv_conf = m_strdup ("keyserver.conf");                   _("WinPT Warning"), MB_WARN);
227      reg_prefs.no_zip_mmedia = 1;      free_if_alloc (defkey);
228      reg_prefs.use_tmpfiles = 1;      return err? -1 : 0;
229      reg_prefs.word_wrap = 80;  }
230      reg_prefs.use_viewer = 0; /* XXX */  
231  }  
232    /* Return the WinPT program file name (with full pathname). */
233    static const char*
234  /* Main entry point. */  get_prog_part (const char * fname, int use_cwd)
235  int WINAPI  {
236  WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)      static char program[2*MAX_PATH+1];
237  {      char currdir[MAX_PATH+1];
238      WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};      char *cmd = NULL;
239      HACCEL accel_tab;      int j;
240      int rc, ec, created = 0, use_cwd = 0, nfiles = 0;          
241      int first_start = 0, start_gpgprefs = 0;      memset (currdir, 0, DIM (currdir));
242      const char * s;      memset (program, 0, DIM (program));
243      MSG msg;          
244      HWND hwnd = NULL;      if (use_cwd) {
245            GetCurrentDirectory (DIM (currdir)-1, currdir);
246      glob_hinst = hinst;          _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);
247        }
248      #ifdef _DEBUG      else {
249      gpg_set_debug_mode (1);          cmd = GetCommandLine ();
250      debug = 1;          if (!cmd)
251      #endif              return NULL;
252            strncpy (currdir, cmd, DIM (currdir)-1);
253      s = PTD_get_version ();          j = strlen (currdir);
254      if (strcmp (s, MIN_PTD_VER)) {          while (j--) {
255          log_box (_("Privacy Tray Dynamic (PTD)"), MB_ERR,              if (currdir[j] == '\\')
256                   _("Please update your PTD.dll to the newest version, "                  break;
257                     "the version (%s) you use is too old."), s);          }
258          return 0;          currdir[j] = 0;
259      }          _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);
260        }
261      if (gpg_md_selftest ()) {      return program;
262          msg_box (NULL, _("Cryptographic selftest failed."),  }
263                   _("WinPT Error"), MB_ERR);  
264          return 0;  
265      }  /* Check that the underlying crypto engine fullfills the minimal
266       requirements so all commands work properly. */
267      s = gpgme_check_version (MIN_GPGME_VER);  static bool
268      if (!s || !*s) {  check_crypto_engine (void)
269          msg_box (NULL, _("A newer GPGME version is needed; at least "MIN_GPGME_VER),  {
270                   _("WinPT Error"), MB_ERR);      int ma = 0, mi = 0, pa = 0;
271          return 0;      int rc;
272      }  
273        rc = check_gnupg_engine (NEED_GPG_VERSION, &ma, &mi, &pa);
274      if (cmdline && stristr (cmdline, "--mobile")) {      if (rc == -1) {
275          msg_box (NULL, "WARNING: mobile modus is not fully implemented yet!",          msg_box (NULL, _("Could not read GnuPG version."),
276                   "WinPT", MB_INFO);                   _("WinPT Error"), MB_ERR);
277          mobile = 1;          return false;
278      }      }
279        else if (rc) {
280      set_default_kserver ();          log_box (_("WinPT Error"), MB_ERR,
281                     _("Sorry, you need a newer GPG version.\n"
282      if (!mobile) {                     "GPG version %d.%d.%d required GPG version "NEED_GPG_VERSION),
283          regist_inst_gnupg (1);                     ma, mi, pa);
284          regist_inst_winpt (1, &created);          return false;
285      }      }
286      else {      /* Enable smart card support for GPG 2 or >= 1.4 */
287          enable_mobile_mode ();      if ((ma > 1 || pa >= 4) && pcsc_available ())
288          /* XXX: ask for GPG path */          scard_support = 1;
289          created = 1; /* Disable registry writing */  
290      }      gpgver[0] = ma;
291        gpgver[1] = mi;
292      if (!created) {      gpgver[2] = pa;
293          memset (&reg_prefs, 0, sizeof (reg_prefs));      return true;
294          reg_prefs.use_tmpfiles = 1; /* default */  }
295          reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */  
296          get_reg_winpt_prefs (&reg_prefs);  
297          if (!reg_prefs.no_hotkeys)  /* Try to load the keyserver config file. If @quiet is 1
298              hotkeys_modify ();     do not show any errors. */
299      }  static int
300    load_keyserver_conf (int quiet)
301      rc = gnupg_check_homedir ();  {    
302      if (rc) {      const char *t, *conf;
303          log_box (_("WinPT Error"), MB_ERR,      char *buf;
304                   _("GPG home directory is not set correctly.\n"      int rc;
305                     "Please check the GPG registry settings:\n%s."),  
306                   winpt_strerror (rc));      #ifdef WINPT_MOBILE
307          const char * s = get_fileopen_dlg (GetActiveWindow (),      /* In mobile mode we automatically assume the config file
308                                             _("Select GPG Public Keyring"),         in the current directory. */
309                                             _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),      return kserver_load_conf ("keyserver.conf");
310                                             NULL);      #endif
311          if (s != NULL) {  
312              size_t n;      /* Create $APPDATA\winpt if needed. */
313              char * p = strrchr (s, '\\');      buf = make_special_filename (CSIDL_APPDATA, "winpt", NULL);
314              if (!p)      if (buf && dir_exist_check (buf) && !CreateDirectory (buf, NULL)) {
315                  BUG (0);          MessageBox (NULL, _("Failed to create WinPT directory"),
316              n = p - s;                      _("Keyserver"), MB_ERR);
317              if (n)          free_if_alloc (buf);
318              {          return -1;
319                  char * file = new char[n+1];      }
320                  if (!file)      free_if_alloc (buf);
321                      BUG (NULL);  
322                  memset (file, 0, n);      /* Check for $APPDATA\winpt\keyserver.conf */
323                  memcpy (file, s, n);      buf = make_special_filename (CSIDL_APPDATA, "winpt\\keyserver.conf", NULL);
324                  file[n] = '\0';          
325                  set_reg_entry_gpg ("HomeDir", file);      conf = get_prog_part ("keyserver.conf", 0);
326                  free_if_alloc (file);      if (!file_exist_check (conf))
327                  gnupg_check_homedir (); /* change gpgProgram if needed */          t = conf;
328              }      else
329          }          t = "keyserver.conf";
330          else {      if (file_exist_check (t) == 0 && file_exist_check (buf) != 0) {
331              msg_box (NULL, _("GPG home directory could not be determited."),          if (!CopyFile (t, buf, FALSE)) {
332                       _("WinPT Error"), MB_ERR);              MessageBox (NULL, _("Failed to copy the keyserver.conf"),
333              goto start;                          _("Keyserver"), MB_ERR);
334          }              free_if_alloc (buf);
335      }              return -1;
336            }
337      rc = check_gnupg_prog ();          t = buf;
338      if (rc) {      }
339          if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"      else
340                               "Do you want to start the GPG preferences to "          t = buf;
341                               "correct  this problem?"), _("WinPT Error"),      
342                               MB_INFO|MB_YESNO) == IDYES)      rc = kserver_load_conf (t);
343              start_gpgprefs = 1;      if (rc && !quiet)
344          else          msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);
345          {      else {
346              msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);          free_if_alloc (reg_prefs.kserv_conf);
347              return 0;          reg_prefs.kserv_conf = m_strdup (t);
348          }      }
349      }      free_if_alloc (buf);
350        return rc;
351      rc = gnupg_access_files ();  }
352      if (!start_gpgprefs && rc) {  
353          if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS) {  
354              ec = msg_box (NULL,  /* Check if both keyrings are empty. This indicates that
355                  _("Could not access and/or find the public and secret keyring.\n"     WinPT should offer to generate a key pair. */
356                    "If this is an accident, quit the program and fix it.\n\n"  static bool
357                    "Continue if you want that WinPT offers you more choices.\n"),  check_for_empty_keyrings (bool pub_only)
358                    "WinPT", MB_INFO|MB_YESNO);  {
359              if (ec == IDYES)      char *p;
360                  first_start = 1;      int n = 0;
361          }  
362          if (!first_start) {      p = get_gnupg_keyring (1, 0);
363              msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);      if (file_exist_check (p) == 0 && get_file_size (p) == 0)
364              return 0;          n++;
365          }      free_if_alloc (p);
366      }      if (pub_only)
367            return n == 1? true : false;
368      if (!first_start) {      p = get_gnupg_keyring (0, 0);
369          rc = gpg_check_permissions (1);      if (file_exist_check (p) == 0 && get_file_size (p) == 0)
370          if (rc && rc == 2)          n++;
371              gpg_read_only = 1;      free_if_alloc (p);
372          else if (rc)      return n==2? true : false;
373              return 0;  }
374      }  
375    
376      load_gettext ();  #ifdef WINPT_MOBILE
377      init_gnupg_table ();  /* Enable the mobile mode if possible.
378       There are some constraints which must be fullfilled.
379      nfiles = fm_parse_command_line (cmdline);     Return value: 0 on success. */
380      if (nfiles > 0) {  static int
381          free_gnupg_table ();  enable_mobile_mode (void)
382          return 0;  {
383      }      static const char *test_fname = "winpt_mobile_test.txt";
384        FILE *fp;
385      if (cmdline && stristr (cmdline, "--wipe-freespace")) {      char *pubring;
386          dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,      ULARGE_INTEGER caller, total;
387                              GetDesktopWindow(), space_wipefrees_dlg_proc, NULL,      DWORD temp_size;
388                              _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);  
389          free_gnupg_table ();      fp = fopen (test_fname, "wb");
390          return 0;      if (fp == NULL) {
391      }          MessageBox (NULL, "Mobile mode cannot be used without write permission\n"
392                              "for the current directory", "WinPT Error", MB_ERR);
393      load_keyserver_conf (cmdline? 1 : 0);              
394            return -1;
395      if (cmdline && (stristr (cmdline, "--keymanager")      }
396                  || stristr (cmdline, "--cardmanager"))) {      fclose (fp);
397          update_keycache (GetDesktopWindow ());      DeleteFile (test_fname);
398          if (stristr (cmdline, "keymanager"))      if (file_exist_check ("gpg.exe")) {
399              dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYMISC,          MessageBox (NULL, "The GnuPG program needs to be in the same directory\n"
400                              GetDesktopWindow(), keymanager_dlg_proc, NULL,                            "as the WinPT program", "WinPT Error", MB_ERR);
401                              _("Key Manager"), IDS_WINPT_KEYMISC);            return -1;
402          else {      }
403              gpg_card_t crd = gpg_card_load ();      
404              if (crd)      /* Because write operations to the keyring result in a temporary
405                  dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_EDIT,         file, we need at least 2 MB plus the size of the keyring for
406                                    GetDesktopWindow(), card_edit_dlg_proc,         free space. */
407                                    (LPARAM)crd, _("Card Manager"),      pubring = get_gnupg_keyring (1);
408                                    IDS_WINPT_CARD_EDIT);      temp_size = get_file_size (pubring) + 2097152;
409              gpg_card_release (crd);      free_if_alloc (pubring);
410          }  
411          keycache_release (0);      if (!GetDiskFreeSpaceEx (NULL, &caller, &total, NULL) ||
412          free_gnupg_table ();          caller.LowPart < temp_size) {
413          return 0;          log_box ("WinPT Error", MB_ERR,
414      }                   "The mobile mode needs at least %lu KB for temporary files",
415                     temp_size/1024);
416      CreateMutex (NULL, TRUE, PGM_NAME);          return -1;
417      if (GetLastError () == ERROR_ALREADY_EXISTS) {      }
418          free_gnupg_table ();  
419          return 0;      /* XXX: shall we check for 'temp-directory' in the gpg.conf? */
420      }  
421        return 0;
422      if (cmdline) {  }
423          if (stristr (cmdline, "--enable-debug") || stristr (cmdline, "--debug")) {  #endif
424              gpg_set_debug_mode (1);  
425              winpt_debug_msg ();  
426              debug = 1;  /* Set the default keyserver for this instance. */
427          }  void
428      }  set_default_keyserver (void)
429    {
430      wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));      char *host = get_reg_entry_keyserver ("Default");
431      rc = RegisterClass (&wc);      char *str_port = get_reg_entry_keyserver ("Default_Port");
432      if (rc == FALSE) {      WORD port = HKP_PORT;
433          msg_box (NULL, _("Could not register window class"),  
434                   _("WinPT Error"), MB_ERR);      if (!host)
435          free_gnupg_table ();          keyserver_set_default (NULL, 0);
436          return 0;      else {
437      }          if (str_port && *str_port)
438                port = atoi (str_port);
439      hwnd = CreateWindow (PGM_NAME,          keyserver_set_default (host, port);
440                           PGM_NAME,      }
441                           0, 0, 0, 0, 0,      free_if_alloc (host);
442                           NULL,      free_if_alloc (str_port);
443                           NULL,  }
444                           hinst,  
445                           NULL);  
446      if (hwnd == NULL) {  /* Display info message that WinPT is now in debug mode. */
447          msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);  void
448          free_gnupg_table ();  winpt_debug_msg (void)
449          return 0;  {      
450      }      char output[512];
451      glob_hwnd = hwnd;      char temp[128];
452      UpdateWindow (hwnd);          
453        GetTempPath (DIM (temp) -1, temp);
454      if (!first_start && !start_gpgprefs) {      _snprintf (output, DIM (output)-1,
455          gnupg_backup_options ();                  "The GPGME output file is %sgpgme.dbg\n"
456          rc = check_crypto_engine ();          "The WinPT output file is %swinpt.log\n", temp, temp);
457          if (rc) {      MessageBox (NULL, output, "WinPT now runs in DEBUG MODE", MB_INFO);
458              DestroyWindow (hwnd);  }
459              free_gnupg_table ();  
460              return 0;  
461          }  /* Search for insecure ElGamal keys and return the
462      }     number of founded keys. */
463        static int
464      if (start_gpgprefs) {  count_insecure_elgkeys (void)
465          char *ring;  {
466          size_t size = 0;      gpg_keycache_t pc;
467          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,      gpgme_key_t key;
468                          gpgprefs_dlg_proc, NULL);      int n = 0;
469          ring = get_gnupg_keyring (0, !NO_STRICT);  
470          if (gnupg_access_keyring (0) == -1 && get_file_size (ring) == 0)      pc = keycache_get_ctx (1);
471              first_start = 1; /* The keyring is empty! */      while (!gpg_keycache_next_key (pc, 0, &key)) {
472          free_if_alloc (ring);          if (key->subkeys->pubkey_algo == GPGME_PK_ELG)
473      }              n++;
474        }
475      if (first_start) {      gpg_keycache_rewind (pc);
476          struct first_start_s fs;      return n;
477          struct genkey_s c;  }
478          HWND h;  
479  start:  
480          h = GetDesktopWindow ();  /* Main entry point. */
481          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,  int WINAPI
482                              gpgprefs_dlg_proc, NULL);  WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
483          DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,  {
484                          first_run_dlg_proc, (LPARAM)&fs);      WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};
485          switch (fs.choice) {      HACCEL accel_tab;
486          case SETUP_KEYGEN:      MSG msg;
487              c.interactive = 1;      HWND hwnd = NULL;
488              c.first_start = 1;      WORD ver[3], ptdver[4];
489              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,      const char *s;
490                                   h, keygen_wizard_dlg_proc, (LPARAM)&c);      int rc, ec, created = 0;
491              if (!rc)      int first_start = 0, start_gpgprefs = 0;
492                  goto start;      int winpt_inst_found = 0;
493              break;      int start_manager = 0;    
494    
495          case SETUP_IMPORT:  #ifdef WINPT_MOBILE
496              rc = gnupg_copy_keyrings ();      /* Do not continue in case of problems. */
497              if (rc) {      if (enable_mobile_mode ())
498                  msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);          return 0;
499                  goto start;  #endif
500              }  
501              break;      glob_hinst = hinst;
502        if (cmdline && stristr (cmdline, "--stop")) {
503          case -1:          hwnd = FindWindow ("WinPT", "WinPT");
504              DestroyWindow (hwnd);          if (hwnd != NULL)
505              free_gnupg_table ();              PostMessage (hwnd, WM_DESTROY, 0, 0);
506              return 0;          return 0;
507          }      }
508          update_keycache (hwnd);  
509          check_crypto_engine ();      #ifdef _DEBUG
510      }      gpg_set_debug_mode (1);
511      else {      debug = 1;
512          gpg_keycache_t c;      #endif
513          update_keycache (hwnd);  
514          c = keycache_get_ctx (1);      get_file_version ("WinPT.exe", &ver[0], &ver[1], &ver[2], &ver[3]);
515          if (!c || !gpg_keycache_get_size (c)) {      ec = get_file_version ("PTD.dll", &ptdver[0], &ptdver[1],  
516              gnupg_display_error ();                                   &ptdver[2], &ptdver[3]);
517              msg_box (hwnd, _("The keycache was not initialized or is empty.\n"      
518                               "Please check your GPG config (keyrings, pathes...)"),      if (!ec && (ptdver[0] != ver[0] ||
519                               _("WinPT Error"), MB_ERR);                  ptdver[1] != ver[1] ||
520              ec = msg_box (NULL, _("It seems that GPG is not set properly.\n"                  ptdver[2] != ver[2])) {
521                                    "Do you want to start the GPG preferences dialog?"),          log_box (_("WinPT Error"), MB_ERR,
522                              "WinPT", MB_INFO|MB_YESNO);                   _("The PTD.dll file has a different version than WinPT.exe\n"
523              if (ec == IDYES) {                     "Please update the PTD.dll to version %d.%d.%d"),
524                  DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,                     ver[0], ver[1], ver[2]);
525                                  gpgprefs_dlg_proc, NULL);          return 0;
526                  update_keycache (hwnd);      }
527              }  
528              else {      if (gpg_md_selftest ()) {
529                  DestroyWindow (hwnd);          msg_box (NULL, _("Cryptographic selftest failed."),
530                  free_gnupg_table ();                   _("WinPT Error"), MB_ERR);
531                  return 0;          return 0;
532              }      }
533          }  
534          if (check_default_key (c)) {      s = gpgme_check_version (NEED_GPGME_VERSION);
535              char * p = get_gnupg_default_key ();      if (!s || !*s) {
536              log_box (_("WinPT Error"), MB_ERR,          msg_box (NULL, _("A newer GPGME version is needed; at least "NEED_GPGME_VERSION),
537                       _("Default key from the GPG options file could not be found.\n"                   _("WinPT Error"), MB_ERR);
538                         "Please check your gpg.conf (options) to correct this:\n\n"          return 0;
539                         "%s: public key not found."), p? p : "[null]");      }
540              free_if_alloc (p);  
541              DestroyWindow (hwnd);      CreateMutex (NULL, TRUE, PGM_NAME);
542              free_gnupg_table ();      if (GetLastError () == ERROR_ALREADY_EXISTS)
543              return 0;          winpt_inst_found = 1;
544          }      
545          if (count_insecure_elgkeys ())      set_default_keyserver ();
546              DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,      load_gettext ();
547                              elgamal_warn_dlg_proc, NULL);      admin_user = user_is_admin ();
548      }  
549        regist_inst_gnupg (1);
550      accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);      regist_inst_winpt (1, &created);
551      keyring_check_last_access (); /* init */  
552      while (GetMessage (&msg, hwnd, 0, 0)) {      if (!created) {
553          if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {          memset (&reg_prefs, 0, sizeof (reg_prefs));
554              TranslateMessage (&msg);          get_reg_winpt_prefs (&reg_prefs);
555              DispatchMessage (&msg);          reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */
556          }          gnupg_load_config ();
557      }      }
558            
559      return 0;      if (is_gpg4win_installed ())
560  }          load_gpg_env (); /* XXX: check return code. */
561    
562        rc = gnupg_check_homedir ();
563        if (rc) {
564            char *p;
565    
566            log_box (_("WinPT Error"), MB_ERR,
567                     _("GPG home directory is not set correctly.\n"
568                       "Please check the GPG registry settings:\n%s."),
569                     winpt_strerror (rc));
570            s = get_fileopen_dlg (GetActiveWindow (),
571                                  _("Select GPG Public Keyring"),
572                                  "GPG Keyrings (*.gpg)\0*.gpg\0\0",
573                                  NULL);
574            if (s != NULL && (p=strrchr (s, '\\'))) {
575                char *path = substr (s, 0, (p-s));
576    
577                set_reg_entry_gpg ("HomeDir", path);
578                free_if_alloc (path);
579            }
580            else {
581                msg_box (NULL, _("GPG home directory could not be determined."),
582                         _("WinPT Error"), MB_ERR);
583                goto start;
584            }
585        }
586    
587        rc = check_gnupg_prog ();
588        if (rc) {
589            if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"
590                                 "Do you want to start the GPG preferences to "
591                                 "correct  this problem?"), _("WinPT Error"),
592                                 MB_INFO|MB_YESNO) == IDYES)
593                start_gpgprefs = 1;
594            else {
595                msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
596                return 0;
597            }
598        }
599    
600        rc = gnupg_access_files ();
601        if (!start_gpgprefs && rc) {
602            if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS) {
603                ec = msg_box (NULL,
604                    _("Could not access and/or find the public and secret keyring.\n"
605                      "If this is an accident, quit the program and fix it.\n\n"
606                      "Continue if you want WinPT to offer you more choices.\n"),
607                      "WinPT", MB_INFO|MB_YESNO);
608                if (ec == IDYES)
609                    first_start = 1;
610            }
611            if (!first_start) {
612                msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
613                return 0;
614            }
615        }
616        if (check_for_empty_keyrings (false))
617            first_start = 1;
618    
619        if (!first_start) {
620            rc = gpg_check_permissions (1);
621            if (rc && rc == 2) /* 2 means read-only mode. */
622                gpg_read_only = 1;
623            else if (rc)
624                return 0;
625        }
626        
627        init_gnupg_table ();
628    
629        if (fm_parse_command_line (cmdline) > 0) {
630            free_gnupg_table ();
631            return 0;
632        }
633    
634        if (cmdline && stristr (cmdline, "--wipe-freespace")) {
635            dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,
636                                GetDesktopWindow(), space_wipefrees_dlg_proc, 0,
637                                _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);
638            free_gnupg_table ();
639            return 0;
640        }
641    
642        load_keyserver_conf (cmdline? 1 : 0);
643    
644        if (cmdline && (stristr (cmdline, "--keymanager")
645                    || stristr (cmdline, "--cardmanager"))) {
646            /* If an instance of WinPT is running, just send the command
647               to open the key manager. Otherwise start a new instance. */
648            HWND tray = FindWindow ("WinPT", "WinPT");
649            if (stristr (cmdline, "keymanager"))
650                start_manager = ID_WINPT_KEY;
651            else
652                start_manager = ID_WINPT_CARD;
653            if (tray != NULL) {
654                PostMessage (tray, WM_COMMAND, start_manager, 0);
655                free_gnupg_table ();
656                return 0;
657            }
658        }
659    
660        /* If we found another WinPT instance, just quit to avoid it
661           will be executed twice. */
662        if (winpt_inst_found) {
663            log_debug ("%s", "WinMain: WinPT is already running.");
664            free_gnupg_table ();
665            return 0;
666        }
667    
668        #ifndef WINPT_MOBILE
669        if (cmdline && (stristr (cmdline, "--enable-debug") ||
670                        stristr (cmdline, "--debug"))) {
671            gpg_set_debug_mode (1);
672            winpt_debug_msg ();
673            debug = 1;
674        }
675        #endif
676    
677        wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));
678        rc = RegisterClass (&wc);
679        if (rc == FALSE) {
680            msg_box (NULL, _("Could not register window class"),
681                     _("WinPT Error"), MB_ERR);
682            free_gnupg_table ();
683            return 0;
684        }
685    
686        hwnd = CreateWindow (PGM_NAME,
687                             PGM_NAME,
688                             0, 0, 0, 0, 0,
689                             NULL,
690                             NULL,
691                             hinst,
692                             NULL);
693        if (hwnd == NULL) {
694            msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);
695            free_gnupg_table ();
696            return 0;
697        }
698        glob_hwnd = hwnd;
699        UpdateWindow (hwnd);
700    
701        if (!first_start && !start_gpgprefs) {
702            gnupg_backup_options ();        
703            if (!check_crypto_engine ()) {
704                DestroyWindow (hwnd);
705                free_gnupg_table ();
706                return 0;
707            }
708        }
709        
710        if (start_gpgprefs) {
711            DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
712                            gpgprefs_dlg_proc, 0);
713            if (check_for_empty_keyrings (true))
714                first_start = 1; /* The public keyring is empty. */
715        }
716    
717        if (first_start) {
718            struct genkey_s c;
719            int choice;
720            HWND h;
721    start:
722            h = GetDesktopWindow ();
723            if (!gpg_prefs_ok ())
724                DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,
725                                gpgprefs_dlg_proc, 0);
726            choice = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,
727                                     first_run_dlg_proc, 0);
728            switch (choice) {
729            case SETUP_KEYGEN:
730                c.interactive = 1;
731                c.first_start = 1;
732                rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,
733                                     h, keygen_wizard_dlg_proc, (LPARAM)&c);
734                if (!rc)
735                    goto start;
736                break;
737    
738            case SETUP_IMPORT:
739                rc = gnupg_copy_keyrings ();
740                if (rc) {
741                    msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
742                    goto start;
743                }
744                break;
745    
746            case SETUP_CARDGEN:
747                rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_CARD_KEYGEN,
748                                     h, card_keygen_dlg_proc, 0);
749                if (!rc)
750                    goto start;
751                break;
752    
753            case 0: /* Cancel/Abort. */
754            default:
755                DestroyWindow (hwnd);
756                free_gnupg_table ();
757                return 0;
758            }
759            update_keycache (hwnd);
760            if (!check_crypto_engine ()) {
761                DestroyWindow (hwnd);
762                free_gnupg_table ();
763                keycache_release (1);
764                return 0;
765            }
766            if (!is_gpg4win_installed ()) {
767                select_language ();
768                load_gettext ();
769            }
770        }
771        else {
772            gpg_keycache_t c, sec_c;
773            if (update_keycache (hwnd)) {
774                DestroyWindow (hwnd);
775                free_gnupg_table ();
776                keycache_release (1);
777                return 0;
778            }
779            /* XXX: rewrite this part. */
780            c = keycache_get_ctx (1);
781            if (!gpg_keycache_get_size (c)) {
782                msg_box (hwnd, _("The keycache was not initialized or is empty.\n"
783                                 "Please check your GPG config (keyrings, pathes...)"),
784                                 _("WinPT Error"), MB_ERR);
785                ec = msg_box (NULL, _("It seems that GPG is not configured properly.\n"
786                                      "Do you want to start the GPG preferences dialog?"),
787                                "WinPT", MB_INFO|MB_YESNO);
788                if (ec == IDYES) {
789                    DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
790                                    gpgprefs_dlg_proc, 0);
791                    update_keycache (hwnd);
792                }
793                else {
794                    DestroyWindow (hwnd);
795                    free_gnupg_table ();
796                    keycache_release (1);
797                    return 0;
798                }
799            }
800            sec_c = keycache_get_ctx (0);
801            if (check_default_key (sec_c)) {
802                char *p = get_gnupg_default_key ();
803                log_box (_("WinPT Error"), MB_ERR,
804                         _("Default key (from the GPG config file) could not be found.\n"
805                           "Please check your gpg.conf or set a new default key to correct it:\n\n"
806                           "%s: public key not found."), p? p : "[null]");
807                set_gnupg_default_key (NULL);
808            }
809            if (count_insecure_elgkeys ())
810                DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,
811                                elgamal_warn_dlg_proc, 0);
812        }
813    
814        if (start_manager)
815            PostMessage (hwnd, WM_COMMAND, start_manager, 0);
816    
817        accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);
818        keyring_check_last_access (); /* init */
819        while (GetMessage (&msg, hwnd, 0, 0)) {
820            if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {
821                TranslateMessage (&msg);
822                DispatchMessage (&msg);
823            }
824        }
825            
826        return 0;
827    }

Legend:
Removed from v.32  
changed lines
  Added in v.271

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26