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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26