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

Annotation of /trunk/Src/wptKeysignDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (hide annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 12824 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26