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

Contents of /trunk/Src/wptKeysignDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 333 - (show annotations)
Tue Oct 13 10:51:21 2009 UTC (15 years, 4 months ago) by twoaday
File size: 12483 byte(s)


1 /* wptKeysignDlg.cpp - Key signing dialog
2 * Copyright (C) 2001-2006, 2008-2009 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 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <windows.h>
21 #include <commctrl.h>
22 #include <time.h>
23 #include <assert.h>
24
25 #include "resource.h"
26 #include "wptGPG.h"
27 #include "wptNLS.h"
28 #include "wptW32API.h"
29 #include "wptVersion.h"
30 #include "wptTypes.h"
31 #include "wptErrors.h"
32 #include "wptCommonCtl.h"
33 #include "wptContext.h"
34 #include "wptDlgs.h"
35 #include "wptUTF8.h"
36 #include "wptRegistry.h"
37 #include "wptKeylist.h"
38 #include "wptKeyEdit.h"
39 #include "StringBuffer.h"
40
41
42 int key_load_photo (winpt_key_t key,
43 char *photo_file, size_t photo_file_size,
44 gpgme_validity_t *r_valid);
45 int get_photo_tmpname (gpgme_key_t key, char *buf, size_t buflen);
46
47 /* Return a beautified printable fingerprint of @fpr. */
48 static const char*
49 get_printable_fpr (const char *fpr)
50 {
51 static char pfpr[128];
52 int pos = 0;
53 size_t i;
54
55 memset (pfpr, 0, sizeof (pfpr));
56 for (i = 0; i < strlen (fpr); i += 4) {
57 pfpr[pos++] = fpr[i];
58 pfpr[pos++] = fpr[i+1];
59 pfpr[pos++] = fpr[i+2];
60 pfpr[pos++] = fpr[i+3];
61 pfpr[pos++] = ' ';
62 }
63 return pfpr;
64 }
65
66
67 /* Return human friendly information about the key @key. */
68 const char*
69 get_keyinfo (gpgme_key_t key)
70 {
71 static char buf[64+16];
72 struct winpt_key_s k;
73
74 memset (&k, 0, sizeof (k));
75 if (winpt_get_seckey (key->subkeys->keyid, &k))
76 BUG (0);
77 _snprintf (buf, DIM (buf)-1-16, _("%d-bit %s key, ID 0x%s"),
78 key->subkeys->length,
79 get_key_pubalgo (key->subkeys->pubkey_algo),
80 key->subkeys->keyid+8);
81 if (k.ext->gloflags.divert_to_card)
82 strcat (buf, _(" (Card)"));
83 return buf;
84 }
85
86
87 /* Fill the secret key combo-box with all entries from the cache.
88 @dlg is the handle to the combo-box. @keyid show which key to skip.
89 Return value: 0 on success. */
90 static int
91 do_fill_seckeylist (HWND dlg, const char *keyid)
92 {
93 gpg_keycache_t sec;
94 gpgme_key_t pk, defkey;
95 const char *s;
96 char *uid;
97 int i = 0, n = 0, curr_sel = 0;
98
99 sec = keycache_get_ctx (0);
100 gpg_keycache_get_default_key (sec, &defkey);
101 gpg_keycache_rewind (sec);
102 while (!gpg_keycache_next_key (sec, 1, &pk)) {
103 StringBuffer p;
104
105 if (!pk)
106 continue;
107 s = pk->subkeys->keyid;
108 if (!strcmp (s, keyid))
109 continue;
110 /* skip all ElGamal sign+encrypt keys */
111 if (pk->subkeys->pubkey_algo == GPGME_PK_ELG)
112 continue;
113 /* make sure the public key is okay not: revoked, expired or disabled. */
114 if (pk->expired ||pk->revoked || pk->disabled)
115 continue;
116 s = pk->uids->name;
117 if (!s)
118 continue;
119 if (defkey && !strcmp (defkey->subkeys->keyid, pk->subkeys->keyid))
120 curr_sel = i;
121
122 uid = utf8_to_native (s);
123 p = uid;
124 p = p + " (" + get_keyinfo (pk) + ")";
125 SendDlgItemMessage (dlg, IDC_KEYSIGN_KEYLIST,
126 CB_ADDSTRING, i, (LPARAM)(char *)p.getBuffer ());
127 SendDlgItemMessage (dlg, IDC_KEYSIGN_KEYLIST,
128 CB_SETITEMDATA, i++, (LPARAM)(DWORD)pk);
129 safe_free (uid);
130 n++;
131 }
132 SendDlgItemMessage (dlg, IDC_KEYSIGN_KEYLIST,
133 CB_SETCURSEL, (WPARAM)curr_sel, 0);
134 if (!n)
135 return -1;
136 return 0;
137 }
138
139
140
141 /* Dialog box procedure to choose the signature class. */
142 BOOL CALLBACK
143 sig_class_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
144 {
145 HWND parent;
146
147 switch (msg) {
148 case WM_INITDIALOG:
149 parent = (HWND)lparam;
150 SetWindowText (dlg, _("Choose Signature Class"));
151 SetDlgItemText (dlg, IDC_SIGCLASS_TITLEINF,
152 _("How carefully have you verified the key you are about to sign actually belongs to the person? If you don't know what to anwser, use \"0\"."));
153 SetDlgItemText (dlg, IDC_SIGCLASS_CLASS0,
154 _("(0) I will not answer (default)"));
155 SetDlgItemText (dlg, IDC_SIGCLASS_CLASS1,
156 _("(1) I have not checked at all."));
157 SetDlgItemText (dlg, IDC_SIGCLASS_CLASS2,
158 _("(2) I have done causal checking."));
159 SetDlgItemText (dlg, IDC_SIGCLASS_CLASS3,
160 _("(3) I have done very careful checking."));
161 CheckDlgButton (dlg, IDC_SIGCLASS_CLASS0, BST_CHECKED);
162 SetForegroundWindow (dlg);
163 center_window (dlg, parent? parent : NULL);
164 return TRUE;
165
166 case WM_COMMAND:
167 switch (LOWORD (wparam)) {
168 case IDOK:
169 int sig_class;
170
171 if (IsDlgButtonChecked (dlg, IDC_SIGCLASS_CLASS0))
172 sig_class = 0;
173 else if (IsDlgButtonChecked (dlg, IDC_SIGCLASS_CLASS1))
174 sig_class = 1;
175 else if (IsDlgButtonChecked (dlg, IDC_SIGCLASS_CLASS2))
176 sig_class = 2;
177 else if (IsDlgButtonChecked (dlg, IDC_SIGCLASS_CLASS3))
178 sig_class = 3;
179 else
180 sig_class = 0;
181 EndDialog (dlg, sig_class);
182 break;
183
184 case IDCANCEL:
185 EndDialog (dlg, 0);
186 break;
187 }
188 break;
189 }
190
191 return FALSE;
192 }
193
194
195 /* Return the humand friendly expiration date of @key. */
196 static const char*
197 get_expire_date (gpgme_key_t key)
198 {
199 u32 u = key->subkeys->expires;
200 if (!u)
201 return _("never");
202 return get_key_expire_date (u);
203 }
204
205
206 /* Check if the given system time @st points to today. */
207 static int
208 date_is_today (SYSTEMTIME *st)
209 {
210 time_t t;
211 struct tm *tm;
212
213 t = time (NULL);
214 tm = localtime (&t);
215 if (st->wDay == tm->tm_mday &&
216 st->wYear == tm->tm_year+1900 &&
217 st->wMonth == tm->tm_mon+1)
218 return -1;
219 return 0;
220 }
221
222
223 /* Display all needed information about the key @key in the dialog @dlg. */
224 static void
225 display_keyinfo (HWND dlg, listview_ctrl_t list, winpt_key_t key)
226 {
227 StringBuffer kinf;
228 struct native_uid_s *u;
229 char tmp[256];
230
231 _snprintf (tmp, DIM (tmp) -1,
232 _("pub %d/0x%s created: %s expires: %s\n\n"
233 "Key fingerprint:\n%s\n\n"),
234 key->ctx->subkeys->length,
235 key->ctx->subkeys->keyid+8,
236 get_key_created (key->ctx->subkeys->timestamp),
237 get_expire_date (key->ctx),
238 get_printable_fpr (key->ctx->subkeys->fpr));
239 kinf = tmp;
240 SetDlgItemText (dlg, IDC_KEYSIGN_INFOS, kinf.getBuffer ());
241
242 for (u = key->ext->uids; u; u = u->next) {
243 if (u->revoked)
244 continue;
245 listview_add_item (list, "");
246 listview_add_sub_item (list, 0, 0, u->name);
247 listview_add_sub_item (list, 0, 1, u->email);
248 }
249 }
250
251
252 void set_gpg_auto_passphrase_cb (passphrase_cb_s *cb, const char *title);
253 gpgme_error_t passphrase_cb (void *hook, const char *uid_hint,
254 const char *passphrase_info,
255 int prev_was_bad, int fd);
256
257 /* Perform the actual procedure to sign the key. */
258 static BOOL
259 on_click_ok (HWND dlg, winpt_key_t key)
260 {
261 gpgme_key_t k;
262 gpgme_error_t err;
263 SYSTEMTIME st;
264 GpgKeyEdit ke;
265 int sig_class = 0;
266 char keymsg[64];
267 int type, expires=0, idx;
268
269 if (IsDlgButtonChecked (dlg, IDC_KEYSIGN_ASKLEVEL))
270 sig_class = dialog_box_param (glob_hinst,
271 (LPCSTR)IDD_WINPT_SIGCLASS, dlg,
272 sig_class_dlg_proc, (LPARAM)dlg,
273 _("Choose Signature Class"),
274 IDS_WINPT_SIGCLASS);
275 type = IsDlgButtonChecked (dlg, IDC_KEYSIGN_LOCAL);
276 if (type)
277 type = GPG_EDITKEY_LSIGN;
278 else
279 type = GPG_EDITKEY_SIGN;
280
281 if (reg_prefs.expert && IsDlgButtonChecked (dlg, IDC_KEYSIGN_NREV)) {
282 type = GPG_EDITKEY_NRSIGN;
283 if (type == GPG_EDITKEY_LSIGN)
284 type = GPG_EDITKEY_NRLSIGN;
285 }
286
287 if (IsDlgButtonChecked (dlg, IDC_KEYSIGN_EXPSIG)) {
288 DateTime_GetSystemtime (GetDlgItem (dlg, IDC_KEYSIGN_EXPIRES), &st);
289 if (date_is_today (&st)) {
290 show_balloon_msg (GetDlgItem (dlg, IDC_KEYSIGN_EXPIRES),
291 _("You cannot select today as the expiration date."),
292 IDI_WARNING);
293 return TRUE;
294 }
295 else
296 expires = 1;
297 _snprintf (keymsg, DIM (keymsg)-1, "%04d-%02d-%02d",
298 st.wYear, st.wMonth, st.wDay);
299 }
300
301 if (key->ctx->subkeys->keyid == NULL)
302 BUG (0); /* should be always true. */
303 ke.setKeyID (key->ctx->subkeys->keyid);
304
305 passphrase_cb_s cb;
306 set_gpg_auto_passphrase_cb (&cb, _("Key Edit"));
307 ke.setPassphraseCallback (passphrase_cb, (void*)&cb);
308
309 HWND klist = GetDlgItem (dlg, IDC_KEYSIGN_KEYLIST);
310 idx = SendMessage (klist, CB_GETCURSEL, 0, 0);
311 k = (gpgme_key_t)SendMessage (klist, CB_GETITEMDATA, (WPARAM)idx, 0);
312 if (k != NULL)
313 ke.setLocalUser (k);
314
315 err = ke.signKey (type, sig_class, expires? keymsg : "0");
316 release_gpg_passphrase_cb (&cb);
317 if (cb.cancel)
318 return TRUE;
319 else if (err) {
320 msg_box (dlg, gpgme_strerror (err), _("Key Signing"), MB_ERR);
321 return TRUE;
322 }
323 else if (ke.getResult () != 0) {
324 show_balloon_msg (klist, _("This key is already signed by your key"),
325 IDI_INFORMATION);
326 return TRUE;
327 }
328 else {
329 status_box (dlg, _("Key successfully signed."), _("Key Signing"));
330 key->update = 1;
331 }
332 EndDialog (dlg, TRUE);
333 return TRUE;
334 }
335
336
337 static listview_ctrl_t
338 init_uidlist (HWND dlg)
339 {
340 struct listview_column_s cols[] = {
341 {0, 190, (char *)_("Name")},
342 {1, 150, (char *)_("E-Mail")}};
343
344 listview_ctrl_t list;
345 listview_new (&list, GetDlgItem (dlg, IDC_KEYSIGN_UIDLIST));
346 listview_add_column (list, &cols[0]);
347 listview_add_column (list, &cols[1]);
348 return list;
349 }
350
351
352 /* Dialog box procedure to sign a key. */
353 BOOL CALLBACK
354 keysign_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
355 {
356 static winpt_key_t key;
357 static listview_ctrl_t list;
358 char buf[MAX_PATH+128+1];
359 const char *s;
360
361 switch (msg) {
362 case WM_INITDIALOG:
363 key = (winpt_key_t) lparam;
364 if (!key)
365 BUG (0);
366 s = key->ctx->subkeys->keyid;
367 if (do_fill_seckeylist (dlg, s)) {
368 msg_box (dlg, _("No valid secret key found."),
369 _("Key Signing"), MB_ERR);
370 EndDialog (dlg, FALSE);
371 return TRUE;
372 }
373 list = init_uidlist (dlg);
374 display_keyinfo (dlg, list, key);
375 SetDlgItemText (dlg, IDC_KEYSIGN_LOCAL, _("Sign local only (non exportable signature)"));
376 SetDlgItemText (dlg, IDC_KEYSIGN_EXPSIG, _("Signature expires on"));
377 SetDlgItemText (dlg, IDC_KEYSIGN_NREV, _("Sign non-revocably"));
378 SetDlgItemText (dlg, IDC_KEYSIGN_ASKLEVEL, _("&Ask for certification level"));
379 SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
380 SetDlgItemText (dlg, IDC_KEYSIGN_CONFIRMSIGN, _("Are you really sure that you want to sign this key with YOUR key?"));
381 SetWindowText (dlg, _("Key Signing"));
382 CheckDlgButton (dlg, IDC_KEYSIGN_LOCAL, BST_CHECKED);
383 CheckDlgButton (dlg, IDC_KEYSIGN_EXPSIG, BST_UNCHECKED);
384 CheckDlgButton (dlg, IDC_KEYSIGN_ASKLEVEL, BST_UNCHECKED);
385 EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_EXPIRES), FALSE);
386 if (reg_prefs.expert == 0)
387 ShowWindow (GetDlgItem (dlg, IDC_KEYSIGN_NREV), SW_HIDE);
388 if (!reg_prefs.gpg.ask_cert_level)
389 EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_ASKLEVEL), FALSE);
390 if (!reg_prefs.gpg.ask_cert_expire)
391 EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_EXPSIG), FALSE);
392 if (key->ext && key->ext->attrib.len > 0)
393 key_load_photo (key, buf, DIM(buf)-1, NULL);
394 CheckDlgButton (dlg, IDC_KEYSIGN_HIDE, BST_CHECKED);
395 SetForegroundWindow (dlg);
396 SetFocus (GetDlgItem (dlg, IDOK));
397 return FALSE;
398
399 case WM_DESTROY:
400 balloon_msg_disable ();
401 if (key->ext && key->ext->attrib.len > 0) {
402 get_photo_tmpname (key->ctx, buf, DIM(buf)-1);
403 DeleteFile (buf);
404 }
405 if (list != NULL) {
406 listview_release (list);
407 list = NULL;
408 }
409 break;
410
411 case WM_PAINT:
412 if (key->ext != NULL && key->ext->attrib.len > 0) {
413 POINT p;
414 p.x = p.y = 0;
415 get_photo_tmpname (key->ctx, buf, DIM (buf)-1);
416 if (jpg_show (GetDlgItem (dlg, IDC_SHOWPHOTO_IMG), &p, buf))
417 EndDialog (dlg, TRUE);
418 }
419 break;
420
421 case WM_COMMAND:
422 if (HIWORD (wparam) == BN_CLICKED &&
423 LOWORD (wparam) == IDC_KEYSIGN_EXPSIG) {
424 int enable = IsDlgButtonChecked (dlg, IDC_KEYSIGN_EXPSIG);
425 EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_EXPIRES),
426 enable? TRUE : FALSE);
427 }
428
429 switch (LOWORD (wparam)) {
430 case IDOK:
431 balloon_msg_disable ();
432 return on_click_ok (dlg, key);
433
434 case IDCANCEL:
435 EndDialog (dlg, FALSE);
436 return TRUE;
437 }
438 break;
439 }
440
441 return FALSE;
442 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26