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

Contents of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 135 - (show annotations)
Mon Jan 9 09:50:55 2006 UTC (19 years, 1 month ago) by twoaday
File size: 16994 byte(s)
Fix GPGME versioning problem.


1 /* WinPT.cpp - Windows Privacy Tray (WinPT)
2 * Copyright (C) 2000-2006 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.2" /* Minimal GPG version. */
44 #define MIN_GPGME_VER NEED_GPGME_VERSION /* Minimal GPGME version. */
45
46
47 HINSTANCE glob_hinst; /* global instance for the dialogs */
48 HWND glob_hwnd; /* global window handle for the dialogs */
49 HWND activ_hwnd;
50 LOCK mo_file;
51 int scard_support = 0;
52 int debug = 0;
53 int mobile = 0;
54 int gpg_read_only = 0;
55 char gpgver[3];
56
57
58 /* Load the key cache and rebuild the signature cache. */
59 static void
60 update_keycache (HWND hwnd)
61 {
62 refresh_cache_s rcs = {0};
63 rcs.kr_reload = 0;
64 rcs.kr_update = 1;
65 rcs.tr_update = 1;
66 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,
67 keycache_dlg_proc, (LPARAM)&rcs);
68 }
69
70
71 /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
72 void
73 gpg_set_debug_mode (int val)
74 {
75 if (val)
76 putenv ("GPGME_DEBUG=5:gpgme.dbg");
77 else
78 putenv ("GPGME_DEBUG=");
79 }
80
81
82 /* Return the name of the gettext language file. */
83 static char*
84 get_gettext_lang (void)
85 {
86 char *fname;
87 fname = get_reg_entry_mo ();
88 if (!fname)
89 return NULL;
90 return fname;
91 }
92
93
94 /* Initialize the gettext sub system. */
95 static void
96 load_gettext (int prev_inst)
97 {
98 char *nls = NULL;
99 char *file = NULL;
100
101 nls = get_gettext_lang ();
102 if (nls) {
103 set_gettext_file ("winpt", nls);
104 file = make_filename (nls, "winpt", "mo");
105 if (!file_exist_check (nls) && init_file_lock (&mo_file, file)) {
106 if (!prev_inst)
107 msg_box (NULL, _("Could not initizalize file lock.\n"
108 "Native Language Support"),
109 _("WinPT Error"), MB_ERR);
110 }
111 free_if_alloc (nls);
112 free_if_alloc (file);
113 }
114 }
115
116
117 /* Load the GPG environment. On the first start, some
118 checks are performed to find out in what state GPG is.
119 Return value: 0 everything OK.
120 >0 fatal error.
121 -1 public keyring is empty or does not exist. */
122 static int
123 load_gpg_env (void)
124 {
125 SECURITY_ATTRIBUTES sec_attr;
126 char *p;
127 char *pkr;
128
129 p = get_reg_entry_gpg4win ("gpg.exe");
130 if (!p)
131 return (1);
132 if (file_exist_check (p)) {
133 free_if_alloc (p);
134 return (1);
135 }
136 free_if_alloc (p);
137 p = multi_gnupg_path (0);
138 if (p && dir_exist_check (p)) {
139 memset (&sec_attr, 0, sizeof (sec_attr));
140 sec_attr.nLength = sizeof (sec_attr);
141 if (!CreateDirectory (p, &sec_attr)) {
142 msg_box (NULL, _("Could not create GPG home directory"),
143 _("WinPT Error"), MB_ERR);
144 free_if_alloc (p);
145 return (2);
146 }
147 }
148 pkr = make_filename (p, "pubring", "gpg");
149 free_if_alloc (p);
150 if (!pkr)
151 return -1;
152 if (get_file_size (pkr) == 0) {
153 free_if_alloc (pkr);
154 return -1;
155 }
156 return 0;
157 }
158
159
160 /* check if the default key from the gpg.conf file is available in the
161 keyring. if not, bail out because encryption won't work properly then. */
162 static int
163 check_default_key (gpg_keycache_t kc)
164 {
165 gpgme_key_t key;
166 gpgme_error_t err = GPG_ERR_NO_ERROR;
167 char *defkey;
168
169 defkey = get_gnupg_default_key ();
170 if (defkey)
171 err = gpg_keycache_find_key (kc, defkey, 0, &key);
172 else
173 msg_box (NULL, _("No useable secret key found."),
174 _("WinPT Error"), MB_ERR);
175 free_if_alloc (defkey);
176 return err? -1 : 0;
177 }
178
179
180 /* Return the WinPT program file name (with full pathname). */
181 static const char*
182 get_prog_part (const char * fname, int use_cwd)
183 {
184 static char program[512];
185 char currdir[256];
186 char *cmd = NULL;
187 int j;
188
189 memset (currdir, 0, DIM (currdir));
190 memset (program, 0, DIM (program));
191
192 if (use_cwd) {
193 GetCurrentDirectory (DIM (currdir)-1, currdir);
194 _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);
195 }
196 else {
197 cmd = GetCommandLine ();
198 if (cmd == NULL)
199 return NULL;
200 strncpy (currdir, cmd, sizeof (currdir)-1);
201 j = strlen (currdir);
202 while (j--) {
203 if (currdir[j] == '\\')
204 break;
205 }
206 currdir[j] = 0;
207 _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);
208 }
209 return program;
210 }
211
212
213 /* Check that the underlying crypto engine fullfills the minimal
214 requirements so all commands work properly. */
215 static bool
216 check_crypto_engine (void)
217 {
218 int ma=1, mi=4, pa=2; /* GPG 1.4.2 */
219 int rc;
220
221 rc = check_gnupg_engine (&ma, &mi, &pa);
222 if (rc == -1) {
223 msg_box (NULL, _("Could not read GnuPG version."),
224 _("WinPT Error"), MB_ERR);
225 return false;
226 }
227 else if (rc) {
228 log_box (_("WinPT Error"), MB_ERR,
229 _("Sorry, you need a newer GPG version.\n"
230 "GPG version %d.%d.%d required GPG version "MIN_GPG_VER),
231 ma, mi, pa);
232 return false;
233 }
234 /* We enable smartcard support for GPG: >= 2 or >= 1.4.3 */
235 if (ma > 1 || pa >= 3)
236 scard_support = 1;
237
238 gpgver[0] = ma;
239 gpgver[1] = mi;
240 gpgver[2] = pa;
241 return true;
242 }
243
244
245 /* Try to load the keyserver config file. If @quiet is 1
246 do not show any errors. */
247 static int
248 load_keyserver_conf (int quiet)
249 {
250 const char *t;
251 int rc;
252
253 if (reg_prefs.kserv_conf)
254 t = reg_prefs.kserv_conf;
255 else if (!file_exist_check (get_prog_part ("keyserver.conf", 0)))
256 t = get_prog_part ("keyserver.conf", 0);
257 else
258 t = "keyserver.conf";
259 rc = kserver_load_conf (t);
260 if (rc && !quiet)
261 msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);
262 return rc;
263 }
264
265
266 /* Check if both keyrings are empty. This indicates that
267 WinPT should offer to generate a key pair. */
268 static bool
269 check_for_empty_keyrings (bool pub_only)
270 {
271 char *p;
272 int n = 0;
273
274 p = get_gnupg_keyring (1, 0);
275 if (file_exist_check (p) == 0 && get_file_size (p) == 0)
276 n++;
277 free_if_alloc (p);
278 if (pub_only)
279 return n == 1? true : false;
280 p = get_gnupg_keyring (0, 0);
281 if (file_exist_check (p) == 0 && get_file_size (p) == 0)
282 n++;
283 free_if_alloc (p);
284 return n==2? true : false;
285 }
286
287
288 /* Enable the mobility mode. */
289 static void
290 enable_mobile_mode (void)
291 {
292 memset (&reg_prefs, 0, sizeof (reg_prefs));
293 reg_prefs.always_trust = 0;
294 reg_prefs.auto_backup = 0;
295 reg_prefs.cache_time = 0;
296 reg_prefs.expert = 0;
297 reg_prefs.keylist_mode = 1;
298 reg_prefs.kserv_conf = m_strdup ("keyserver.conf");
299 reg_prefs.no_zip_mmedia = 1;
300 reg_prefs.use_tmpfiles = 1;
301 reg_prefs.word_wrap = 80;
302 reg_prefs.use_viewer = 0; /* XXX */
303 }
304
305
306 /* Main entry point. */
307 int WINAPI
308 WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
309 {
310 WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};
311 HACCEL accel_tab;
312 MSG msg;
313 HWND hwnd = NULL;
314 WORD ver[3], ptdver[4];
315 int rc, ec, created = 0;
316 int first_start = 0, start_gpgprefs = 0;
317 int winpt_inst_found = 0;
318 int start_manager = 0;
319 const char *s;
320
321 glob_hinst = hinst;
322 if (cmdline && stristr (cmdline, "--stop")) {
323 hwnd = FindWindow ("WinPT", "WinPT");
324 if (hwnd != NULL)
325 PostMessage (hwnd, WM_DESTROY, 0, 0);
326 return 0;
327 }
328
329 /*
330 OSVERSIONINFO osinf;
331 memset (&osinf, 0, sizeof (osinf));
332 if (GetVersionEx (&osinf) &&
333 osinf.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
334 osinf.dwMinorVersion == 0) {
335 msg_box (NULL, "WinPT propably does not work on Windows 95 without restrictions",
336 "WinPT Warning", MB_INFO);
337 }
338 */
339
340 #ifdef _DEBUG
341 gpg_set_debug_mode (1);
342 debug = 1;
343 #endif
344
345 get_file_version ("WinPT.exe", &ver[0], &ver[1], &ver[2], &ver[3]);
346 get_file_version ("PTD.dll", &ptdver[0], &ptdver[1],
347 &ptdver[2], &ptdver[3]);
348 /* XXX
349 if (ptdver[0] != ver[0] || ptdver[1] != ver[1]|| ptdver[2] != ver[2]) {
350 log_box (_("WinPT Error"), MB_ERR,
351 _("The PTD.dll file has a different version than WinPT.exe\n"
352 "Please update the PTD.dll to version %d.%d.%d"),
353 ver[0], ver[1], ver[2]);
354 return 0;
355 }
356 */
357
358 if (gpg_md_selftest ()) {
359 msg_box (NULL, _("Cryptographic selftest failed."),
360 _("WinPT Error"), MB_ERR);
361 return 0;
362 }
363
364 s = gpgme_check_version (MIN_GPGME_VER);
365 if (!s || !*s) {
366 msg_box (NULL, _("A newer GPGME version is needed; at least "MIN_GPGME_VER),
367 _("WinPT Error"), MB_ERR);
368 return 0;
369 }
370
371 CreateMutex (NULL, TRUE, PGM_NAME);
372 if (GetLastError () == ERROR_ALREADY_EXISTS)
373 winpt_inst_found = 1;
374
375 if (cmdline && stristr (cmdline, "--mobile")) {
376 msg_box (NULL, "WARNING: mobile modus is not fully implemented yet!",
377 "WinPT", MB_INFO);
378 mobile = 1;
379 }
380
381 set_default_kserver ();
382 load_gettext (winpt_inst_found);
383
384 if (!mobile) {
385 regist_inst_gnupg (1);
386 regist_inst_winpt (1, &created);
387 }
388 else {
389 enable_mobile_mode ();
390 /* XXX: ask for GPG path */
391 created = 1; /* Disable registry writing */
392 }
393
394 if (!created) {
395 memset (&reg_prefs, 0, sizeof (reg_prefs));
396 reg_prefs.use_tmpfiles = 1; /* default */
397 reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */
398 get_reg_winpt_prefs (&reg_prefs);
399 if (!reg_prefs.no_hotkeys)
400 hotkeys_modify ();
401 gnupg_load_config ();
402 }
403
404 if (is_gpg4win_installed ())
405 load_gpg_env (); /* XXX: check return code. */
406
407 rc = gnupg_check_homedir ();
408 if (rc) {
409 log_box (_("WinPT Error"), MB_ERR,
410 _("GPG home directory is not set correctly.\n"
411 "Please check the GPG registry settings:\n%s."),
412 winpt_strerror (rc));
413 s = get_fileopen_dlg (GetActiveWindow (),
414 _("Select GPG Public Keyring"),
415 _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),
416 NULL);
417 if (s != NULL) {
418 size_t n;
419 char *p = strrchr (s, '\\');
420 if (!p)
421 BUG (0);
422 n = p - s;
423 if (n) {
424 char *file = new char[n+1];
425 if (!file)
426 BUG (NULL);
427 memset (file, 0, n);
428 memcpy (file, s, n);
429 file[n] = '\0';
430 set_reg_entry_gpg ("HomeDir", file);
431 free_if_alloc (file);
432 gnupg_check_homedir (); /* change gpgProgram if needed */
433 }
434 }
435 else {
436 msg_box (NULL, _("GPG home directory could not be determited."),
437 _("WinPT Error"), MB_ERR);
438 goto start;
439 }
440 }
441
442 rc = check_gnupg_prog ();
443 if (rc) {
444 if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"
445 "Do you want to start the GPG preferences to "
446 "correct this problem?"), _("WinPT Error"),
447 MB_INFO|MB_YESNO) == IDYES)
448 start_gpgprefs = 1;
449 else {
450 msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
451 return 0;
452 }
453 }
454
455 rc = gnupg_access_files ();
456 if (!start_gpgprefs && rc) {
457 if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS) {
458 ec = msg_box (NULL,
459 _("Could not access and/or find the public and secret keyring.\n"
460 "If this is an accident, quit the program and fix it.\n\n"
461 "Continue if you want that WinPT offers you more choices.\n"),
462 "WinPT", MB_INFO|MB_YESNO);
463 if (ec == IDYES)
464 first_start = 1;
465 }
466 if (!first_start) {
467 msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
468 return 0;
469 }
470 }
471 if (check_for_empty_keyrings (false))
472 first_start = 1;
473
474 if (!first_start) {
475 rc = gpg_check_permissions (1);
476 if (rc && rc == 2)
477 gpg_read_only = 1;
478 else if (rc)
479 return 0;
480 }
481
482 init_gnupg_table ();
483
484 if (fm_parse_command_line (cmdline) > 0) {
485 free_gnupg_table ();
486 return 0;
487 }
488
489 if (cmdline && stristr (cmdline, "--wipe-freespace")) {
490 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,
491 GetDesktopWindow(), space_wipefrees_dlg_proc, 0,
492 _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);
493 free_gnupg_table ();
494 return 0;
495 }
496
497 load_keyserver_conf (cmdline? 1 : 0);
498
499 if (cmdline && (stristr (cmdline, "--keymanager")
500 || stristr (cmdline, "--cardmanager"))) {
501 /* If an instance of WinPT is running, just send the command
502 to open the key manager. Otherwise start a new instance.
503 */
504 HWND tray = FindWindow ("WinPT", "WinPT");
505 if (stristr (cmdline, "keymanager"))
506 start_manager = ID_WINPT_KEY;
507 else
508 start_manager = ID_WINPT_CARD;
509 if (tray != NULL) {
510 PostMessage (tray, WM_COMMAND, start_manager, 0);
511 free_gnupg_table ();
512 return 0;
513 }
514 }
515
516 /* If we found another WinPT instance, just quit to avoid it
517 will be executed twice. */
518 if (winpt_inst_found) {
519 log_debug ("%s", "WinMain: WinPT is already running.");
520 free_gnupg_table ();
521 return 0;
522 }
523
524 if (cmdline) {
525 if (stristr (cmdline, "--enable-debug") ||
526 stristr (cmdline, "--debug")) {
527 gpg_set_debug_mode (1);
528 winpt_debug_msg ();
529 debug = 1;
530 }
531 }
532
533 wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));
534 rc = RegisterClass (&wc);
535 if (rc == FALSE) {
536 msg_box (NULL, _("Could not register window class"),
537 _("WinPT Error"), MB_ERR);
538 free_gnupg_table ();
539 return 0;
540 }
541
542 hwnd = CreateWindow (PGM_NAME,
543 PGM_NAME,
544 0, 0, 0, 0, 0,
545 NULL,
546 NULL,
547 hinst,
548 NULL);
549 if (hwnd == NULL) {
550 msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);
551 free_gnupg_table ();
552 return 0;
553 }
554 glob_hwnd = hwnd;
555 UpdateWindow (hwnd);
556
557 if (!first_start && !start_gpgprefs) {
558 gnupg_backup_options ();
559 if (!check_crypto_engine ()) {
560 DestroyWindow (hwnd);
561 free_gnupg_table ();
562 return 0;
563 }
564 }
565
566 if (start_gpgprefs) {
567 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
568 gpgprefs_dlg_proc, 0);
569 if (check_for_empty_keyrings (true))
570 first_start = 1; /* The public keyring is empty! */
571 }
572
573 if (first_start) {
574 struct first_start_s fs;
575 struct genkey_s c;
576 HWND h;
577 start:
578 h = GetDesktopWindow ();
579 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,
580 gpgprefs_dlg_proc, 0);
581 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,
582 first_run_dlg_proc, (LPARAM)&fs);
583 switch (fs.choice) {
584 case SETUP_KEYGEN:
585 c.interactive = 1;
586 c.first_start = 1;
587 rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,
588 h, keygen_wizard_dlg_proc, (LPARAM)&c);
589 if (!rc)
590 goto start;
591 break;
592
593 case SETUP_IMPORT:
594 rc = gnupg_copy_keyrings ();
595 if (rc) {
596 msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
597 goto start;
598 }
599 break;
600
601 case -1: /* Cancel/Abort. */
602 DestroyWindow (hwnd);
603 free_gnupg_table ();
604 return 0;
605 }
606 update_keycache (hwnd);
607 check_crypto_engine ();
608 }
609 else {
610 gpg_keycache_t c;
611 update_keycache (hwnd);
612 c = keycache_get_ctx (1);
613 if (!c || !gpg_keycache_get_size (c)) {
614 gnupg_display_error ();
615 msg_box (hwnd, _("The keycache was not initialized or is empty.\n"
616 "Please check your GPG config (keyrings, pathes...)"),
617 _("WinPT Error"), MB_ERR);
618 ec = msg_box (NULL, _("It seems that GPG is not set properly.\n"
619 "Do you want to start the GPG preferences dialog?"),
620 "WinPT", MB_INFO|MB_YESNO);
621 if (ec == IDYES) {
622 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
623 gpgprefs_dlg_proc, 0);
624 update_keycache (hwnd);
625 }
626 else {
627 DestroyWindow (hwnd);
628 free_gnupg_table ();
629 return 0;
630 }
631 }
632 if (check_default_key (c)) {
633 char *p = get_gnupg_default_key ();
634 log_box (_("WinPT Error"), MB_ERR,
635 _("Default key from the GPG options file could not be found.\n"
636 "Please check your gpg.conf (options) to correct this:\n\n"
637 "%s: public key not found."), p? p : "[null]");
638 free_if_alloc (p);
639 DestroyWindow (hwnd);
640 free_gnupg_table ();
641 return 0;
642 }
643 if (count_insecure_elgkeys ())
644 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,
645 elgamal_warn_dlg_proc, 0);
646 }
647
648 if (start_manager)
649 PostMessage (hwnd, WM_COMMAND, start_manager, 0);
650
651 accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);
652 keyring_check_last_access (); /* init */
653 while (GetMessage (&msg, hwnd, 0, 0)) {
654 if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {
655 TranslateMessage (&msg);
656 DispatchMessage (&msg);
657 }
658 }
659
660 return 0;
661 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26