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

Contents of /trunk/Src/wptKeyserverDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File size: 14730 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


1 /* wptKeyserverDlg.cpp - Keyserver dialog
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
21 #include <windows.h>
22 #include <commctrl.h>
23 #include <malloc.h>
24
25 #include "../resource.h"
26 #include "wptKeyserver.h"
27 #include "wptErrors.h"
28 #include "wptTypes.h"
29 #include "wptCommonCtl.h"
30 #include "wptNLS.h"
31 #include "wptW32API.h"
32 #include "wptVersion.h"
33 #include "wptGPG.h"
34 #include "wptKeyManager.h"
35 #include "wptContext.h" /* for passphrase_s */
36 #include "wptDlgs.h"
37
38
39 #define MAX_KEYSIZE 70000
40
41 char * get_reg_entry_keyserver (const char *);
42 int set_reg_entry_keyserver (const char *, const char *);
43
44
45 static void
46 hkp_err_box (HWND dlg, const char * host, u16 port, int rc)
47 {
48 const char *err = kserver_strerror();
49
50 log_box( _("Keyserver"), MB_ERR, "%s:%d: %s", host, port, winpt_strerror (rc));
51 if (err)
52 msg_box (dlg, err, wsock_strerror (), MB_ERR);
53 } /* hkp_err_box */
54
55
56 int
57 hkp_send_key (HWND dlg, const char *kserver, u16 port, const char *pattern)
58 {
59 gpgme_ctx_t c;
60 gpgme_data_t keydata;
61 gpgme_error_t ec;
62 char *rawkey = NULL, msg[1024];
63 size_t n;
64 int rc;
65
66 ec = gpgme_new( &c );
67 if( ec )
68 BUG( NULL );
69 gpgme_set_armor (c, 1);
70 ec = gpgme_data_new( &keydata );
71 if( ec )
72 BUG( NULL );
73 rc = (int) gpgme_op_export( c, pattern, 0, keydata );
74 if( rc ) {
75 msg_box( dlg, gpgme_strerror( (gpgme_error_t)rc ), _("Export"), MB_ERR );
76 goto leave;
77 }
78 rawkey = gpgme_data_release_and_get_mem (keydata, &n);
79 rawkey[n] = 0;
80 rc = kserver_sendkey (kserver, port, rawkey, strlen (rawkey));
81 if (rc) {
82 hkp_err_box (dlg, kserver, port, rc);
83 goto leave;
84 }
85
86 _snprintf (msg, sizeof (msg) -1, _("Key '%s' successfully sent"), pattern);
87 status_box (dlg, msg, _("GnuPG status"));
88
89 leave:
90 gpgme_release (c);
91 safe_free (rawkey);
92 return rc;
93 } /* hkp_send_key */
94
95
96 int
97 hkp_recv_key (HWND dlg, const char *kserver, u16 port,
98 const char *pattern, int proto, int flags)
99 {
100 gpgme_ctx_t ctx;
101 gpgme_data_t keydata;
102 gpgme_error_t ec;
103 gpgme_import_result_t import_res;
104 int rc;
105 char *rawkey = NULL, msg[384];
106
107 rawkey = new char[MAX_KEYSIZE];
108 if (!rawkey)
109 BUG (0);
110 memset (rawkey, 0, MAX_KEYSIZE);
111 if( proto == KSPROTO_LDAP ) {
112 rc = ldap_recvkey( kserver, pattern, rawkey, MAX_KEYSIZE-1 );
113 if( rc ) {
114 msg_box( dlg, _("LDAP key import failed.\n"
115 "Please make sure you have an online connection"
116 " and gpgkeys_ldap.exe is installed"),
117 _("Keyserver"), MB_ERR );
118 free_if_alloc( rawkey );
119 return rc;
120 }
121 }
122 else if (proto == KSPROTO_FINGER) {
123 rc = finger_recvkey (kserver, pattern, rawkey, MAX_KEYSIZE-1);
124 if (rc) {
125 log_box (_("Keyserver"), MB_ERR, _("Finger key import failed: %s\n"),
126 winpt_strerror (rc));
127 free_if_alloc (rawkey);
128 return rc;
129 }
130 }
131 else if( ( rc = kserver_recvkey( kserver, port, kserver_check_keyid( pattern ),
132 rawkey, MAX_KEYSIZE-1 ) ) ) {
133 hkp_err_box (dlg, kserver, port, rc);
134 free_if_alloc (rawkey);
135 return rc;
136 }
137 else {
138 if( !strstr( rawkey, "BEGIN PGP PUBLIC KEY BLOCK" ) ) {
139 msg_box( dlg, _("This is not a valid OpenPGP key."), _("Keyserver"), MB_ERR );
140 goto leave;
141 }
142 ec = gpgme_new( &ctx );
143 if( ec )
144 BUG( NULL );
145 gpgme_data_new_from_mem( &keydata, rawkey, strlen( rawkey ), 1 );
146 rc = gpgme_op_import( ctx, keydata );
147 if( rc ) {
148 msg_box( dlg, gpgme_strerror( (gpgme_error_t)rc ), _("Import"), MB_ERR );
149 goto leave;
150 }
151 import_res = gpgme_op_import_result (ctx);
152 }
153
154 /* if we use the refresh mode, a lot of keys will be fetched and thus only
155 a summarize at the end is presented and not for each key. */
156 if (!(flags & KM_KS_REFRESH)) {
157 if (import_res->new_user_ids == 0) {
158 _snprintf (msg, DIM (msg)-1,
159 _("Key '%s' successfully received but nothing was changed."), pattern );
160 status_box (dlg, msg, _("GnuPG Status"));
161 rc = WPTERR_GENERAL;
162 goto leave;
163 }
164 _snprintf (msg, DIM (msg)-1, _("Key '%s' sucessfully received and imported."), pattern);
165 status_box (dlg, msg, _("GnuPG Status"));
166 }
167
168 leave:
169 free_if_alloc (rawkey);
170 gpgme_release (ctx);
171 gpgme_data_release (keydata);
172
173 return rc;
174 } /* hkp_recv_key */
175
176
177 #define my_iskeychar(a) ( ( (a) >='0' && (a) <= '9' ) || ( (a) >= 'A' && (a) <= 'F' ) )
178
179 static int
180 check_pattern( const char *pattern )
181 {
182 int rc = 1;
183
184 /* Whitespace are not allowed! */
185 if( strchr( pattern, ' ') ) {
186 rc = WPTERR_GENERAL;
187 goto leave;
188 }
189
190 if( (( strstr( pattern, "0x" ) ) && ( strlen( pattern ) == 10 ) )
191 || (strstr(pattern, "0x")) && ( strlen( pattern ) == 18 ) ) {
192 rc = 0;
193 goto leave;
194 }
195
196 if( (( my_iskeychar( pattern[0] )) && ( strlen( pattern ) == 8 ) )
197 || (my_iskeychar(pattern[0])) && ( strlen( pattern ) == 16) ) {
198 rc = 0;
199 goto leave;
200 }
201
202 if( ( strchr( pattern, '@' ) ) && ( strlen( pattern ) >= 3 ) ) {
203 rc = 0;
204 goto leave;
205 }
206
207 leave:
208 return rc;
209 } /* check_pattern */
210
211
212 static void
213 set_proxy (HWND dlg)
214 {
215 char proxy[384];
216 int port = 0;
217
218 strcpy (proxy, "HTTP proxy: ");
219 if (kserver_get_proxy (&port)) {
220 char t[256];
221 const char *http = kserver_get_proxy (&port);
222 _snprintf (t, sizeof (t) - 1, "\"%s:%d\"", http, port);
223 strcat (proxy, t);
224 }
225 else
226 strcat( proxy, "none" );
227 SetDlgItemText( dlg, IDC_KEYSERVER_PROXY, proxy );
228 } /* set_proxy */
229
230
231 static int inline
232 kserver_get_pos (listview_ctrl_t lv)
233 {
234 if (listview_count_items (lv, 0) == 1)
235 return 0;
236 return listview_get_curr_pos (lv);
237 }
238
239
240 static u16 inline
241 kserver_get_port (listview_ctrl_t lv)
242 {
243 char buf[16];
244
245 listview_get_item_text (lv, kserver_get_pos (lv), 3, buf, 15);
246 return (u16)strtoul (buf, NULL, 10);
247 }
248
249 static void
250 load_default_ks (listview_ctrl_t lv)
251 {
252 char * p, buf[192];
253 int i;
254
255 p = get_reg_entry_keyserver ("Default");
256 if (!p)
257 return;
258 for( i = 0; i < listview_count_items( lv, 0 ); i++ ) {
259 listview_get_item_text( lv, i, 0, buf, sizeof (buf)-1 );
260 if( !strncmp( p, buf, strlen( p ) ) ) {
261 listview_add_sub_item( lv, i, 2, "x" );
262 break;
263 }
264 }
265 free_if_alloc (p);
266 } /* load_default_ks */
267
268
269 static int
270 save_default_ks (listview_ctrl_t lv)
271 {
272 char buf[192], port[32];
273 int idx, i;
274
275 idx = listview_get_curr_pos( lv );
276 if( idx == -1 ) {
277 msg_box( NULL, _("Please select one of the servers."), _("Keyserver"), MB_ERR );
278 return -1;
279 }
280 listview_get_item_text( lv, idx, 1, buf, sizeof (buf)-1 );
281 if( *buf != 'H' ) {
282 msg_box( NULL, _("Only HTTP keyserver can be used."), _("Keyserver"), MB_ERR );
283 return -1;
284 }
285 for (i = 0; i < listview_count_items( lv, 0 ); i++)
286 listview_add_sub_item (lv, i, 2, "");
287 listview_add_sub_item (lv, idx, 2, "x");
288 listview_get_item_text (lv, idx, 0, buf, sizeof (buf)-1);
289 set_reg_entry_keyserver ("Default", buf);
290 i = kserver_get_port (lv);
291 sprintf (port, "%d", i);
292 set_reg_entry_keyserver ("Default_Port", port);
293 keyserver_set_default (buf, (u16)i);
294 return 0;
295 } /* save_default_ks */
296
297
298 int
299 keyserver_list_build (listview_ctrl_t *r_lv, HWND hwnd)
300 {
301 struct listview_column_s keyserver[] = {
302 {0, 160, (char *)_("DNS Name")},
303 {1, 52, (char *)_("Protocol")},
304 {2, 46, (char *)_("Default")},
305 {3, 46, (char *)_("Port")},
306 {0, 0, NULL}
307 };
308 listview_ctrl_t lv;
309 char buf[32];
310 int j;
311
312 listview_new (&lv);
313 lv->ctrl = hwnd;
314 for (j=0; keyserver[j].fieldname; j++)
315 listview_add_column (lv, &keyserver[j]);
316 for (j = 0; j<MAX_KEYSERVERS; j++) {
317 if (!server[j].used)
318 continue;
319 listview_add_item (lv, " ");
320 listview_add_sub_item (lv, 0, 0, server[j].name);
321 switch (server[j].proto) {
322 case KSPROTO_HTTP:
323 listview_add_sub_item( lv, 0, 1, "H" ); break;
324 case KSPROTO_LDAP:
325 listview_add_sub_item( lv, 0, 1, "L" ); break;
326 case KSPROTO_FINGER:
327 listview_add_sub_item( lv, 0, 1, "F" ); break;
328 }
329 sprintf (buf, "%d", server[j].port);
330 listview_add_sub_item (lv, 0, 3, buf);
331 }
332 load_default_ks (lv);
333 if (listview_count_items (lv, 0) == 0) {
334 listview_add_item (lv, "");
335 listview_add_sub_item (lv, 0, 0, DEF_HKP_KEYSERVER);
336 listview_add_sub_item (lv, 0, 1, "H");
337 }
338 listview_set_ext_style (lv);
339 *r_lv = lv;
340 return 0;
341 }
342
343
344 BOOL CALLBACK
345 keyserver_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
346 {
347 static listview_ctrl_t lv = NULL;
348 static int lv_idx = 0;
349 int rc, proto_nr = 0;
350 char kserver[128], pattern[128];
351 char proto[16];
352 keyserver_ctx ksc;
353
354 switch ( msg ) {
355 case WM_INITDIALOG:
356 #ifndef LANG_DE
357 SetWindowText( dlg, _("Keyserver Access") );
358 SetDlgItemText( dlg, IDC_KEYSERVER_SEND,
359 _("Send key (default is receiving)") );
360 SetDlgItemText( dlg, IDC_KEYSERVER_INFO,
361 _("Please enter the key ID or email address you search for"));
362 SetDlgItemText( dlg, IDC_KEYSERVER_INDEX, _("&Search") );
363 #endif
364 set_proxy (dlg);
365 keyserver_list_build (&lv, GetDlgItem (dlg, IDC_KEYSERVER_LIST));
366 center_window (dlg, NULL);
367 SetForegroundWindow (dlg);
368 return TRUE;
369
370 case WM_NOTIFY:
371 NMHDR *notify;
372 notify = (NMHDR *)lparam;
373 if( notify && notify->code == NM_CLICK
374 && notify->idFrom == IDC_KEYSERVER_LIST )
375 lv_idx = listview_get_curr_pos( lv );
376 return TRUE;
377
378 case WM_DESTROY:
379 if( lv ) {
380 listview_release( lv );
381 lv = NULL;
382 }
383 lv_idx = 0;
384 return FALSE;
385
386 case WM_SYSCOMMAND:
387 if( LOWORD( wparam ) == SC_CLOSE )
388 EndDialog( dlg, TRUE );
389 return FALSE;
390
391 case WM_COMMAND:
392 switch( LOWORD( wparam ) ) {
393 case IDC_KEYSERVER_PROXSETT:
394 dialog_box_param( glob_hinst, (LPCTSTR)IDD_WINPT_KEYSERVER_PROXY, glob_hwnd,
395 keyserver_proxy_dlg_proc, NULL,
396 _("Proxy Settings"), IDS_WINPT_KEYSERVER_PROXY );
397 set_proxy( dlg );
398 return TRUE;
399
400 case IDC_KEYSERVER_INDEX:
401 if (!lv_idx) {
402 lv_idx = kserver_get_pos (lv);
403 if (lv_idx == -1) {
404 msg_box (dlg, _("Please select one of the keyservers."), _("Keyserver"), MB_INFO);
405 return FALSE;
406 }
407 }
408 listview_get_item_text (lv, lv_idx, 1, proto, sizeof (proto)-1);
409 if (*proto == 'L') {
410 msg_box( dlg, _("This is not implemented yet!"), _("Keyserver"), MB_ERR );
411 return FALSE;
412 }
413 listview_get_item_text (lv, lv_idx, 0, kserver, sizeof (kserver)-1);
414 if (!GetDlgItemText (dlg, IDC_KEYSERVER_SEARCH, pattern, sizeof (pattern)-1)) {
415 msg_box (dlg, _("Please enter the search pattern."), _("Keyserver"), MB_INFO);
416 return FALSE;
417 }
418 ksc.name = kserver;
419 ksc.pattern = pattern;
420 ksc.port = kserver_get_port (lv);
421 DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_HKPSEARCH, dlg,
422 hkpsearch_dlg_proc, (LPARAM) &ksc );
423 return TRUE;
424
425 case IDC_KEYSERVER_RECV:
426 memset (&kserver, 0, sizeof (kserver));
427 if (!lv_idx) {
428 lv_idx = kserver_get_pos (lv);
429 if (lv_idx == -1) {
430 msg_box( dlg, _("Please select one of the keyservers."), _("Keyserver"), MB_INFO );
431 return FALSE;
432 }
433 }
434 listview_get_item_text( lv, lv_idx, 1, proto, sizeof (proto)-1 );
435 proto_nr = KSPROTO_HTTP;
436 if( *proto == 'L' )
437 proto_nr = KSPROTO_LDAP;
438 else if( *proto == 'F' )
439 proto_nr = KSPROTO_FINGER;
440 listview_get_item_text( lv, lv_idx, 0, kserver, sizeof (kserver)-1 );
441 if( !GetDlgItemText( dlg, IDC_KEYSERVER_SEARCH, pattern, sizeof (pattern)-1 ) ) {
442 msg_box( dlg, _("Please enter the search pattern."), _("Keyserver"), MB_INFO );
443 return FALSE;
444 }
445 if( proto_nr == KSPROTO_LDAP && strchr( pattern, '@' ) ) {
446 msg_box( dlg, _("Only keyids are allowed."), _("LDAP Keyserver"), MB_INFO );
447 return FALSE;
448 }
449 else if (proto_nr == KSPROTO_FINGER) {
450 if (strchr (pattern, '@') || strchr (pattern, ' ')) {
451 msg_box (dlg, _("Only enter the name of the user."), _("FINGER Keyserver"), MB_INFO);
452 return FALSE;
453 }
454 }
455 else if( check_pattern( pattern ) ) {
456 msg_box( dlg, _("Only email addresses or keyids are allowed."), _("HKP Keyserver"), MB_INFO );
457 return FALSE;
458 }
459 rc = hkp_recv_key (dlg, kserver, kserver_get_port (lv), pattern, proto_nr, 0);
460 if (!rc)
461 keycache_set_reload (1);
462 return TRUE;
463
464 case IDC_KEYSERVER_DEFAULT:
465 save_default_ks( lv );
466 break;
467
468 case IDCANCEL:
469 EndDialog( dlg, FALSE );
470 return FALSE;
471 }
472 break;
473 }
474
475 return FALSE;
476 } /* keyserver_dlg_proc */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26