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

Contents of /trunk/Src/wptKeyserverDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 117 - (show annotations)
Thu Dec 8 09:26:32 2005 UTC (19 years, 2 months ago) by twoaday
File size: 16604 byte(s)
2005-12-07  Timo Schulz  <ts@g10code.com>
 
        * wptOwnertrustDlg.cpp (ownertrust_dlg_proc):
        Use 'Close' instead of 'Exit'.
        * wptKeyEditDlgs.cpp (keyedit_dlg_proc): Likewise.
        * wptGPG.cpp (gnupg_backup_keyrings): Use $APPDATA
        as the destination dir. Thanks to Werner.
        * wptRegistry.cpp (is_gpgee_installed): New.
        (regist_inst_winpt): Do not register file extensions
        if GPGee is available.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Limit
        use of local vars.
        * wptPreferencesDlg.cpp (prefs_dlg_proc): Make sure
        no illegal backup mode is saved.
        * wptKeyserverDlg.cpp (show_imported_key): New.
        (hkp_recv_key2): Show imported keys if the blob
        contained more than one.
         


1 /* wptKeyserverDlg.cpp - Keyserver dialog
2 * Copyright (C) 2000-2005 Timo Schulz
3 * Copyright (C) 2005 g10 Code GmbH
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <windows.h>
26 #include <commctrl.h>
27 #include <malloc.h>
28
29 #include "resource.h"
30 #include "wptKeyserver.h"
31 #include "wptErrors.h"
32 #include "wptTypes.h"
33 #include "wptCommonCtl.h"
34 #include "wptNLS.h"
35 #include "wptW32API.h"
36 #include "wptVersion.h"
37 #include "wptGPG.h"
38 #include "wptKeyManager.h"
39 #include "wptContext.h" /* for passphrase_s */
40 #include "wptDlgs.h"
41
42
43 #define MAX_KEYSIZE 70000
44
45 char* get_reg_entry_keyserver (const char *);
46 int set_reg_entry_keyserver (const char *, const char *);
47
48
49 /* Print out keyserver error and a possible Winsock error. */
50 static void
51 hkp_err_box (HWND dlg, const char *host, WORD port, int rc)
52 {
53 const char *err = kserver_strerror ();
54
55 log_box (_("Keyserver"), MB_ERR, "%s:%d: %s",
56 host, port, winpt_strerror (rc));
57 if (err)
58 msg_box (dlg, err, wsock_strerror (), MB_ERR);
59 }
60
61
62 /* Send the extracted key with keyid @pattern to the
63 keyserver @kserver (port @port).
64 Return value: 0 on success. */
65 int
66 hkp_send_key (HWND dlg, const char *kserver, WORD port, const char *pattern)
67 {
68 gpgme_ctx_t ctx;
69 gpgme_data_t keydata;
70 gpgme_error_t ec;
71 char *rawkey = NULL;
72 char msg[384];
73 size_t n;
74
75 ec = gpgme_new (&ctx);
76 if (ec)
77 BUG (NULL);
78 gpgme_set_armor (ctx, 1);
79 ec = gpgme_data_new (&keydata);
80 if (ec)
81 BUG (NULL);
82 ec = gpgme_op_export (ctx, pattern, 0, keydata);
83 if (ec) {
84 msg_box (dlg, gpgme_strerror (ec), _("Export"), MB_ERR);
85 goto leave;
86 }
87 rawkey = gpgme_data_release_and_get_mem (keydata, &n);
88 ec = kserver_sendkey (kserver, port, rawkey, n);
89 if (ec) {
90 hkp_err_box (dlg, kserver, port, ec);
91 goto leave;
92 }
93
94 _snprintf (msg, sizeof (msg) -1, _("Key '%s' successfully sent"), pattern);
95 status_box (dlg, msg, _("GnuPG status"));
96
97 leave:
98 gpgme_release (ctx);
99 if (rawkey)
100 gpgme_free (rawkey);
101 return ec? -1 : 0;
102 }
103
104
105
106 /* If the keyserver returned one than more key in a
107 keyblob, show the names of all imported keys. */
108 static void
109 show_imported_keys (gpgme_import_result_t res)
110 {
111 gpgme_import_status_t t;
112 gpgme_key_t key;
113 gpgme_data_t msg;
114 gpgme_ctx_t ctx;
115 gpgme_error_t err;
116 const char *s;
117 char *p;
118 size_t n=0;
119
120 err = gpgme_data_new (&msg);
121 if (err)
122 BUG (NULL);
123 err = gpgme_new (&ctx);
124 if (err)
125 BUG (NULL);
126 s = _("WARNING: multiple keys matched request.\n\n");
127 gpgme_data_write (msg, s, strlen (s));
128 for (t=res->imports; t; t = t->next) {
129 if (!gpgme_get_key (ctx, t->fpr, &key, 0)) {
130 s = key->uids->uid;
131 gpgme_data_write (msg, s, strlen (s));
132 gpgme_data_write (msg, "\n", 1);
133 gpgme_key_release (key);
134 }
135 }
136 gpgme_data_write (msg, "\0", 1);
137 p = gpgme_data_release_and_get_mem (msg, &n);
138 if (p != NULL) {
139 msg_box (NULL, p, _("Imported Keys"), MB_INFO);
140 gpgme_free (p);
141 }
142 gpgme_release (ctx);
143 }
144
145
146 /* Receive a key from the keyserver @kserver (port @port)
147 with the pattern @pattern.
148 Return value: 0 on success. */
149 int
150 hkp_recv_key2 (HWND dlg, const char *kserver, WORD port,
151 const char *pattern, int proto, int flags,
152 char **r_fpr)
153 {
154 gpgme_ctx_t ctx;
155 gpgme_data_t keydata;
156 gpgme_error_t ec;
157 gpgme_import_result_t import_res = NULL;
158 char *rawkey = NULL;
159 char msg[384];
160 int rc;
161
162 /* XXX: implement dynamic buffers. */
163 rawkey = new char[MAX_KEYSIZE];
164 if (!rawkey)
165 BUG (0);
166 memset (rawkey, 0, MAX_KEYSIZE);
167 if (proto == KSPROTO_LDAP) {
168 rc = ldap_recvkey (kserver, pattern, rawkey, MAX_KEYSIZE-1);
169 if (rc) {
170 msg_box (dlg, _("LDAP key import failed.\n"
171 "Please make sure you have an online connection"
172 " and gpgkeys_ldap.exe is installed"),
173 _("Keyserver"), MB_ERR);
174 free_if_alloc (rawkey);
175 return rc;
176 }
177 }
178 else if (proto == KSPROTO_FINGER) {
179 rc = finger_recvkey (kserver, pattern, rawkey, MAX_KEYSIZE-1);
180 if (rc) {
181 log_box (_("Keyserver"), MB_ERR,
182 _("Finger key import failed: %s\n"), winpt_strerror (rc));
183 free_if_alloc (rawkey);
184 return rc;
185 }
186 }
187 else if ((rc = kserver_recvkey (kserver, port,
188 kserver_check_keyid (pattern),
189 rawkey, MAX_KEYSIZE-1))) {
190 hkp_err_box (dlg, kserver, port, rc);
191 free_if_alloc (rawkey);
192 return rc;
193 }
194 else {
195 if (!strstr (rawkey, "BEGIN PGP PUBLIC KEY BLOCK")) {
196 msg_box (dlg, _("This is not a valid OpenPGP key."),
197 _("Keyserver"), MB_ERR);
198 goto leave;
199 }
200 ec = gpgme_new (&ctx);
201 if (ec)
202 BUG (NULL);
203 gpgme_data_new_from_mem (&keydata, rawkey, strlen (rawkey), 1);
204 rc = gpgme_op_import (ctx, keydata);
205 if (rc) {
206 msg_box (dlg, gpgme_strerror ((gpgme_error_t)rc), _("Import"), MB_ERR);
207 goto leave;
208 }
209 import_res = gpgme_op_import_result (ctx);
210 if (import_res && r_fpr)
211 *r_fpr = m_strdup (import_res->imports->fpr);
212 }
213
214 /* if we use the refresh mode, a lot of keys will be fetched and thus only
215 a summarize at the end is presented and not for each key. */
216 if (!(flags & KM_KS_REFRESH)) {
217 if (import_res && import_res->considered > 1)
218 show_imported_keys (import_res);
219 if (import_res && import_res->unchanged == import_res->considered) {
220 _snprintf (msg, DIM (msg)-1,
221 _("Key '%s' successfully received but nothing was changed."), pattern );
222 status_box (dlg, msg, _("GnuPG Status"));
223 rc = WPTERR_GENERAL;
224 goto leave;
225 }
226 _snprintf (msg, DIM (msg)-1, _("Key '%s' sucessfully received and imported."), pattern);
227 status_box (dlg, msg, _("GnuPG Status"));
228 }
229
230 leave:
231 free_if_alloc (rawkey);
232 gpgme_release (ctx);
233 gpgme_data_release (keydata);
234
235 return rc;
236 }
237
238
239 /* Alias for hkp_recv_key2 but without the ability to return
240 the fingerprint of the key. */
241 int
242 hkp_recv_key (HWND dlg, const char *kserver, WORD port,
243 const char *pattern, int proto, int flags)
244 {
245 return hkp_recv_key2 (dlg, kserver, port, pattern, proto, flags, NULL);
246 }
247
248
249 #define my_iskeychar(a) (((a) >='0' && (a) <= '9' ) || ((a) >= 'A' && (a) <= 'F'))
250
251 static int
252 check_pattern (const char *pattern)
253 {
254 int rc = 1;
255
256 /* Whitespace are not allowed! */
257 if (strchr( pattern, ' ')) {
258 rc = WPTERR_GENERAL;
259 goto leave;
260 }
261
262 if (((strstr (pattern, "0x")) && (strlen (pattern) == 10)) ||
263 (strstr(pattern, "0x")) && (strlen (pattern) == 18)) {
264 rc = 0; /* Either long or short keyid */
265 goto leave;
266 }
267
268 if( (( my_iskeychar( pattern[0] )) && ( strlen( pattern ) == 8 ) )
269 || (my_iskeychar(pattern[0])) && ( strlen( pattern ) == 16) ) {
270 rc = 0;
271 goto leave;
272 }
273
274 if( ( strchr( pattern, '@' ) ) && ( strlen( pattern ) >= 3 ) ) {
275 rc = 0;
276 goto leave;
277 }
278
279 leave:
280 return rc;
281 } /* check_pattern */
282
283
284 static void
285 set_proxy (HWND dlg)
286 {
287 char proxy[256];
288 int port = 0;
289
290 strcpy (proxy, "HTTP proxy: ");
291 if (kserver_get_proxy (&port)) {
292 char t[128];
293 const char *http = kserver_get_proxy (&port);
294 _snprintf (t, sizeof (t) - 1, "\"%s:%d\"", http, port);
295 strcat (proxy, t);
296 }
297 else
298 strcat (proxy, "none");
299 SetDlgItemText (dlg, IDC_KEYSERVER_PROXY, proxy);
300 } /* set_proxy */
301
302
303 static int inline
304 kserver_get_pos (listview_ctrl_t lv)
305 {
306 if (listview_count_items (lv, 0) == 1)
307 return 0;
308 return listview_get_curr_pos (lv);
309 }
310
311
312 static u16 inline
313 kserver_get_port (listview_ctrl_t lv)
314 {
315 char buf[16];
316
317 listview_get_item_text (lv, kserver_get_pos (lv), 3, buf, 15);
318 return (u16)strtoul (buf, NULL, 10);
319 }
320
321 static void
322 load_default_ks (listview_ctrl_t lv)
323 {
324 char * p, buf[192];
325 int i;
326
327 p = get_reg_entry_keyserver ("Default");
328 if (!p)
329 return;
330 for( i = 0; i < listview_count_items( lv, 0 ); i++ ) {
331 listview_get_item_text( lv, i, 0, buf, sizeof (buf)-1 );
332 if( !strncmp( p, buf, strlen( p ) ) ) {
333 listview_add_sub_item( lv, i, 2, "x" );
334 break;
335 }
336 }
337 free_if_alloc (p);
338 } /* load_default_ks */
339
340
341 static int
342 save_default_ks (listview_ctrl_t lv)
343 {
344 char buf[192], port[32];
345 int idx, i;
346
347 idx = listview_get_curr_pos( lv );
348 if( idx == -1 ) {
349 msg_box( NULL, _("Please select one of the servers."), _("Keyserver"), MB_ERR );
350 return -1;
351 }
352 listview_get_item_text( lv, idx, 1, buf, sizeof (buf)-1 );
353 if( *buf != 'H' ) {
354 msg_box( NULL, _("Only HTTP keyserver can be used."), _("Keyserver"), MB_ERR );
355 return -1;
356 }
357 for (i = 0; i < listview_count_items( lv, 0 ); i++)
358 listview_add_sub_item (lv, i, 2, "");
359 listview_add_sub_item (lv, idx, 2, "x");
360 listview_get_item_text (lv, idx, 0, buf, sizeof (buf)-1);
361 set_reg_entry_keyserver ("Default", buf);
362 i = kserver_get_port (lv);
363 sprintf (port, "%d", i);
364 set_reg_entry_keyserver ("Default_Port", port);
365 keyserver_set_default (buf, (u16)i);
366 return 0;
367 } /* save_default_ks */
368
369
370 int
371 keyserver_list_build (listview_ctrl_t *r_lv, HWND hwnd)
372 {
373 struct listview_column_s keyserver[] = {
374 {0, 160, (char *)_("DNS Name")},
375 {1, 52, (char *)_("Protocol")},
376 {2, 46, (char *)_("Default")},
377 {3, 46, (char *)_("Port")},
378 {0, 0, NULL}
379 };
380 listview_ctrl_t lv;
381 char buf[32];
382 int j;
383
384 listview_new (&lv);
385 lv->ctrl = hwnd;
386 for (j=0; keyserver[j].fieldname; j++)
387 listview_add_column (lv, &keyserver[j]);
388 for (j = 0; j<MAX_KEYSERVERS; j++) {
389 if (!server[j].used)
390 continue;
391 listview_add_item (lv, " ");
392 listview_add_sub_item (lv, 0, 0, server[j].name);
393 switch (server[j].proto) {
394 case KSPROTO_HTTP:
395 listview_add_sub_item( lv, 0, 1, "H" ); break;
396 case KSPROTO_LDAP:
397 listview_add_sub_item( lv, 0, 1, "L" ); break;
398 case KSPROTO_FINGER:
399 listview_add_sub_item( lv, 0, 1, "F" ); break;
400 }
401 sprintf (buf, "%d", server[j].port);
402 listview_add_sub_item (lv, 0, 3, buf);
403 }
404 load_default_ks (lv);
405 if (listview_count_items (lv, 0) == 0) {
406 listview_add_item (lv, "");
407 listview_add_sub_item (lv, 0, 0, DEF_HKP_KEYSERVER);
408 listview_add_sub_item (lv, 0, 1, "H");
409 }
410 listview_set_ext_style (lv);
411 *r_lv = lv;
412 return 0;
413 }
414
415
416 /* Dialog box procedure to access keyservers. */
417 BOOL CALLBACK
418 keyserver_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
419 {
420 static listview_ctrl_t lv = NULL;
421 static int lv_idx = 0;
422 static struct genkey_s *key;
423 keyserver_ctx ksc;
424 char kserver[128], pattern[128];
425 char proto[16];
426 int rc, proto_nr = 0;
427
428 switch (msg) {
429 case WM_INITDIALOG:
430 if (lparam != 0)
431 key = (struct genkey_s*)lparam;
432 SetWindowText (dlg, _("Keyserver Access"));
433 SetDlgItemText (dlg, IDC_KEYSERVER_RECV, _("&Receive"));
434 SetDlgItemText (dlg, IDC_KEYSERVER_SEND,
435 _("Send key (default is receiving)"));
436 SetDlgItemText (dlg, IDC_KEYSERVER_INFO,
437 _("Please enter the key ID or email address you search for"));
438 SetDlgItemText (dlg, IDC_KEYSERVER_INDEX, _("&Search"));
439 SetDlgItemText (dlg, IDC_KEYSERVER_PROXSETT, _("C&hange"));
440 SetDlgItemText (dlg, IDC_KEYSERVER_DEFAULT, _("Set &default"));
441 SetDlgItemText (dlg, IDCANCEL, _("&Close"));
442
443 set_proxy (dlg);
444 keyserver_list_build (&lv, GetDlgItem (dlg, IDC_KEYSERVER_LIST));
445 center_window (dlg, NULL);
446 SetForegroundWindow (dlg);
447 return TRUE;
448
449 case WM_NOTIFY:
450 NMHDR *notify;
451 notify = (NMHDR *)lparam;
452 if (notify && notify->code == NM_CLICK
453 && notify->idFrom == IDC_KEYSERVER_LIST)
454 lv_idx = listview_get_curr_pos (lv);
455 return TRUE;
456
457 case WM_DESTROY:
458 if (lv) {
459 listview_release (lv);
460 lv = NULL;
461 }
462 lv_idx = 0;
463 return FALSE;
464
465 case WM_SYSCOMMAND:
466 if (LOWORD (wparam) == SC_CLOSE)
467 EndDialog (dlg, TRUE);
468 return FALSE;
469
470 case WM_COMMAND:
471 switch (LOWORD (wparam)) {
472 case IDC_KEYSERVER_PROXSETT:
473 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYSERVER_PROXY,
474 dlg, keyserver_proxy_dlg_proc, NULL,
475 _("Proxy Settings"), IDS_WINPT_KEYSERVER_PROXY);
476 set_proxy (dlg);
477 return TRUE;
478
479 case IDC_KEYSERVER_INDEX:
480 if (!lv_idx) {
481 lv_idx = kserver_get_pos (lv);
482 if (lv_idx == -1) {
483 msg_box (dlg, _("Please select one of the keyservers."),
484 _("Keyserver"), MB_INFO);
485 return FALSE;
486 }
487 }
488 listview_get_item_text (lv, lv_idx, 1, proto, sizeof (proto)-1);
489 if (*proto == 'L') {
490 msg_box (dlg, _("This is not implemented yet!"),
491 _("Keyserver"), MB_ERR);
492 return FALSE;
493 }
494 listview_get_item_text (lv, lv_idx, 0, kserver, sizeof (kserver)-1);
495 if (!GetDlgItemText (dlg, IDC_KEYSERVER_SEARCH, pattern, sizeof (pattern)-1)) {
496 msg_box (dlg, _("Please enter the search pattern."),
497 _("Keyserver"), MB_INFO);
498 return FALSE;
499 }
500 ksc.name = kserver;
501 ksc.pattern = pattern;
502 ksc.port = kserver_get_port (lv);
503 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_HKPSEARCH, dlg,
504 hkpsearch_dlg_proc, (LPARAM) &ksc);
505 return TRUE;
506
507 case IDC_KEYSERVER_RECV:
508 memset (&kserver, 0, sizeof (kserver));
509 if (!lv_idx) {
510 lv_idx = kserver_get_pos (lv);
511 if (lv_idx == -1) {
512 msg_box (dlg, _("Please select one of the keyservers."),
513 _("Keyserver"), MB_INFO);
514 return FALSE;
515 }
516 }
517 listview_get_item_text( lv, lv_idx, 1, proto, sizeof (proto)-1 );
518 proto_nr = KSPROTO_HTTP;
519 if (*proto == 'L')
520 proto_nr = KSPROTO_LDAP;
521 else if (*proto == 'F')
522 proto_nr = KSPROTO_FINGER;
523 listview_get_item_text (lv, lv_idx, 0, kserver, sizeof (kserver)-1);
524 if( !GetDlgItemText( dlg, IDC_KEYSERVER_SEARCH, pattern, sizeof (pattern)-1)) {
525 msg_box (dlg, _("Please enter the search pattern."),
526 _("Keyserver"), MB_INFO);
527 return FALSE;
528 }
529 if (proto_nr == KSPROTO_LDAP && strchr (pattern, '@')) {
530 msg_box (dlg, _("Only keyids are allowed."), _("LDAP Keyserver"), MB_INFO);
531 return FALSE;
532 }
533 else if (proto_nr == KSPROTO_FINGER) {
534 if (strchr (pattern, '@') || strchr (pattern, ' ')) {
535 msg_box (dlg, _("Only enter the name of the user."),
536 _("FINGER Keyserver"), MB_INFO);
537 return FALSE;
538 }
539 }
540 else if (check_pattern (pattern)) {
541 msg_box (dlg, _("Only email addresses or keyids are allowed."),
542 _("HKP Keyserver"), MB_INFO);
543 return FALSE;
544 }
545 rc = hkp_recv_key2 (dlg, kserver, kserver_get_port (lv),
546 pattern, proto_nr, 0, key? &key->fpr : NULL);
547 if (!rc && key->fpr != NULL) {
548 keycache_update (0, key->fpr);
549 get_pubkey (key->fpr, &key->newkey);
550 /* we do not need the fingerprint any longer. */
551 free_if_alloc (key->fpr);
552 }
553 return TRUE;
554
555 case IDC_KEYSERVER_DEFAULT:
556 save_default_ks (lv);
557 break;
558
559 case IDCANCEL:
560 EndDialog (dlg, FALSE);
561 return FALSE;
562 }
563 break;
564 }
565
566 return FALSE;
567 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26