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

Annotation of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (hide 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 werner 36 /* 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 werner 42 #ifdef HAVE_CONFIG_H
21     #include <config.h>
22     #endif
23    
24 werner 36 #include <windows.h>
25    
26 werner 47 #include "resource.h"
27 werner 36 #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 werner 48 #include "wptCrypto.h"
42 werner 36
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 twoaday 66 else
131     msg_box (NULL, _("No useable secret key found."), _("WinPT Error"), MB_ERR);
132 werner 36 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 werner 58 if ((ma == 1 && mi >= 4) || ma > 1)
193 werner 36 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 twoaday 41 const char * fm_get_file_type (const char *fname, int *r_type);
243    
244 werner 36 /* 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 twoaday 41 int rc, ec, created = 0, nfiles = 0;
251 werner 36 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 werner 58 #ifdef _DEBUG
260 werner 36 gpg_set_debug_mode (1);
261     debug = 1;
262 werner 58 #endif
263 werner 36
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 twoaday 41 gnupg_load_config ();
307 werner 36 }
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 werner 48 s = get_fileopen_dlg (GetActiveWindow (),
316     _("Select GPG Public Keyring"),
317     _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),
318     NULL);
319 werner 36 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 werner 48
476 werner 36 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
477 twoaday 41 gpgprefs_dlg_proc, 0);
478 werner 36 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 twoaday 41 gpgprefs_dlg_proc, 0);
492 werner 36 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 twoaday 41 gpgprefs_dlg_proc, 0);
535 werner 36 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 twoaday 41 elgamal_warn_dlg_proc, 0);
557 werner 36 }
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