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

Contents of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 159 - (show annotations)
Wed Jan 18 13:57:31 2006 UTC (19 years, 1 month ago) by twoaday
File size: 17501 byte(s)
Supress message.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26