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

Contents of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (show annotations)
Thu Nov 3 17:55:18 2005 UTC (19 years, 3 months ago) by twoaday
File size: 14701 byte(s)
Fix crash in the GPG preference dialog.
Allow to have an empty secret keyring.


1 /* WinPT.cpp - Windows Privacy Tray (WinPT)
2 * Copyright (C) 2000-2005 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * 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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with WinPT; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <windows.h>
25
26 #include "resource.h"
27 #include "wptTypes.h"
28 #include "wptW32API.h"
29 #include "wptVersion.h"
30 #include "wptErrors.h"
31 #include "wptGPG.h"
32 #include "wptRegistry.h"
33 #include "wptCommonCtl.h"
34 #include "wptDlgs.h"
35 #include "wptNLS.h"
36 #include "wptKeyserver.h"
37 #include "wptCard.h"
38 #include "wptFileManager.h"
39 #include "wptContext.h"
40 #include "wptCardEdit.h"
41 #include "wptCrypto.h"
42
43 #define MIN_GPG_VER "1.4.3" /* Minimal GPG version. */
44 #define MIN_GPGME_VER "1.2.0" /* Minimal GPGME version. */
45 #define MIN_PTD_VER "0.8.1" /* Minimal PTD version. */
46
47
48 HINSTANCE glob_hinst; /* global instance for the dialogs */
49 HWND glob_hwnd; /* global window handle for the dialogs */
50 HWND activ_hwnd;
51 LOCK mo_file;
52 int scard_support = 0;
53 int debug = 0;
54 int mobile = 0;
55 int gpg_read_only = 0;
56 char gpgver[3];
57
58
59 /* Load the key cache and rebuild the signature cache. */
60 static void
61 update_keycache (HWND hwnd)
62 {
63 refresh_cache_s rcs = {0};
64 rcs.kr_reload = 0;
65 rcs.kr_update = 1;
66 rcs.tr_update = 1;
67 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,
68 keycache_dlg_proc, (LPARAM)&rcs);
69 }
70
71
72 /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
73 void
74 gpg_set_debug_mode (int val)
75 {
76 if (val)
77 putenv ("GPGME_DEBUG=5:gpgme.dbg");
78 else
79 putenv ("GPGME_DEBUG=");
80 }
81
82
83 /* Return the name of the gettext language file. */
84 static char*
85 get_gettext_lang (void)
86 {
87 char *fname;
88 fname = get_reg_entry_mo ();
89 if (!fname)
90 return NULL;
91 return fname;
92 }
93
94
95 /* Initialize the gettext sub system. */
96 static void
97 load_gettext (int prev_inst)
98 {
99 char *nls = NULL;
100 char *file = NULL;
101
102 nls = get_gettext_lang ();
103 if (nls) {
104 set_gettext_file ("winpt", nls);
105 file = make_filename (nls, "winpt", "mo");
106 if (!file_exist_check (nls) && init_file_lock (&mo_file, file)) {
107 if (!prev_inst)
108 msg_box (NULL, _("Could not initizalize file lock.\n"
109 "Native Language Support"),
110 _("WinPT Error"), MB_ERR);
111 }
112 free_if_alloc (nls);
113 free_if_alloc (file);
114 }
115 }
116
117
118 /* check if the default key from the gpg.conf file is available in the
119 keyring. if not, bail out because encryption won't work properly then. */
120 static int
121 check_default_key (gpg_keycache_t kc)
122 {
123 gpgme_key_t key;
124 gpgme_error_t err = GPG_ERR_NO_ERROR;
125 char * defkey;
126
127 defkey = get_gnupg_default_key ();
128 if (defkey)
129 err = gpg_keycache_find_key (kc, defkey, 0, &key);
130 else
131 msg_box (NULL, _("No useable secret key found."), _("WinPT Error"), MB_ERR);
132 free_if_alloc (defkey);
133 return err? -1 : 0;
134 }
135
136
137 /* Return the WinPT program file name (with full pathname). */
138 static const char *
139 get_prog_part (const char * fname, int use_cwd)
140 {
141 static char program[512];
142 char currdir[256];
143 char *cmd = NULL;
144 int j;
145
146 memset (currdir, 0, DIM (currdir));
147 memset (program, 0, DIM (program));
148
149 if (use_cwd) {
150 GetCurrentDirectory (DIM (currdir)-1, currdir);
151 _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);
152 }
153 else {
154 cmd = GetCommandLine ();
155 if (cmd == NULL)
156 return NULL;
157 strncpy (currdir, cmd, sizeof (currdir)-1);
158 j = strlen (currdir);
159 while (j--) {
160 if (currdir[j] == '\\')
161 break;
162 }
163 currdir[j] = 0;
164 _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);
165 }
166 return program;
167 }
168
169
170 /* Check that the underlying crypto engine fullfills the minimal
171 requirements so all commands work properly. */
172 static int
173 check_crypto_engine (void)
174 {
175 int ma=1, mi=4, pa=3; /* GPG 1.4.3 */
176 int rc;
177
178 rc = check_gnupg_engine (&ma, &mi, &pa);
179 if (rc == -1) {
180 msg_box (NULL, _("Could not read GnuPG version."),
181 _("WinPT Error"), MB_ERR);
182 return rc;
183 }
184 else if (rc) {
185 log_box (_("WinPT Error"), MB_ERR,
186 _("Sorry, you need a newer GPG version.\n"
187 "GPG version %d.%d.%d required GPG version "MIN_GPG_VER),
188 ma, mi, pa);
189 return rc;
190 }
191 /* We enable smartcard support for GPG: 1.9 or >= 1.4 */
192 if ((ma == 1 && mi >= 4) || ma > 1)
193 scard_support = 1;
194
195 gpgver[0] = ma;
196 gpgver[1] = mi;
197 gpgver[2] = pa;
198 return rc;
199 }
200
201
202 /* Try to load the keyserver config file. If @quiet is 1
203 do not show any errors. */
204 static int
205 load_keyserver_conf (int quiet)
206 {
207 const char * t;
208 int rc;
209
210 if (reg_prefs.kserv_conf)
211 t = reg_prefs.kserv_conf;
212 else if (!file_exist_check (get_prog_part ("keyserver.conf", 0)))
213 t = get_prog_part ("keyserver.conf", 0);
214 else
215 t = "keyserver.conf";
216 rc = kserver_load_conf (t);
217 if (rc && !quiet)
218 msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);
219 return rc;
220 }
221
222
223 /* Enable the mobility mode. */
224 static void
225 enable_mobile_mode (void)
226 {
227 memset (&reg_prefs, 0, sizeof (reg_prefs));
228 reg_prefs.always_trust = 0;
229 reg_prefs.auto_backup = 0;
230 reg_prefs.cache_time = 0;
231 reg_prefs.expert = 0;
232 reg_prefs.keylist_mode = 1;
233 reg_prefs.kserv_conf = m_strdup ("keyserver.conf");
234 reg_prefs.no_zip_mmedia = 1;
235 reg_prefs.use_tmpfiles = 1;
236 reg_prefs.word_wrap = 80;
237 reg_prefs.use_viewer = 0; /* XXX */
238 }
239
240 char* multi_gnupg_path (void);
241
242 const char * fm_get_file_type (const char *fname, int *r_type);
243
244 /* Main entry point. */
245 int WINAPI
246 WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
247 {
248 WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};
249 HACCEL accel_tab;
250 int rc, ec, created = 0, nfiles = 0;
251 int first_start = 0, start_gpgprefs = 0;
252 int winpt_inst_found = 0;
253 const char *s;
254 MSG msg;
255 HWND hwnd = NULL;
256
257 glob_hinst = hinst;
258
259 #ifdef _DEBUG
260 gpg_set_debug_mode (1);
261 debug = 1;
262 #endif
263
264 if (gpg_md_selftest ()) {
265 msg_box (NULL, _("Cryptographic selftest failed."),
266 _("WinPT Error"), MB_ERR);
267 return 0;
268 }
269
270 s = gpgme_check_version (MIN_GPGME_VER);
271 if (!s || !*s) {
272 msg_box (NULL, _("A newer GPGME version is needed; at least "MIN_GPGME_VER),
273 _("WinPT Error"), MB_ERR);
274 return 0;
275 }
276
277 CreateMutex (NULL, TRUE, PGM_NAME);
278 if (GetLastError () == ERROR_ALREADY_EXISTS)
279 winpt_inst_found = 1;
280
281 if (cmdline && stristr (cmdline, "--mobile")) {
282 msg_box (NULL, "WARNING: mobile modus is not fully implemented yet!",
283 "WinPT", MB_INFO);
284 mobile = 1;
285 }
286
287 set_default_kserver ();
288
289 if (!mobile) {
290 regist_inst_gnupg (1);
291 regist_inst_winpt (1, &created);
292 }
293 else {
294 enable_mobile_mode ();
295 /* XXX: ask for GPG path */
296 created = 1; /* Disable registry writing */
297 }
298
299 if (!created) {
300 memset (&reg_prefs, 0, sizeof (reg_prefs));
301 reg_prefs.use_tmpfiles = 1; /* default */
302 reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */
303 get_reg_winpt_prefs (&reg_prefs);
304 if (!reg_prefs.no_hotkeys)
305 hotkeys_modify ();
306 gnupg_load_config ();
307 }
308
309 rc = gnupg_check_homedir ();
310 if (rc) {
311 log_box (_("WinPT Error"), MB_ERR,
312 _("GPG home directory is not set correctly.\n"
313 "Please check the GPG registry settings:\n%s."),
314 winpt_strerror (rc));
315 s = get_fileopen_dlg (GetActiveWindow (),
316 _("Select GPG Public Keyring"),
317 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),
318 NULL);
319 if (s != NULL) {
320 size_t n;
321 char * p = strrchr (s, '\\');
322 if (!p)
323 BUG (0);
324 n = p - s;
325 if (n) {
326 char * file = new char[n+1];
327 if (!file)
328 BUG (NULL);
329 memset (file, 0, n);
330 memcpy (file, s, n);
331 file[n] = '\0';
332 set_reg_entry_gpg ("HomeDir", file);
333 free_if_alloc (file);
334 gnupg_check_homedir (); /* change gpgProgram if needed */
335 }
336 }
337 else {
338 msg_box (NULL, _("GPG home directory could not be determited."),
339 _("WinPT Error"), MB_ERR);
340 goto start;
341 }
342 }
343
344 rc = check_gnupg_prog ();
345 if (rc) {
346 if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"
347 "Do you want to start the GPG preferences to "
348 "correct this problem?"), _("WinPT Error"),
349 MB_INFO|MB_YESNO) == IDYES)
350 start_gpgprefs = 1;
351 else
352 {
353 msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
354 return 0;
355 }
356 }
357
358 rc = gnupg_access_files ();
359 if (!start_gpgprefs && rc) {
360 if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS) {
361 ec = msg_box (NULL,
362 _("Could not access and/or find the public and secret keyring.\n"
363 "If this is an accident, quit the program and fix it.\n\n"
364 "Continue if you want that WinPT offers you more choices.\n"),
365 "WinPT", MB_INFO|MB_YESNO);
366 if (ec == IDYES)
367 first_start = 1;
368 }
369 if (!first_start) {
370 msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
371 return 0;
372 }
373 }
374
375 if (!first_start) {
376 rc = gpg_check_permissions (1);
377 if (rc && rc == 2)
378 gpg_read_only = 1;
379 else if (rc)
380 return 0;
381 }
382
383 load_gettext (winpt_inst_found);
384 init_gnupg_table ();
385
386 nfiles = fm_parse_command_line (cmdline);
387 if (nfiles > 0) {
388 free_gnupg_table ();
389 return 0;
390 }
391
392 if (cmdline && stristr (cmdline, "--wipe-freespace")) {
393 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,
394 GetDesktopWindow(), space_wipefrees_dlg_proc, NULL,
395 _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);
396 free_gnupg_table ();
397 return 0;
398 }
399
400 load_keyserver_conf (cmdline? 1 : 0);
401
402 if (cmdline && (stristr (cmdline, "--keymanager")
403 || stristr (cmdline, "--cardmanager"))) {
404 update_keycache (GetDesktopWindow ());
405 if (stristr (cmdline, "keymanager"))
406 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYMISC,
407 GetDesktopWindow(), keymanager_dlg_proc, NULL,
408 _("Key Manager"), IDS_WINPT_KEYMISC);
409 else {
410 gpg_card_t crd = gpg_card_load ();
411 if (crd)
412 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_EDIT,
413 GetDesktopWindow(), card_edit_dlg_proc,
414 (LPARAM)crd, _("Card Manager"),
415 IDS_WINPT_CARD_EDIT);
416 gpg_card_release (crd);
417 }
418 keycache_release (0);
419 free_gnupg_table ();
420 return 0;
421 }
422
423 /* If we found another WinPT instance, just quit to avoid it
424 will be executed twice. */
425 if (winpt_inst_found) {
426 log_debug ("%s", "WinMain: WinPT is already running.");
427 free_gnupg_table ();
428 return 0;
429 }
430
431 if (cmdline) {
432 if (stristr (cmdline, "--enable-debug") || stristr (cmdline, "--debug")) {
433 gpg_set_debug_mode (1);
434 winpt_debug_msg ();
435 debug = 1;
436 }
437 }
438
439 wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));
440 rc = RegisterClass (&wc);
441 if (rc == FALSE) {
442 msg_box (NULL, _("Could not register window class"),
443 _("WinPT Error"), MB_ERR);
444 free_gnupg_table ();
445 return 0;
446 }
447
448 hwnd = CreateWindow (PGM_NAME,
449 PGM_NAME,
450 0, 0, 0, 0, 0,
451 NULL,
452 NULL,
453 hinst,
454 NULL);
455 if (hwnd == NULL) {
456 msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);
457 free_gnupg_table ();
458 return 0;
459 }
460 glob_hwnd = hwnd;
461 UpdateWindow (hwnd);
462
463 if (!first_start && !start_gpgprefs) {
464 gnupg_backup_options ();
465 rc = check_crypto_engine ();
466 if (rc) {
467 DestroyWindow (hwnd);
468 free_gnupg_table ();
469 return 0;
470 }
471 }
472
473 if (start_gpgprefs) {
474 char *ring;
475
476 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
477 gpgprefs_dlg_proc, 0);
478 ring = get_gnupg_keyring (0, !NO_STRICT);
479 if (gnupg_access_keyring (0) == -1 && get_file_size (ring) == 0)
480 first_start = 1; /* The keyring is empty! */
481 free_if_alloc (ring);
482 }
483
484 if (first_start) {
485 struct first_start_s fs;
486 struct genkey_s c;
487 HWND h;
488 start:
489 h = GetDesktopWindow ();
490 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,
491 gpgprefs_dlg_proc, 0);
492 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,
493 first_run_dlg_proc, (LPARAM)&fs);
494 switch (fs.choice) {
495 case SETUP_KEYGEN:
496 c.interactive = 1;
497 c.first_start = 1;
498 rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,
499 h, keygen_wizard_dlg_proc, (LPARAM)&c);
500 if (!rc)
501 goto start;
502 break;
503
504 case SETUP_IMPORT:
505 rc = gnupg_copy_keyrings ();
506 if (rc) {
507 msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
508 goto start;
509 }
510 break;
511
512 case -1:
513 DestroyWindow (hwnd);
514 free_gnupg_table ();
515 return 0;
516 }
517 update_keycache (hwnd);
518 check_crypto_engine ();
519 }
520 else {
521 gpg_keycache_t c;
522 update_keycache (hwnd);
523 c = keycache_get_ctx (1);
524 if (!c || !gpg_keycache_get_size (c)) {
525 gnupg_display_error ();
526 msg_box (hwnd, _("The keycache was not initialized or is empty.\n"
527 "Please check your GPG config (keyrings, pathes...)"),
528 _("WinPT Error"), MB_ERR);
529 ec = msg_box (NULL, _("It seems that GPG is not set properly.\n"
530 "Do you want to start the GPG preferences dialog?"),
531 "WinPT", MB_INFO|MB_YESNO);
532 if (ec == IDYES) {
533 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
534 gpgprefs_dlg_proc, 0);
535 update_keycache (hwnd);
536 }
537 else {
538 DestroyWindow (hwnd);
539 free_gnupg_table ();
540 return 0;
541 }
542 }
543 if (check_default_key (c)) {
544 char * p = get_gnupg_default_key ();
545 log_box (_("WinPT Error"), MB_ERR,
546 _("Default key from the GPG options file could not be found.\n"
547 "Please check your gpg.conf (options) to correct this:\n\n"
548 "%s: public key not found."), p? p : "[null]");
549 free_if_alloc (p);
550 DestroyWindow (hwnd);
551 free_gnupg_table ();
552 return 0;
553 }
554 if (count_insecure_elgkeys ())
555 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,
556 elgamal_warn_dlg_proc, 0);
557 }
558
559 accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);
560 keyring_check_last_access (); /* init */
561 while (GetMessage (&msg, hwnd, 0, 0)) {
562 if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {
563 TranslateMessage (&msg);
564 DispatchMessage (&msg);
565 }
566 }
567
568 return 0;
569 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26