/[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 23 by twoaday, Fri Sep 30 10:10:16 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  HINSTANCE glob_hinst; /* global instance for the dialogs */  #include "wptCard.h"
39  HWND glob_hwnd; /* global window handle for the dialogs */  #include "wptFileManager.h"
40  HWND activ_hwnd;  #include "wptContext.h"
41  LOCK mo_file;  #include "wptCardEdit.h"
42  int scard_support = 0;  #include "wptCrypto.h"
43  int debug = 0;  #include "wptUTF8.h"
44  int mobile = 0;  
45  int gpg_read_only = 0;  void remove_crit_file_attrs (const char *fname, int force);
46  char gpgver[3];  BOOL user_is_admin (void);
47    extern "C" int  pcsc_available (void);
48  /* Internal IPC */  
49  int start_keymanager = 0;  /* Global variables. */
50    HINSTANCE glob_hinst;   /* global instance for the dialogs */
51  static void  HWND glob_hwnd;         /* global window handle for the dialogs */
52  update_keycache (HWND hwnd)  int scard_support = 0;
53  {  int debug = 0;
54      refresh_cache_s rcs = {0};  int gpg_read_only = 0;
55      rcs.kr_reload = 0;  int admin_user = 0;
56      rcs.kr_update = 1;  char gpgver[3];
57      rcs.tr_update = 1;  /* End */
58      DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,  
59                      keycache_dlg_proc, (LPARAM)&rcs);  
60  } /* update_keycache */  /* Load the key cache and rebuild the signature cache. */
61    int
62    update_keycache (HWND hwnd)
63  static char *  {
64  get_gettext_lang (void)      int err;
65  {      
66      char * fname;      refresh_cache_s rcs = {0};
67      fname = get_reg_entry_mo ();      rcs.kr_reload = 0;
68      if (!fname)      rcs.kr_update = 1;
69          return NULL;      rcs.tr_update = 1;
70      return fname;      err = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,
71  } /* get_gettext_lang */                      keycache_dlg_proc, (LPARAM)&rcs);
72        if (err) {
73            char *cfgf = get_gnupg_config ();
74  static void          if (cfgf && check_gnupg_options (cfgf, 0) == WPTERR_FILE_EXIST)
75  load_gettext (void)              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      char * nls = NULL;          return -1;
78      char * file = NULL;      }
79        return 0;
80      nls = get_gettext_lang ();  }
81      if (nls) {  
82          set_gettext_file ("winpt", nls);  
83          file = make_filename (nls, "winpt", "mo");  /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
84          if (!file_exist_check (nls) && init_file_lock (&mo_file, file))  {  void
85              msg_box (NULL, _("Could not initizalize file lock.\n"  gpg_set_debug_mode (int val)
86                               "Native Language Support"),  {
87                       _("WinPT Error"), MB_ERR);      static char buf[256];
88          }      char tmp[128];
89          free_if_alloc (nls);      
90          free_if_alloc (file);      /* XXX: no gpgme.dbg is created. */
91      }      if (val > 0) {
92  } /* load_gettext */          GetTempPath (DIM (tmp)-1, tmp);
93            _snprintf (buf, DIM (buf)-1, "GPGME_DEBUG=5:%sgpgme.dbg", tmp);
94            putenv (buf);
95  /* check if the default key from the gpg.conf file is available in the      }
96     keyring. if not, bail out because encryption won't work properly then. */      else
97  static int          putenv ("GPGME_DEBUG=");
98  check_default_key (gpgme_keycache_t kc)  }
99  {  
100      gpgme_key_t key;  
101      gpgme_error_t err = GPG_ERR_NO_ERROR;  /* Initialize the gettext sub system. */
102      char * defkey;  static void
103    load_gettext (void)
104      defkey = get_gnupg_default_key ();  {
105      if (defkey)      char *nls;
106          err = gpgme_keycache_find_key (kc, defkey, 0, &key);  
107      free_if_alloc (defkey);      /* Return the name of the gettext language file. */
108      return err? -1 : 0;      nls = get_reg_entry_mo ();
109  } /* check_default_key */      if (nls != NULL) {
110            set_gettext_file ("winpt", nls);
111            free_if_alloc (nls);
112  /* Return the WinPT program file name (with full pathname). */      }
113  static const char *  }
114  get_prog_part (const char * fname, int use_cwd)  
115  {  
116      static char program[1024];  /* Return true if the GPG environment is useable. */
117      char currdir[256], * cmd = NULL;  static bool
118      int j;  gpg_prefs_ok (void)
119            {
120      memset (currdir, 0, DIM (currdir));      char *p;
121      memset (program, 0, DIM (program));  
122                p = get_reg_entry_gpg4win ("gpg.exe");
123      if (use_cwd) {      if (!p || file_exist_check (p) != 0) {
124          GetCurrentDirectory (DIM (currdir)-1, currdir);          free_if_alloc (p);
125          _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);          p = get_reg_entry_gpg ("gpgProgram");
126      }          if (!p || file_exist_check (p) != 0) {
127      else {              free_if_alloc (p);
128          cmd = GetCommandLine ();              log_debug ("gpg_prefs_ok: could not locate gpg.exe");
129          if (cmd == NULL)              return false;
130              return NULL;          }
131          strncpy (currdir, cmd, 255);      }
132          j = strlen (currdir);      free_if_alloc (p);
133          while (j--) {      p = get_reg_entry_gpg4win (NULL);
134              if (currdir[j] == '\\')      if (!p || dir_exist_check (p) != 0) {
135                  break;                    free_if_alloc (p);
136          }          p = get_reg_entry_gpg ("HomeDir");
137          currdir[j] = 0;          if (!p || dir_exist_check (p) != 0) {
138          _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);              free_if_alloc (p);
139      }              log_debug ("gpg_prefs_ok: could not determine home directory");
140      return program;              return false;
141  } /* get_prog_part */          }
142        }
143        free_if_alloc (p);
144  static int      return true;
145  check_crypto_engine (void)  }
146  {  
147      int ma=1, mi=4, pa=0; /* GPG 1.4.0 */  
148      int rc;  /* Check gpg files if they are read-only and ask the user
149       if this should be corrected. */
150      rc = check_gnupg_engine (&ma, &mi, &pa);  static void
151      if (rc == -1) {  check_readonly_attr (const char *homedir)
152          msg_box (NULL, _("Could not read GnuPG version."), _("WinPT Error"), MB_ERR);  {
153          return rc;      const char *files[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg", NULL};
154      }      char *file;
155      else if (rc) {      int i;
156          log_box (_("WinPT Error"), MB_ERR,  
157                   _("Sorry, you need a newer GPG version.\n"      for (i=0; files[i] != NULL; i++) {
158                     "GPG version %d.%d.%d required GPG version 1.4.0"),          file = make_filename (homedir, files[i], NULL);
159                     ma, mi, pa);          remove_crit_file_attrs (file, 0);
160          return rc;          free_if_alloc (file);
161      }      }
162      /* We enable smartcard support for GPG: 1.9.x or >= 1.4.0 */  }
163      if (ma >= 1 && mi >= 4)  
164          scard_support = 1;  
165    /* Load the GPG environment. On the first start, some
166      gpgver[0] = ma;     checks are performed to find out in what state GPG is.
167      gpgver[1] = mi;     Return value: 0  everything OK.
168      gpgver[2] = pa;                   >0  fatal error.
169      return rc;                   -1 public keyring is empty or does not exist. */
170  } /* check_crypto_engine */  static int
171    load_gpg_env (void)
172    {
173  static int      SECURITY_ATTRIBUTES sec_attr;
174  load_keyserver_conf (int quiet)      char *p;
175  {      char *pkr;
176      const char * t;      int err = 0;
177      int rc;  
178        p = get_reg_entry_gpg4win ("gpg.exe");
179      if (reg_prefs.kserv_conf)      if (!p)
180          t = reg_prefs.kserv_conf;          return (1);
181      else if (!file_exist_check (get_prog_part ("keyserver.conf", 0)))      if (file_exist_check (p)) {
182          t = get_prog_part ("keyserver.conf", 0);          free_if_alloc (p);
183      else          return (1);
184          t = "keyserver.conf";      }
185      rc = kserver_load_conf (t);      free_if_alloc (p);
186      if (rc && !quiet)  
187          msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);      p = get_reg_entry_gpg ("HomeDir");
188      return rc;      if (!p || dir_exist_check (p) != 0) {
189  }          free_if_alloc (p);
190            p = multi_gnupg_path (0);
191        }
192  static void      if (p && dir_exist_check (p)) {
193  enable_mobile_mode (void)          memset (&sec_attr, 0, sizeof (sec_attr));
194  {          sec_attr.nLength = sizeof (sec_attr);
195      memset (&reg_prefs, 0, sizeof (reg_prefs));          if (!CreateDirectory (p, &sec_attr)) {
196      reg_prefs.always_trust = 0;              msg_box (NULL, _("Could not create GPG home directory"),
197      reg_prefs.auto_backup = 0;                       _("WinPT Error"), MB_ERR);
198      reg_prefs.cache_time = 0;              free_if_alloc (p);
199      reg_prefs.expert = 0;              return (2);
200      reg_prefs.keylist_mode = 1;          }
201      reg_prefs.kserv_conf = m_strdup ("keyserver.conf");      }
202      reg_prefs.no_zip_mmedia = 1;      check_readonly_attr (p);
203      reg_prefs.use_tmpfiles = 1;      pkr = make_filename (p, "pubring", "gpg");
204      reg_prefs.word_wrap = 80;      free_if_alloc (p);
205      reg_prefs.use_viewer = 0; /* XXX */      if (get_file_size (pkr) == 0)
206  }          err = -1;
207        free_if_alloc (pkr);
208  char* get_subkey_fingerprint (gpgme_ctx_t ctx, const char *keyid);      return err;
209    }
210  int WINAPI  
211  #ifndef WINPT_IPC  
212  WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)  /* check if the default key from the gpg.conf file is available in the
213  #else     keyring. if not, bail out because encryption won't work properly then. */
214  win_main (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)  static int
215  #endif  check_default_key (gpg_keycache_t kc)
216  {  {
217      WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};      gpgme_key_t key;
218      HACCEL accel_tab;      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
219      int rc, ec, created = 0, use_cwd = 0, nfiles = 0;      char *defkey;
220      int first_start = 0, start_gpgprefs = 0;  
221      const char * s;      defkey = get_gnupg_default_key ();
222      MSG msg;      if (defkey)
223      HWND hwnd = NULL;          err = gpg_keycache_find_key (kc, defkey, 0, &key);
224        else
225      glob_hinst = hinst;          msg_box (NULL, _("No useable secret key found."),
226                         _("WinPT Warning"), MB_WARN);
227      #ifdef _DEBUG      free_if_alloc (defkey);
228      gpgme_set_debug_mode (1);      return err? -1 : 0;
229      #endif  }
230    
231      s = PTD_get_version ();  
232      if (strcmp (s, "0.8.0")) {  /* Return the WinPT program file name (with full pathname). */
233          log_box (_("Privacy Tray Dynamic (PTD)"), MB_ERR,  static const char*
234                   _("Please update your PTD.dll to the newest version, "  get_prog_part (const char * fname, int use_cwd)
235                     "the version (%s) you use is too old."), s);  {
236          return 0;      static char program[2*MAX_PATH+1];
237      }      char currdir[MAX_PATH+1];
238        char *cmd = NULL;
239      if (gpg_md_selftest ()) {      int j;
240          msg_box (NULL, _("Cryptographic selftest failed."),          
241                   _("WinPT Error"), MB_ERR);      memset (currdir, 0, DIM (currdir));
242          return 0;      memset (program, 0, DIM (program));
243      }          
244        if (use_cwd) {
245      if (cmdline && stristr (cmdline, "--mobile")) {          GetCurrentDirectory (DIM (currdir)-1, currdir);
246          msg_box (NULL, "WARNING: mobile modus is not fully implemented yet!",          _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);
247                   "WinPT", MB_INFO);      }
248          mobile = 1;      else {
249      }          cmd = GetCommandLine ();
250            if (!cmd)
251      set_default_kserver ();              return NULL;
252            strncpy (currdir, cmd, DIM (currdir)-1);
253      if (!mobile) {          j = strlen (currdir);
254          regist_inst_gnupg (1);          while (j--) {
255          regist_inst_winpt (1, &created);              if (currdir[j] == '\\')
256      }                  break;
257      else {          }
258          enable_mobile_mode ();          currdir[j] = 0;
259          /* XXX: ask for GPG path */          _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);
260          created = 1; /* Disable registry writing */      }
261      }      return program;
262    }
263      if (!created) {  
264          memset (&reg_prefs, 0, sizeof (reg_prefs));  
265          reg_prefs.use_tmpfiles = 1; /* default */  /* Check that the underlying crypto engine fullfills the minimal
266          reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */     requirements so all commands work properly. */
267          get_reg_winpt_prefs (&reg_prefs);  static bool
268          if (!reg_prefs.no_hotkeys)  check_crypto_engine (void)
269              hotkeys_modify ();  {
270      }      int ma = 0, mi = 0, pa = 0;
271        int rc;
272      rc = gnupg_check_homedir ();  
273      if (rc) {      rc = check_gnupg_engine (NEED_GPG_VERSION, &ma, &mi, &pa);
274          log_box (_("WinPT Error"), MB_ERR,      if (rc == -1) {
275                   _("GPG home directory is not set correctly.\n"          msg_box (NULL, _("Could not read GnuPG version."),
276                     "Please check the GPG registry settings:\n%s."),                   _("WinPT Error"), MB_ERR);
277                   winpt_strerror (rc));          return false;
278          const char * s = get_filename_dlg (GetActiveWindow (), FILE_OPEN,      }
279                                             _("Select GPG Public Keyring"),      else if (rc) {
280                                             _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),          log_box (_("WinPT Error"), MB_ERR,
281                                             NULL);                   _("Sorry, you need a newer GPG version.\n"
282          if (s != NULL) {                     "GPG version %d.%d.%d required GPG version "NEED_GPG_VERSION),
283              size_t n;                     ma, mi, pa);
284              char * p = strrchr (s, '\\');          return false;
285              if (!p)      }
286                  BUG (0);      /* Enable smart card support for GPG 2 or >= 1.4 */
287              n = p - s;      if ((ma > 1 || pa >= 4) && pcsc_available ())
288              if (n)          scard_support = 1;
289              {  
290                  char * file = new char[n+1];      gpgver[0] = ma;
291                  if (!file)      gpgver[1] = mi;
292                      BUG (NULL);      gpgver[2] = pa;
293                  memset (file, 0, n);      return true;
294                  memcpy (file, s, n);  }
295                  file[n] = '\0';          
296                  set_reg_entry_gpg ("HomeDir", file);  
297                  free_if_alloc (file);  /* Try to load the keyserver config file. If @quiet is 1
298                  gnupg_check_homedir (); /* change gpgProgram if needed */     do not show any errors. */
299              }  static int
300          }  load_keyserver_conf (int quiet)
301          else {  {    
302              msg_box (NULL, _("GPG home directory could not be determited."),      const char *t, *conf;
303                       _("WinPT Error"), MB_ERR);      char *buf;
304              goto start;      int rc;
305          }  
306      }      #ifdef WINPT_MOBILE
307        /* In mobile mode we automatically assume the config file
308      rc = check_gnupg_prog ();         in the current directory. */
309      if (rc) {      return kserver_load_conf ("keyserver.conf");
310          if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"      #endif
311                               "Do you want to start the GPG preferences to "  
312                               "correct  this problem?"), _("WinPT Error"),      /* Create $APPDATA\winpt if needed. */
313                               MB_INFO|MB_YESNO) == IDYES)      buf = make_special_filename (CSIDL_APPDATA, "winpt", NULL);
314              start_gpgprefs = 1;      if (buf && dir_exist_check (buf) && !CreateDirectory (buf, NULL)) {
315          else          MessageBox (NULL, _("Failed to create WinPT directory"),
316          {                      _("Keyserver"), MB_ERR);
317              msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);          free_if_alloc (buf);
318              return 0;          return -1;
319          }      }
320      }      free_if_alloc (buf);
321    
322      rc = gnupg_access_files ();      /* Check for $APPDATA\winpt\keyserver.conf */
323      if (!start_gpgprefs && rc)      buf = make_special_filename (CSIDL_APPDATA, "winpt\\keyserver.conf", NULL);
324      {  
325          if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS)      conf = get_prog_part ("keyserver.conf", 0);
326          {      if (!file_exist_check (conf))
327              ec = msg_box (NULL,          t = conf;
328                  _("Could not access and/or find the public and secret keyring.\n"      else
329                    "If this is an accident, quit the program and fix it.\n\n"          t = "keyserver.conf";
330                    "Continue if you want that WinPT offers you more choices.\n"),      if (file_exist_check (t) == 0 && file_exist_check (buf) != 0) {
331                    "WinPT", MB_INFO|MB_YESNO);          if (!CopyFile (t, buf, FALSE)) {
332              if (ec == IDYES)              MessageBox (NULL, _("Failed to copy the keyserver.conf"),
333                  first_start = 1;                          _("Keyserver"), MB_ERR);
334          }              free_if_alloc (buf);
335          if (!first_start)              return -1;
336          {          }
337              msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);          t = buf;
338              return 0;      }
339          }      else
340      }          t = buf;
341        
342      if (!first_start)      rc = kserver_load_conf (t);
343      {      if (rc && !quiet)
344          rc = gpg_check_permissions (1);          msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);
345          if (rc && rc == 2)      else {
346              gpg_read_only = 1;          free_if_alloc (reg_prefs.kserv_conf);
347          else if (rc)          reg_prefs.kserv_conf = m_strdup (t);
348              return 0;      }
349      }      free_if_alloc (buf);
350        return rc;
351      load_gettext ();  }
352      init_gnupg_table ();  
353    
354      nfiles = fm_parse_command_line (cmdline);  /* Check if both keyrings are empty. This indicates that
355      if (nfiles > 0)     WinPT should offer to generate a key pair. */
356          return 0;  static bool
357    check_for_empty_keyrings (bool pub_only)
358      if (cmdline && stristr (cmdline, "--wipe-freespace")) {  {
359          dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,      char *p;
360                              GetDesktopWindow(), space_wipefrees_dlg_proc, NULL,      int n = 0;
361                              _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);  
362          free_gnupg_table ();      p = get_gnupg_keyring (1, 0);
363          return 0;      if (file_exist_check (p) == 0 && get_file_size (p) == 0)
364      }          n++;
365        free_if_alloc (p);
366      load_keyserver_conf (cmdline? 1 : 0);      if (pub_only)
367      if (start_keymanager) {          return n == 1? true : false;
368          dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYMISC,      p = get_gnupg_keyring (0, 0);
369                              GetDesktopWindow(), keymanager_dlg_proc, NULL,      if (file_exist_check (p) == 0 && get_file_size (p) == 0)
370                              _("Key Manager"), IDS_WINPT_KEYMISC);          n++;
371          keycache_release ();      free_if_alloc (p);
372          free_gnupg_table ();      return n==2? true : false;
373          return 0;  }
374      }  
375    
376      if (cmdline && (stristr (cmdline, "--keymanager")  #ifdef WINPT_MOBILE
377                  || stristr (cmdline, "--cardmanager"))) {  /* Enable the mobile mode if possible.
378          update_keycache (GetDesktopWindow ());     There are some constraints which must be fullfilled.
379          if (stristr (cmdline, "keymanager"))     Return value: 0 on success. */
380              dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYMISC,  static int
381                              GetDesktopWindow(), keymanager_dlg_proc, NULL,  enable_mobile_mode (void)
382                              _("Key Manager"), IDS_WINPT_KEYMISC);    {
383          else {      static const char *test_fname = "winpt_mobile_test.txt";
384              gpg_card_t crd = smartcard_init ();      FILE *fp;
385              if (crd)      char *pubring;
386                  dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_EDIT,      ULARGE_INTEGER caller, total;
387                                    GetDesktopWindow(), card_edit_dlg_proc,      DWORD temp_size;
388                                    (LPARAM)crd, _("Card Manager"),  
389                                    IDS_WINPT_CARD_EDIT);      fp = fopen (test_fname, "wb");
390              gpg_card_release (crd);      if (fp == NULL) {
391          }          MessageBox (NULL, "Mobile mode cannot be used without write permission\n"
392          keycache_release ();                            "for the current directory", "WinPT Error", MB_ERR);
393          free_gnupg_table ();              
394          return 0;          return -1;
395      }      }
396        fclose (fp);
397      CreateMutex (NULL, TRUE, PGM_NAME);      DeleteFile (test_fname);
398      if (GetLastError () == ERROR_ALREADY_EXISTS) {      if (file_exist_check ("gpg.exe")) {
399          free_gnupg_table ();          MessageBox (NULL, "The GnuPG program needs to be in the same directory\n"
400          return 0;                            "as the WinPT program", "WinPT Error", MB_ERR);
401      }          return -1;
402        }
403      if (cmdline) {      
404          if (stristr (cmdline, "--enable-debug") || stristr (cmdline, "--debug")) {      /* Because write operations to the keyring result in a temporary
405              gpg_set_debug_mode (1);         file, we need at least 2 MB plus the size of the keyring for
406              winpt_debug_msg ();         free space. */
407              debug = 1;      pubring = get_gnupg_keyring (1);
408          }      temp_size = get_file_size (pubring) + 2097152;
409      }      free_if_alloc (pubring);
410    
411      wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));      if (!GetDiskFreeSpaceEx (NULL, &caller, &total, NULL) ||
412      rc = RegisterClass (&wc);          caller.LowPart < temp_size) {
413      if (rc == FALSE) {          log_box ("WinPT Error", MB_ERR,
414          msg_box (NULL, _("Could not register window class"), _("WinPT Error"), MB_ERR);                   "The mobile mode needs at least %lu KB for temporary files",
415          free_gnupg_table ();                   temp_size/1024);
416          return 0;          return -1;
417      }      }
418    
419      hwnd = CreateWindow (PGM_NAME,      /* XXX: shall we check for 'temp-directory' in the gpg.conf? */
420                           PGM_NAME,  
421                           0, 0, 0, 0, 0,      return 0;
422                           NULL,  }
423                           NULL,  #endif
424                           hinst,  
425                           NULL);  
426      if (hwnd == NULL) {  /* Set the default keyserver for this instance. */
427          msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);  void
428          free_gnupg_table ();  set_default_keyserver (void)
429          return 0;  {
430      }      char *host = get_reg_entry_keyserver ("Default");
431      glob_hwnd = hwnd;      char *str_port = get_reg_entry_keyserver ("Default_Port");
432      UpdateWindow (hwnd);      WORD port = HKP_PORT;
433    
434      if (!first_start && !start_gpgprefs) {      if (!host)
435          gnupg_backup_options ();                  keyserver_set_default (NULL, 0);
436          rc = check_crypto_engine ();      else {
437          if (rc) {          if (str_port && *str_port)
438              DestroyWindow (hwnd);              port = atoi (str_port);
439              free_gnupg_table ();          keyserver_set_default (host, port);
440              return 0;      }
441          }      free_if_alloc (host);
442      }      free_if_alloc (str_port);
443        }
444      if (start_gpgprefs) {  
445          char *ring;  
446          size_t size = 0;  /* Display info message that WinPT is now in debug mode. */
447          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,  void
448                          gpgprefs_dlg_proc, NULL);  winpt_debug_msg (void)
449          ring = get_gnupg_keyring (0, !NO_STRICT);  {      
450          if (gnupg_access_keyring (0) == -1 && get_file_size (ring) == 0)      char output[512];
451              first_start = 1; /* The keyring is empty! */      char temp[128];
452          free_if_alloc (ring);          
453      }      GetTempPath (DIM (temp) -1, temp);
454        _snprintf (output, DIM (output)-1,
455      if (first_start) {          "The GPGME output file is %sgpgme.dbg\n"
456          struct first_start_s fs;          "The WinPT output file is %swinpt.log\n", temp, temp);
457          struct genkey_s c;      MessageBox (NULL, output, "WinPT now runs in DEBUG MODE", MB_INFO);
458          HWND h;  }
459  start:  
460          h = GetDesktopWindow ();  
461          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,  /* Search for insecure ElGamal keys and return the
462                              gpgprefs_dlg_proc, NULL);     number of founded keys. */
463          DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,  static int
464                          first_run_dlg_proc, (LPARAM)&fs);  count_insecure_elgkeys (void)
465          switch (fs.choice) {  {
466          case SETUP_KEYGEN:      gpg_keycache_t pc;
467              c.interactive = 1;      gpgme_key_t key;
468              c.first_start = 1;      int n = 0;
469              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,  
470                                   h, keygen_wizard_dlg_proc, (LPARAM)&c);      pc = keycache_get_ctx (1);
471              if (!rc)      while (!gpg_keycache_next_key (pc, 0, &key)) {
472                  goto start;          if (key->subkeys->pubkey_algo == GPGME_PK_ELG)
473              break;              n++;
474        }
475          case SETUP_IMPORT:      gpg_keycache_rewind (pc);
476              rc = gnupg_copy_keyrings ();      return n;
477              if (rc) {  }
478                  msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);  
479                  goto start;  
480              }  /* Main entry point. */
481              break;  int WINAPI
482    WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
483          case -1:  {
484              DestroyWindow (hwnd);      WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};
485              free_gnupg_table ();      HACCEL accel_tab;
486              return 0;      MSG msg;
487          }      HWND hwnd = NULL;
488          update_keycache (hwnd);      WORD ver[3], ptdver[4];
489          check_crypto_engine ();      const char *s;
490      }      int rc, ec, created = 0;
491      else {      int first_start = 0, start_gpgprefs = 0;
492          gpgme_keycache_t c;      int winpt_inst_found = 0;
493          update_keycache (hwnd);      int start_manager = 0;    
494          c = keycache_get_ctx (1);  
495          if (!c || !gpgme_keycache_count (c)) {  #ifdef WINPT_MOBILE
496              gnupg_display_error ();      /* Do not continue in case of problems. */
497              msg_box (hwnd, _("The keycache was not initialized or is empty.\n"      if (enable_mobile_mode ())
498                               "Please check your GPG config (keyrings, pathes...)"),          return 0;
499                               _("WinPT Error"), MB_ERR);  #endif
500              ec = msg_box (NULL, _("It seems that GPG is not set properly.\n"  
501                                    "Do you want to start the GPG preferences dialog?"),      glob_hinst = hinst;
502                              "WinPT", MB_INFO|MB_YESNO);      if (cmdline && stristr (cmdline, "--stop")) {
503              if (ec == IDYES) {          hwnd = FindWindow ("WinPT", "WinPT");
504                  DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,          if (hwnd != NULL)
505                                  gpgprefs_dlg_proc, NULL);              PostMessage (hwnd, WM_DESTROY, 0, 0);
506                  update_keycache (hwnd);          return 0;
507              }      }
508              else {  
509                  DestroyWindow (hwnd);      #ifdef _DEBUG
510                  free_gnupg_table ();      gpg_set_debug_mode (1);
511                  return 0;      debug = 1;
512              }      #endif
513          }  
514          if (check_default_key (c)) {      get_file_version ("WinPT.exe", &ver[0], &ver[1], &ver[2], &ver[3]);
515              char * p = get_gnupg_default_key ();      ec = get_file_version ("PTD.dll", &ptdver[0], &ptdver[1],  
516              log_box (_("WinPT Error"), MB_ERR,                                   &ptdver[2], &ptdver[3]);
517                       _("Default key from the GPG options file could not be found.\n"      
518                         "Please check your gpg.conf (options) to correct this:\n\n"      if (!ec && (ptdver[0] != ver[0] ||
519                         "%s: public key not found."), p? p : "[null]");                  ptdver[1] != ver[1] ||
520              free_if_alloc (p);                  ptdver[2] != ver[2])) {
521              DestroyWindow (hwnd);          log_box (_("WinPT Error"), MB_ERR,
522              free_gnupg_table ();                   _("The PTD.dll file has a different version than WinPT.exe\n"
523              return 0;                     "Please update the PTD.dll to version %d.%d.%d"),
524          }                     ver[0], ver[1], ver[2]);
525          if (count_insecure_elgkeys ())          return 0;
526              DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,      }
527                              elgamal_warn_dlg_proc, NULL);  
528      }      if (gpg_md_selftest ()) {
529            msg_box (NULL, _("Cryptographic selftest failed."),
530      accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);                   _("WinPT Error"), MB_ERR);
531      keyring_check_last_access (); /* init */          return 0;
532      while (GetMessage (&msg, hwnd, 0, 0)) {      }
533          if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {  
534              TranslateMessage (&msg);      s = gpgme_check_version (NEED_GPGME_VERSION);
535              DispatchMessage (&msg);      if (!s || !*s) {
536          }          msg_box (NULL, _("A newer GPGME version is needed; at least "NEED_GPGME_VERSION),
537      }                   _("WinPT Error"), MB_ERR);
538                    return 0;
539      return 0;      }
540  } /* WinMain */  
541        CreateMutex (NULL, TRUE, PGM_NAME);
542        if (GetLastError () == ERROR_ALREADY_EXISTS)
543            winpt_inst_found = 1;
544        
545        set_default_keyserver ();
546        load_gettext ();
547        admin_user = user_is_admin ();
548    
549        regist_inst_gnupg (1);
550        regist_inst_winpt (1, &created);
551    
552        if (!created) {
553            memset (&reg_prefs, 0, sizeof (reg_prefs));
554            get_reg_winpt_prefs (&reg_prefs);
555            reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */
556            gnupg_load_config ();
557        }
558    
559        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.23  
changed lines
  Added in v.271

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26