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

Contents of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 128 - (show annotations)
Mon Dec 19 13:05:59 2005 UTC (19 years, 2 months ago) by twoaday
File size: 16472 byte(s)
2005-12-17  Timo Schulz  <ts@g10code.com>
 
        * wptUTF8.cpp: Removed unused charset array.
        * wptSigList.cpp (siglist_build): Increase size for 'class'
        column.
        * wptGPG.cpp (get_gnupg_path): Simplified.
        * WinPT.cpp (load_gpg_env): New.
        (check_crypto_engine): Return type is now bool.
        * wptRegistry.cpp (is_gpg4win_installed): New.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): More consistent
        dialog design.
        * wptKeyManagerDlg.cpp (translate_menu_strings): New.
        (translate_popupmenu_strings): New.
        * wptKeyEditDlgs.cpp (is_jpg_file): New.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26