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

Contents of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 236 - (show annotations)
Wed Jun 28 06:59:30 2006 UTC (18 years, 8 months ago) by twoaday
File size: 61404 byte(s)


1 /* wptKeyEditDlgs.cpp - GPG key edit dialogs
2 * Copyright (C) 2002-2006 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 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <time.h>
27 #include <assert.h>
28
29 #include "resource.h"
30 #include "wptTypes.h"
31 #include "wptW32API.h"
32 #include "wptVersion.h"
33 #include "wptGPG.h"
34 #include "wptCommonCtl.h"
35 #include "wptContext.h"
36 #include "wptDlgs.h"
37 #include "wptNLS.h"
38 #include "wptUTF8.h"
39 #include "wptErrors.h"
40 #include "wptKeylist.h"
41 #include "wptKeyManager.h"
42 #include "wptRegistry.h"
43 #include "wptKeyEdit.h"
44
45 /* All edit key commands. */
46 enum keyedit_commands {
47 CMD_ADDKEY = 0,
48 CMD_ADDUID,
49 CMD_ADDPHOTO,
50 CMD_ADDREVOKER,
51 CMD_DELUID,
52 CMD_DELKEY,
53 CMD_EXPIRE,
54 CMD_SHOWPREF,
55 CMD_SETPREF,
56 CMD_PASSWD,
57 CMD_PRIMARY,
58 CMD_TRUST,
59 CMD_REVUID,
60 CMD_REVKEY,
61 CMD_DISABLE,
62 CMD_ENABLE,
63 CMD_SIGN,
64 CMD_LSIGN,
65 CMD_CHECK,
66 CMD_CLEAN,
67 CMD_MINIMIZE
68 };
69
70 struct cmdlist_s {
71 const char *name;
72 unsigned int need_pair:1;
73 int id;
74 } cmdlist[] = {
75 {"ADDKEY", 1, CMD_ADDKEY},
76 {"ADDUID", 1, CMD_ADDUID},
77 {"ADDPHOTO", 1, CMD_ADDPHOTO},
78 {"ADDREVOKER", 1, CMD_ADDREVOKER},
79 {"DELUID", 1, CMD_DELUID},
80 {"DELKEY", 1, CMD_DELKEY},
81 {"EXPIRE", 1, CMD_EXPIRE},
82 {"SHOWPREF", 0, CMD_SHOWPREF},
83 {"SETPREF", 1, CMD_SETPREF},
84 {"PASSWD", 1, CMD_PASSWD},
85 {"PRIMARY", 1, CMD_PRIMARY},
86 {"TRUST", 0, CMD_TRUST},
87 {"REVUID", 1, CMD_REVUID},
88 {"REVKEY", 1, CMD_REVKEY},
89 {"DISABLE", 0, CMD_DISABLE},
90 {"ENABLE", 0, CMD_ENABLE},
91 {"SIGN", 0, CMD_SIGN},
92 {"LSIGN", 0, CMD_LSIGN},
93 {"CHECK", 0, CMD_CHECK},
94 {"CLEAN", 0, CMD_CLEAN},
95 {"MINIMIZE", 0, CMD_MINIMIZE},
96 {NULL, 0}
97 };
98
99
100 /* Symbolic ids for the subkey columns. */
101 enum subk_col_t {
102 SUBK_COL_DESC = 0,
103 SUBK_COL_KEYID = 1,
104 SUBK_COL_CREATION = 2,
105 SUBK_COL_EXPIRES = 3,
106 SUBK_COL_STATUS = 4,
107 SUBK_COL_C_FLAG = 5,
108 SUBK_COL_S_FLAG = 6,
109 SUBK_COL_E_FLAG = 7,
110 SUBK_COL_A_FLAG = 8
111 };
112
113 /* Symbolic ids for the userid columns. */
114 enum uid_col_t {
115 UID_COL_VALID = 0,
116 UID_COL_NAME = 1,
117 UID_COL_EMAIL = 2,
118 UID_COL_CREATION = 3
119 };
120
121 /* Key edit callback context. */
122 struct keyedit_cb_s {
123 HWND parent; /* parent window handle. */
124 const char *keyid; /* key ID of the key. */
125 const char *pass; /* pointer to the passphrase. */
126 listview_ctrl_t lv;
127 int lv_pos;
128 void *opaque;
129 unsigned int finished:1;
130 unsigned int is_protected:1;
131 };
132 typedef struct keyedit_cb_s *keyedit_cb_t;
133
134
135 /* Key generation callback context. */
136 struct keygen_cb_s {
137 int bits;
138 int algo;
139 DWORD expire;
140 char *fpr;
141 char *name;
142 char *comment;
143 char *email;
144 };
145 typedef struct keygen_cb_s *keygen_cb_t;
146
147 /* Subclass context for the subkey list. */
148 static subclass_s keyedit_subkey_proc;
149
150 /* Subclass context for the user-id list. */
151 static subclass_s keyedit_uid_proc;
152
153 int keygen_check_date (SYSTEMTIME *st);
154 void get_userid_preflist (const char *old_prefs, char **r_prefs, int *r_flags);
155 char* get_subkey_keyid (const char *keyid);
156 void ComboBox_AddString_utf8 (HWND cb, const char *txt);
157
158
159 /* Safe wrapper for allocation. */
160 static GpgKeyEdit*
161 create_GpgKeyEdit (const char *keyid)
162 {
163 GpgKeyEdit *ke;
164
165 ke = new GpgKeyEdit (keyid);
166 if (!ke)
167 BUG (NULL);
168 return ke;
169 }
170
171
172 /* Associate each key with a combo box entry.
173 Skip the key in @k. */
174 static void
175 do_init_keylist (HWND dlg, const char *keyid)
176 {
177 gpg_keycache_t pub;
178 gpgme_key_t key;
179 const char *s, *kid;
180 int i, n;
181
182 pub = keycache_get_ctx (1);
183 gpg_keycache_rewind (pub);
184 while (!gpg_keycache_next_key (pub, 0, &key)) {
185 if (key->expired || key->revoked ||
186 key->disabled || key->invalid)
187 continue;
188 s = key->uids->uid;
189 kid = key->subkeys->keyid;
190 if (!s || !strcmp (kid+8, keyid))
191 continue;
192 ComboBox_AddString_utf8 (GetDlgItem (dlg, IDC_ADDREV_KEYLIST), s);
193 }
194 gpg_keycache_rewind (pub);
195 n = SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0);
196 for (i = 0; i < n; i++) {
197 gpg_keycache_next_key (pub, 0, &key);
198 SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
199 (WPARAM)(int)i, (LPARAM)key);
200 }
201 SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
202 }
203
204
205 /* Add a new user-id to the list view @lv. */
206 static void
207 do_add_new_userid (listview_ctrl_t lv,
208 const char *utf8_name, const char *email,
209 const char *utf8_comment)
210 {
211 char *p, *native;
212 size_t n;
213
214 n = strlen (utf8_name) + strlen (email) + 16;
215 if (utf8_comment)
216 n += strlen (utf8_comment);
217 p = new char[n+1];
218 if (!p)
219 BUG (NULL);
220 if (utf8_comment)
221 sprintf (p, "%s (%s)", utf8_name, utf8_comment);
222 else
223 sprintf (p, "%s", utf8_name);
224 native = utf8_to_native (p);
225 free_if_alloc (p);
226
227 listview_add_item (lv, "");
228 listview_add_sub_item (lv, 0, UID_COL_VALID, _("Ultimate" ));
229 listview_add_sub_item (lv, 0, UID_COL_NAME, native);
230 listview_add_sub_item (lv, 0, UID_COL_EMAIL, email && *email? email : "");
231 listview_add_sub_item (lv, 0, UID_COL_CREATION, get_key_created (time (NULL)));
232 free_if_alloc (native);
233 }
234
235
236 static void
237 do_add_new_subkey (listview_ctrl_t lv, keygen_cb_t keygen, unsigned int flags)
238 {
239 char info[128], keyid[32];
240 const char *expdate, *s, *kid;
241 int n;
242
243 expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
244 _snprintf (info, sizeof (info)-1, "%d-bit %s",
245 keygen->bits,
246 get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
247 kid = get_keyid_from_fpr (keygen->fpr);
248 _snprintf (keyid, sizeof (keyid)-1, "0x%s", kid);
249 s = get_key_created (time (NULL));
250 n = listview_count_items (lv, 0);
251 listview_add_item_pos (lv, n);
252 listview_add_sub_item (lv, n, SUBK_COL_DESC, info);
253 listview_add_sub_item (lv, n, SUBK_COL_KEYID, keyid);
254 listview_add_sub_item (lv, n, SUBK_COL_CREATION, s);
255 listview_add_sub_item (lv, n, SUBK_COL_EXPIRES, expdate);
256 if (flags & KM_FLAG_REVOKED)
257 s = _("Revoked");
258 else if (flags & KM_FLAG_EXPIRED)
259 s = _("Expired");
260 else
261 s = _("OK");
262 listview_add_sub_item (lv, n, SUBK_COL_STATUS, s);
263 }
264
265
266 /* Try to find the GPG edit key index which belongs to the user ID
267 given by the email address @email, @name is used as a fallback.
268 If @r_inf != NULL, the info context will be returned.
269 Return value: index of the user ID or -1 on error. */
270 static int
271 do_find_userid (const char *keyid, const char *email,
272 const char *name, gpg_uid_info_t *r_inf)
273 {
274 GpgKeyEdit *ke;
275 gpgme_error_t err;
276 gpg_uid_info_t inf, ui;
277 int pos = -1;
278
279 ke = create_GpgKeyEdit (keyid);
280 err = ke->getUseridInfo (&inf);
281 delete ke;
282 if (err) {
283 log_box (_("user ID"), MB_ERR,
284 _("Could not get key information for: \"%s\":\n%s"),
285 name, gpgme_strerror (err));
286 return -1;
287 }
288
289 for (ui = inf; ui; ui = ui->next) {
290 if (name && email && ui->email && ui->name) {
291 if (!strcmp (ui->email, email) &&
292 !strncmp (ui->name, name, strlen (name))) {
293 pos = ui->index;
294 break;
295 }
296 continue;
297 }
298 if (email && ui->email) {
299 if (!strcmp (ui->email, email)) {
300 pos = ui->index;
301 break;
302 }
303 /* The email address is more unique, use the name just
304 as the fallbck when no email address is available. */
305 continue;
306 }
307 if (ui->name && name && !strcmp (ui->name, name)) {
308 pos = ui->index;
309 break;
310 }
311 }
312 if (r_inf)
313 *r_inf = inf;
314 else
315 gpg_uid_info_release (inf);
316 return pos;
317 }
318
319
320 /* Return true if @fname is a JPEG file. */
321 bool
322 is_jpg_file (const char *fname)
323 {
324 FILE *fp;
325 BYTE buf[10];
326 int n;
327
328 fp = fopen (fname, "rb");
329 if (!fp)
330 return false;
331 n = fread (buf, 1, 10, fp);
332 fclose (fp);
333 if (n < 10)
334 return false;
335 return buf[6] == 'J' && buf[7] == 'F' &&
336 buf[8] == 'I' && buf[9] == 'F';
337 }
338
339
340 /* Dialog box procedure to add a photo. */
341 BOOL CALLBACK
342 keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
343 {
344 static keyedit_cb_t cb;
345 GpgKeyEdit *ke;
346 gpgme_error_t err;
347 const char *s;
348 char file[128];
349 int id;
350
351 switch( msg ) {
352 case WM_INITDIALOG:
353 cb = (keyedit_cb_t)lparam;
354 if (!cb)
355 BUG (NULL);
356 SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key. If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is a good size to use."));
357 SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
358 SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
359 SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
360 SetWindowText (dlg, _("Add Photo ID"));
361 SetForegroundWindow (dlg);
362 break;
363
364 case WM_COMMAND:
365 switch( LOWORD (wparam)) {
366 case IDC_ADDPHOTO_SELFILE:
367 s = get_fileopen_dlg (dlg, _("Select Image File"),
368 "JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0",
369 NULL);
370 if (s && !is_jpg_file (s)) {
371 log_box (_("Add Photo"), MB_ERR,
372 _("'%s' is not a valid JPEG file."), s);
373 return FALSE;
374 }
375 if (s && *s)
376 SetDlgItemText (dlg, IDC_ADDPHOTO_FILE, s);
377 break;
378
379 case IDOK:
380 if (!GetDlgItemText (dlg, IDC_ADDPHOTO_FILE, file, sizeof (file)-1)){
381 msg_box (dlg, _("Please enter a file name."),
382 _("Add Photo"), MB_ERR);
383 return FALSE;
384 }
385 if (get_file_size (file) == 0 || get_file_size (file) > 6144) {
386 id = msg_box (dlg, _("The JPEG is really large.\n"
387 "Are you sure you want to use it?"),
388 _("Add Photo"), MB_YESNO|MB_INFO);
389 if (id == IDNO)
390 return TRUE;
391 }
392 ke = create_GpgKeyEdit (cb->keyid);
393 if (cb->pass)
394 ke->setPassphrase (cb->pass);
395 else
396 ke->setNoPassphrase (true);
397 err = ke->addPhotoid (file);
398 delete ke;
399 if (err) {
400 msg_box (dlg, gpgme_strerror (err), _("Add Photo"), MB_ERR);
401 return FALSE;
402 }
403 else {
404 cb->finished = 1;
405 msg_box (dlg, _("Photo successfully added."),
406 _("GnuPG Status"), MB_OK);
407 }
408 EndDialog (dlg, TRUE);
409 break;
410
411 case IDCANCEL:
412 EndDialog (dlg, FALSE);
413 break;
414 }
415 break;
416 }
417 return FALSE;
418 }
419
420
421 /* Dialog box procedure to add a designated revoker. */
422 BOOL CALLBACK
423 keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
424 {
425 static keyedit_cb_t cb;
426 gpgme_error_t err;
427 GpgKeyEdit *ke;
428 char *uid=NULL;
429
430 switch (msg) {
431 case WM_INITDIALOG:
432 cb = (keyedit_cb_t)lparam;
433 if (!cb)
434 BUG (NULL);
435 do_init_keylist (dlg, cb->keyid);
436 SetDlgItemText (dlg, IDC_ADDREV_INF,
437 _("Appointing a key as designated revoker cannot be undone."));
438 SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));
439 SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
440 SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
441 SetWindowText (dlg, _("Add Revoker"));
442 SetForegroundWindow (dlg);
443 center_window (dlg, cb->parent);
444 break;
445
446 case WM_COMMAND:
447 switch (LOWORD (wparam)) {
448 case IDOK:
449 if (!GetDlgItemText_utf8 (dlg, IDC_ADDREV_KEYLIST, &uid)) {
450 msg_box (dlg, _("Please select a user ID."), _("Add Revoker"), MB_ERR);
451 return FALSE;
452 }
453
454 ke = create_GpgKeyEdit (cb->keyid);
455 if (cb->pass)
456 ke->setPassphrase (cb->pass);
457 else
458 ke->setNoPassphrase (true);
459 err = ke->addDesignatedRevoker (uid);
460 delete ke;
461 safe_free (uid);
462 if (err) {
463 msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
464 return TRUE;
465 }
466 else {
467 cb->finished = 1;
468 msg_box (dlg, _("Revoker successfully addded."),
469 _("GnuPG Status"), MB_OK);
470 }
471 EndDialog (dlg, TRUE);
472 break;
473
474 case IDCANCEL:
475 EndDialog (dlg, FALSE);
476 break;
477 }
478 break;
479 }
480 return FALSE;
481 }
482
483
484 /* Dialog box procedure to add a new user-ID. */
485 BOOL CALLBACK
486 keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
487 {
488 static keyedit_cb_t ctx;
489 keygen_cb_t keygen;
490 gpgme_error_t err;
491 GpgKeyEdit *ke;
492 char *utf8_name = NULL;
493 char *utf8_comment = NULL;
494 char email[128];
495 int rc;
496
497 switch (msg) {
498 case WM_INITDIALOG:
499 ctx = (keyedit_cb_t)lparam;
500 if (!ctx)
501 dlg_fatal_error(dlg, "Could not get dialog param!");
502 SetWindowText (dlg, _("Add new User ID"));
503 SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name"));
504 SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email"));
505 SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment"));
506 SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
507 SetForegroundWindow (dlg);
508 center_window (dlg, ctx->parent);
509 return FALSE;
510
511 case WM_COMMAND:
512 switch ( LOWORD( wparam ) ) {
513 case IDOK:
514 keygen = (keygen_cb_t)ctx->opaque;
515 rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_NAME, &utf8_name);
516 if (!rc || rc < 5) {
517 msg_box (dlg, _("Please enter a name (min. 5 chars.)"),
518 _("UserID"), MB_ERR);
519 free_if_alloc (utf8_name);
520 return FALSE;
521 }
522 if (strchr (utf8_name, '@')) {
523 msg_box (dlg, _("Please enter the email address in the email field and not in the name field"),
524 _("UserID"), MB_INFO);
525 free_if_alloc (utf8_name);
526 return FALSE;
527 }
528
529 if( !GetDlgItemText (dlg, IDC_ADDUID_EMAIL, email, sizeof (email) -1)) {
530 msg_box (dlg, _("Please enter an email address."), _("UserID"), MB_ERR);
531 free_if_alloc (utf8_name);
532 return FALSE;
533 }
534 if (check_email_address (email)) {
535 msg_box (dlg, _("Invalid email address."), _("UserID"), MB_ERR);
536 free_if_alloc (utf8_name);
537 return FALSE;
538 }
539
540 rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_COMMENT, &utf8_comment);
541
542 ke = create_GpgKeyEdit (ctx->keyid);
543 if (ctx->is_protected)
544 ke->setPassphrase (ctx->pass);
545 else
546 ke->setNoPassphrase (true);
547 err = ke->addUserid (utf8_name, utf8_comment, email);
548 if (err)
549 msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
550 else {
551 msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
552 ctx->finished = 1;
553 /* The caller releases this items later. */
554 keygen->name = utf8_name;
555 keygen->comment = utf8_comment;
556 keygen->email = m_strdup (email);
557 }
558 delete ke;
559 EndDialog (dlg, TRUE);
560 return TRUE;
561
562 case IDCANCEL:
563 EndDialog (dlg, FALSE);
564 return FALSE;
565 }
566 break;
567 }
568
569 return FALSE;
570 }
571
572
573 /* Initalize a combo box with default key sizes (1024-4096). */
574 static void
575 init_keysize_box (HWND dlg, int ctlid)
576 {
577 const char *sizelist[] = {
578 "1024", "1536",
579 "2048", "3072",
580 "4096", NULL
581 };
582 int i;
583
584 for (i=0; sizelist[i] != NULL; i++)
585 SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
586 (LPARAM)(char*)sizelist[i]);
587 SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);
588 }
589
590
591 static int
592 get_keysize_from_box (HWND dlg, int ctlid)
593 {
594 int pos;
595 char buf[32];
596
597 pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
598 if (pos == CB_ERR)
599 return -1;
600 SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
601 return atoi (buf);
602 }
603
604
605 /* Create a time_t from a system time @st. */
606 time_t
607 w32_mktime (SYSTEMTIME *st)
608 {
609 struct tm tm;
610
611 memset (&tm, 0, sizeof (tm));
612 tm.tm_year = st->wYear-1900;
613 tm.tm_mday = st->wDay+1;
614 tm.tm_mon = st->wMonth-1;
615 return mktime (&tm);
616 }
617
618
619 /* Dialog procedure for adding a new secondary key. */
620 BOOL CALLBACK
621 keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
622 {
623 static keyedit_cb_t ctx;
624 keygen_cb_t keygen;
625 GpgKeyEdit *ke;
626 gpgme_error_t err;
627 SYSTEMTIME st;
628 HWND hwnd;
629 int index, size, valid;
630
631 switch (msg) {
632 case WM_INITDIALOG:
633 ctx = (keyedit_cb_t)lparam;
634 if (!ctx)
635 BUG (NULL);
636 SetWindowText (dlg, _("Add new Subkey"));
637 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));
638 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));
639 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration"));
640 SetDlgItemText (dlg, IDC_ADDSUBKEY_EXPIRE, _("&Never"));
641 SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
642
643 hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
644 listbox_add_string (hwnd, "DSA (sign only)");
645 listbox_add_string (hwnd, "ElGamal (encrypt only)");
646 listbox_add_string (hwnd, "RSA (sign only)");
647 listbox_add_string (hwnd, "RSA (encrypt only)");
648 CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
649 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
650 init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
651 SetForegroundWindow (dlg);
652 center_window (dlg, ctx->parent);
653 return FALSE;
654
655 case WM_COMMAND:
656 if (HIWORD (wparam) == BN_CLICKED &&
657 LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
658 if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
659 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
660 else
661 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
662 }
663 if (HIWORD (wparam) == LBN_SELCHANGE &&
664 LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
665 index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
666 if (index == 0)
667 SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL, 0, 0);
668 }
669
670 switch (LOWORD (wparam)) {
671 case IDOK:
672 keygen = (keygen_cb_t)ctx->opaque;
673 assert (keygen);
674 hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
675 switch (listbox_get_cursel (hwnd)) {
676 case 0: index = 2; break;
677 case 1: index = 4; break;
678 case 2: index = 5; break;
679 case 3: index = 6; break;
680 default:
681 msg_box (dlg, _("Please select one entry."),
682 _("Add Subkey"), MB_ERR);
683 return FALSE;
684 }
685 size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
686 if (index == 2 && size != 1024) {
687 msg_box (dlg,_("DSS uses a fixed keysize of 1024. Size changed."),
688 _("Add Subkey"), MB_INFO);
689 size = 1024;
690 }
691
692 hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE);
693 DateTime_GetSystemtime (hwnd, &st);
694 valid = w32_mktime (&st) - time (NULL);
695 valid /= 86400;
696
697 keygen->bits = size;
698 switch (index) {
699 case 2: keygen->algo = GPGME_PK_DSA; break;
700 case 4: keygen->algo = GPGME_PK_ELG_E; break;
701 case 5: keygen->algo = GPGME_PK_RSA_S; break;
702 case 6: keygen->algo = GPGME_PK_RSA_E; break;
703 }
704 if (valid > 0)
705 keygen->expire = time (NULL) + valid*24*60*60;
706
707 ke = create_GpgKeyEdit (ctx->keyid);
708 ke->setCallback (keygen_cb, NULL);
709 if (ctx->is_protected)
710 ke->setPassphrase (ctx->pass);
711 else
712 ke->setNoPassphrase (true);
713 keygen_cb_dlg_create ();
714
715 err = ke->addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
716 keygen->fpr = get_subkey_keyid (ctx->keyid);
717 keygen_cb_dlg_destroy (1);
718 if (err)
719 msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
720 else {
721 msg_box (dlg, _("Subkey successfully added."),
722 _("GnuPG Status"), MB_OK);
723 ctx->finished = 1;
724 }
725 delete ke;
726 EndDialog (dlg, TRUE);
727 return TRUE;
728
729 case IDCANCEL:
730 EndDialog (dlg, FALSE);
731 return FALSE;
732 }
733 break;
734 }
735
736 return FALSE;
737 }
738
739
740 BOOL
741 keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
742 {
743 keyedit_cb_s cb;
744 keygen_cb_s keygen;
745 char *pass = NULL;
746 int cancel = 0;
747
748 if (!k->key_pair) {
749 msg_box (dlg, _("There is no secret key available!"),
750 _("Add user ID"), MB_ERR);
751 return FALSE;
752 }
753
754 if (k->is_protected) {
755 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
756 if (cancel)
757 return FALSE;
758 }
759
760 memset (&keygen, 0, sizeof (keygen));
761 memset (&cb, 0, sizeof cb);
762 cb.parent = dlg;
763 cb.opaque = &keygen;
764 cb.is_protected = k->is_protected;
765 cb.pass = pass;
766 cb.keyid = k->keyid;
767 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
768 dlg, keyedit_adduid_dlg_proc,
769 (LPARAM)&cb, _("Add user ID"),
770 IDS_WINPT_KEYEDIT_ADDUID);
771 if (lv != NULL && cb.finished)
772 do_add_new_userid (lv, keygen.name, keygen.email, keygen.comment);
773 if (cb.finished)
774 k->update = 1;
775
776 free_if_alloc (keygen.name);
777 free_if_alloc (keygen.email);
778 free_if_alloc (keygen.comment);
779 sfree_if_alloc (pass);
780 return TRUE;
781 }
782
783
784 /* Return the keyID of the last subkey. */
785 char*
786 get_subkey_keyid (const char *keyid)
787 {
788 gpgme_error_t err;
789 gpgme_key_t key;
790 gpgme_ctx_t ctx;
791 gpgme_subkey_t subk;
792 char *kid = NULL;
793
794 err = gpgme_new (&ctx);
795 if (err)
796 return NULL;
797 err = gpgme_get_key (ctx, keyid, &key, 0);
798 gpgme_release (ctx);
799 if (err)
800 return NULL;
801 subk = get_nth_key (key, count_subkeys (key));
802 if (subk != NULL)
803 kid = strdup (subk->keyid);
804 gpgme_key_release (key);
805 return kid;
806 }
807
808
809 BOOL
810 keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
811 {
812 keyedit_cb_s cb;
813 keygen_cb_s keygen;
814 char *pass = NULL;
815 int cancel = 0;
816
817 if (!k->key_pair) {
818 msg_box (dlg, _("There is no secret key available!"),
819 _("Add Subkey"), MB_ERR);
820 return FALSE;
821 }
822 if (k->is_protected) {
823 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
824 if (cancel)
825 return FALSE;
826 }
827
828 memset (&keygen, 0, sizeof (keygen));
829 memset (&cb, 0, sizeof (cb));
830 cb.keyid = k->keyid;
831 cb.is_protected = k->is_protected;
832 cb.pass = pass;
833 cb.opaque = &keygen;
834 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,
835 dlg, keyedit_addsubkey_dlg_proc,
836 (LPARAM)&cb, _("Add new Subkey"),
837 IDS_WINPT_KEYEDIT_ADDSUBKEY);
838 if (lv != NULL && cb.finished)
839 do_add_new_subkey (lv, &keygen, 0);
840 if (cb.finished)
841 k->update = 1;
842
843 safe_free (keygen.fpr);
844 sfree_if_alloc (pass);
845 return cb.finished? TRUE: FALSE;
846 }
847
848
849 /* Set the preferred keyserver of the given key @k. */
850 BOOL
851 keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
852 {
853 GpgKeyEdit *ke;
854 gpgme_error_t err;
855 struct URL_ctx_s *url;
856 char *pass = NULL;
857
858 url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
859 if (url->cancel == 1) {
860 delete url;
861 return FALSE;
862 }
863
864 pass = request_key_passphrase (k->ctx, _("Key Edit"), &url->cancel);
865 if (url->cancel) {
866 delete url;
867 return FALSE;
868 }
869
870 ke = create_GpgKeyEdit (k->keyid);
871 if (k->is_protected)
872 ke->setPassphrase (pass);
873 else
874 ke->setNoPassphrase (true);
875 err = ke->setPreferredKeyserver (-1, url->url);
876 if (!err)
877 msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);
878 else
879 msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
880
881 sfree_if_alloc (pass);
882 delete ke;
883 delete url;
884 return err == 0? 0 : WPTERR_GENERAL;
885 }
886
887
888 /* Add a photo-ID to the key specified in @k. @dlg is the handle of
889 the calling dialog. */
890 BOOL
891 keyedit_add_photo (winpt_key_t k, HWND dlg)
892 {
893 keyedit_cb_s cb;
894 char *pass = NULL;
895 int cancel;
896
897 if (!k->key_pair) {
898 msg_box (dlg, _("There is no secret key available!"),
899 _("Add Photo"), MB_ERR);
900 return FALSE;
901 }
902
903 memset (&cb, 0, sizeof (cb));
904 if (k->is_protected) {
905 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
906 if (cancel)
907 return FALSE;
908 }
909 cb.parent = dlg;
910 cb.pass = pass;
911 cb.keyid = k->keyid;
912 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
913 keyedit_addphoto_dlg_proc, (LPARAM)&cb);
914
915 if (cb.finished)
916 k->update = 1;
917 sfree_if_alloc (pass);
918 return TRUE;
919 }
920
921
922 BOOL
923 keyedit_add_revoker (winpt_key_t k, HWND dlg)
924 {
925 keyedit_cb_s cb;
926 char *pass = NULL;
927 int cancel;
928
929 if (!k->key_pair) {
930 msg_box (dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR);
931 return FALSE;
932 }
933
934 if (k->is_protected) {
935 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
936 if (cancel)
937 return FALSE;
938 }
939
940 memset (&cb, 0, sizeof (cb));
941 cb.parent = dlg;
942 cb.is_protected = k->is_protected;
943 cb.keyid = k->keyid;
944 cb.pass = pass;
945 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
946 keyedit_addrevoker_dlg_proc, (LPARAM)&cb);
947
948 if (cb.finished)
949 k->update = 1;
950 sfree_if_alloc (pass);
951 return TRUE;
952 }
953
954
955 /* Change ownertrust of the given key @key.
956 Return TRUE if the ownertrust was changed. */
957 BOOL
958 keyedit_change_ownertrust (winpt_key_t key, HWND dlg)
959 {
960 int rc;
961
962 rc = dialog_box_param (glob_hinst,
963 (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,
964 dlg, keyedit_ownertrust_dlg_proc,
965 (LPARAM)key, _("Change Ownertrust"),
966 IDS_WINPT_KEYEDIT_OWNERTRUST);
967 if (rc == TRUE) {
968 msg_box (dlg, _("Key status changed."), _("Key Edit"), MB_OK);
969 key->update = 1;
970 }
971 return rc;
972 }
973
974
975 /* Check if the given key is supposed to have IDEA
976 for secret key protection. */
977 static int
978 is_idea_protect_algo (const char *keyid)
979 {
980 winpt_key_s k;
981 const unsigned char *sym_prefs;
982 size_t n;
983
984 memset (&k, 0, sizeof (k));
985 if (winpt_get_pubkey (keyid, &k))
986 BUG (NULL);
987 if (!k.is_v3)
988 return 0;
989 sym_prefs = k.ext->sym_prefs;
990 if (!sym_prefs)
991 return 1; /* assume that only v3 keys have no symmetric cipher preferences
992 and thus IDEA is explicit. */
993 for (n = 0; sym_prefs[n]; n++)
994 ;
995 if ((n == 0 || n == 1) && *sym_prefs == 0x01)
996 return 1;
997 return 0;
998 }
999
1000
1001 BOOL
1002 keyedit_change_passwd (winpt_key_t k, HWND dlg)
1003 {
1004 gpgme_error_t err;
1005 GpgKeyEdit *ke;
1006 char *old_pass = NULL;
1007 char *new_pass = NULL;
1008 int cancel = 0;
1009
1010 if (!k->key_pair) {
1011 msg_box (dlg, _("There is no secret key available!"),
1012 _("Key Edit"), MB_ERR);
1013 return FALSE;
1014 }
1015
1016 if (!idea_available && is_idea_protect_algo (k->keyid)) {
1017 msg_box (dlg, _("Cannot change passphrase because the key\n"
1018 "is protected with the IDEA encryption algorithm."),
1019 _("Key Edit"), MB_ERR);
1020 return FALSE;
1021 }
1022
1023 if (k->is_protected) {
1024 old_pass = request_passphrase (_("Current (old) Passphrase"),
1025 PASSDLG_INIT, &cancel);
1026 if (cancel)
1027 return FALSE;
1028 }
1029 new_pass = request_passphrase2 (_("New Passphrase" ),
1030 PASSDLG_INIT|PASSDLG_WARN_UTF8, &cancel);
1031 if (cancel) {
1032 sfree_if_alloc (old_pass);
1033 return FALSE;
1034 }
1035
1036 if (strlen (new_pass) == 0) {
1037 cancel = msg_box (dlg, _("Are you sure that you really don't want a passphrase?\n"
1038 "This is propably a bad idea, still proceed?"),
1039 _("Key Edit"), MB_WARN_ASK);
1040 if (cancel != IDYES) {
1041 sfree_if_alloc (old_pass);
1042 sfree_if_alloc (new_pass);
1043 return FALSE;
1044 }
1045 }
1046
1047 ke = create_GpgKeyEdit (k->keyid);
1048 ke->setPassphrase (k->is_protected? old_pass : NULL);
1049 if (!k->is_protected)
1050 ke->setNoPassphrase (true);
1051 err = ke->changePassphrase (new_pass, 1);
1052 if (err)
1053 msg_box (dlg, gpgme_strerror (err), _("Change Passwd"), MB_ERR);
1054 else
1055 msg_box (dlg, _("Passphrase successfully changed."), _("GnuPG status"), MB_OK);
1056 sfree_if_alloc (old_pass);
1057 sfree_if_alloc (new_pass);
1058 delete ke;
1059 return TRUE;
1060 }
1061
1062
1063 /* Initialize sub key list from key @k and return
1064 the new listview control. */
1065 listview_ctrl_t
1066 subkey_list_init (HWND dlg, winpt_key_t k)
1067 {
1068 LV_ITEM lvi;
1069 gpgme_subkey_t sub;
1070 struct listview_column_s cols[] = {
1071 {0, 80, (char *)_("Description")},
1072 {1, 78, (char *)_("Key ID")},
1073 {2, 66, (char *)_("Creation")},
1074 {3, 66, (char *)_("Expires")},
1075 {4, 64, (char *)_("Status")},
1076 {5, 16, "C"/*ertify*/},
1077 {6, 16, "S"/*ign*/},
1078 {7, 16, "E"/*ncrypt*/},
1079 {8, 16, "A"/*uth*/},
1080 {0, 0, 0}
1081 };
1082 listview_ctrl_t lv;
1083 char buf[256], tmp[128];
1084 const char *t;
1085 int nkeys = 0, i;
1086
1087 nkeys = count_subkeys (k->ctx);
1088 if (!nkeys)
1089 BUG (NULL); /* should never happen. */
1090
1091 listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
1092 for (i = 0; cols[i].fieldname != NULL; i++)
1093 listview_add_column (lv, &cols[i]);
1094
1095 for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
1096 listview_add_item (lv, "");
1097 listview_add_sub_item (lv, 0, 1, "");
1098 memset (&lvi, 0, sizeof (lvi));
1099 lvi.mask = LVIF_PARAM;
1100 lvi.lParam = (LPARAM)sub;
1101 if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
1102 BUG (NULL);
1103 }
1104
1105 listview_set_ext_style (lv);
1106 for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
1107 _snprintf (buf, sizeof buf-1, "%d-bit %s", sub->length,
1108 get_key_pubalgo (sub->pubkey_algo));
1109 listview_add_sub_item (lv, i, SUBK_COL_DESC, buf);
1110 t = sub->keyid;
1111 assert (t != NULL);
1112 _snprintf (tmp, sizeof tmp-1, "0x%s", t+8);
1113 listview_add_sub_item (lv, i, SUBK_COL_KEYID, tmp);
1114
1115 t = get_key_created (sub->timestamp);
1116 if (!t)
1117 t = "????" "-??" "-??";
1118 listview_add_sub_item (lv, i, SUBK_COL_CREATION, t);
1119
1120 if (sub->expires) {
1121 t = get_key_created (sub->expires);
1122 listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, t);
1123 }
1124 else
1125 listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, _("Never"));
1126 if (sub->expired)
1127 t = _("Expired");
1128 else if (sub->revoked)
1129 t = _("Revoked");
1130 else
1131 t = _("OK");
1132 listview_add_sub_item (lv, i, SUBK_COL_STATUS, t);
1133
1134 if (sub->can_certify) t = "*"; else t = "";
1135 listview_add_sub_item (lv, i, SUBK_COL_C_FLAG, t);
1136 if (sub->can_sign) t = "*"; else t = "";
1137 listview_add_sub_item( lv, i, SUBK_COL_S_FLAG, t );
1138 if (sub->can_encrypt) t = "*"; else t = "";
1139 listview_add_sub_item( lv, i, SUBK_COL_E_FLAG, t );
1140 if (sub->can_authenticate) t = "*"; else t = "";
1141 listview_add_sub_item (lv, i, SUBK_COL_A_FLAG, t);
1142 }
1143 return lv;
1144 }
1145
1146
1147 static listview_ctrl_t
1148 userid_list_init (HWND dlg, winpt_key_t k)
1149 {
1150 listview_ctrl_t lv = NULL;
1151 gpgme_key_sig_t ks;
1152 struct native_uid_s *u;
1153 int nuids = 0, j, u_attr;
1154 struct listview_column_s cols[] = {
1155 {0, 72, (char *)_("Validity")},
1156 {1, 150, (char *)_("Name")},
1157 {2, 110, (char *)_("Email")},
1158 {3, 76, (char *)_("Creation")},
1159 {0, 0, 0}
1160 };
1161 const char *attr;
1162
1163 nuids = count_userids (k->ctx);
1164 if (!nuids)
1165 BUG (NULL); /* should never happen. */
1166
1167 listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST));
1168 for (j = 0; cols[j].fieldname != NULL; j++)
1169 listview_add_column (lv, &cols[j]);
1170
1171 for (j = 0; j < nuids; j++) {
1172 listview_add_item (lv, " ");
1173 listview_add_sub_item (lv, 0, 1, " " );
1174 }
1175
1176 listview_set_ext_style (lv);
1177 for (j = 0, u=k->ext->uids; j < nuids; u=u->next, j++) {
1178 if (u->revoked)
1179 attr = _("Revoked");
1180 else {
1181 u_attr = (int)u->validity;
1182 attr = get_key_trust2 (NULL, u_attr, 0, 0);
1183 }
1184 listview_add_sub_item (lv, j, UID_COL_VALID, (char *)attr);
1185 /* XXX: add comment if available */
1186 listview_add_sub_item (lv, j, UID_COL_NAME,
1187 u->name? u->name : _("Invalid user ID"));
1188 if (u->email)
1189 listview_add_sub_item (lv, j, UID_COL_EMAIL, u->email);
1190
1191 ks = get_selfsig (u->signatures, k->keyid, 1);
1192 if (ks)
1193 listview_add_sub_item (lv, j, UID_COL_CREATION,
1194 get_key_created (ks->timestamp));
1195 }
1196 if (!k->key_pair) {
1197 CheckDlgButton (dlg, IDC_KEYUID_ADD, BST_INDETERMINATE);
1198 CheckDlgButton (dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE);
1199 }
1200 return lv;
1201 }
1202
1203
1204 static void
1205 do_init_cmdlist (HWND dlg, int is_keypair)
1206 {
1207 const char *s;
1208 int i = 0;
1209
1210 for (i = 0; (s=cmdlist[i].name); i++) {
1211 if (is_keypair)
1212 SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1213 (LPARAM)(char *)s);
1214 else if (!cmdlist[i].need_pair)
1215 SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1216 (LPARAM)(char *)s);
1217 }
1218 SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0);
1219 }
1220
1221
1222 /* Return 1 if the requested command is RFC2440. */
1223 static int
1224 is_cmd_openpgp (int cmdid)
1225 {
1226 switch (cmdid) {
1227 case CMD_ADDKEY:
1228 case CMD_ADDPHOTO:
1229 case CMD_ADDREVOKER:
1230 case CMD_SETPREF:
1231 return 1;
1232 }
1233 return 0;
1234 }
1235
1236
1237 /* Display a message box with a short description of the commands. */
1238 static void
1239 do_show_help (HWND dlg)
1240 {
1241 const char *help;
1242
1243 help =
1244 _(
1245 "ADDUID add a user ID\r\n"
1246 "ADDPHOTO add a photo ID\r\n"
1247 "DELUID delete a user ID\r\n"
1248 "ADDKEY add a secondard key\r\n"
1249 "DELKEY delete a secondary key\r\n"
1250 "ADDREVOKER add a revocation key\r\n"
1251 "EXPIRE change the expire date\r\n"
1252 "SHOWPREF list preferences (verbose)\r\n"
1253 "SETPREF set preference list\r\n"
1254 "UPDPREF updated preferences\r\n"
1255 "PASSWD change the passphrase\r\n"
1256 "PRIMARY flag user ID as primary\r\n"
1257 "TRUST change the ownertrust\r\n"
1258 "REVUID revoke a user ID\r\n"
1259 "REVKEY revoke a secondary key\r\n"
1260 "DISABLE disable a key\r\n"
1261 "ENABLE enable a key\r\n"
1262 "SIGN sign a user-id (exportable)\r\n"
1263 "LSIGN sign a user-id (non-exportable)\r\n"
1264 "CLEAN remove unusable signatures from key\r\n"
1265 "MINIMIZE remove all signatures from key\r\n"
1266 );
1267 msg_box (dlg, help, _("Key Edit Help"), MB_OK);
1268 }
1269
1270
1271 static int
1272 do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1273 {
1274 gpgme_error_t err;
1275 GpgKeyEdit *ke;
1276 int pos, id;
1277 char tmp[64];
1278
1279 if (!k->key_pair)
1280 return FALSE;
1281
1282 if (listview_count_items (lv, 0) == 1) {
1283 msg_box (dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
1284 return FALSE;
1285 }
1286 pos = listview_get_curr_pos (lv);
1287 if (pos == -1) {
1288 msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
1289 return FALSE;
1290 }
1291 if (pos == 0) {
1292 msg_box (dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
1293 return FALSE;
1294 }
1295
1296 /* XXX: change the warning to make clear that verification won't work
1297 any longer if this is a sign-only key. */
1298 listview_get_item_text (lv, pos, 0, tmp, sizeof (tmp) -1);
1299 id = log_box (_("Key Edit"), MB_YESNO|MB_ICONWARNING,
1300 _("\"Subkey %s.\"\n\n"
1301 "Anything encrypted to the selected subkey will no longer\n"
1302 "be able to be decrypted.\n\n"
1303 "Do you really want to delete this subkey?"), tmp);
1304 if (id == IDNO)
1305 return FALSE;
1306
1307 ke = create_GpgKeyEdit (k->keyid);
1308 err = ke->delKey (pos);
1309 if (err)
1310 msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
1311 else {
1312 listview_del_item (lv, pos);
1313 k->update = 1;
1314 status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));
1315 }
1316 delete ke;
1317 return err? FALSE : TRUE;
1318 }
1319
1320
1321 /* Set the expiration date for the selected key in list view @lv.
1322 Return value: TRUE on success. */
1323 static int
1324 do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1325 {
1326 gpgme_error_t err;
1327 GpgKeyEdit *ke;
1328 date_s udd = {0};
1329 char buf[256], * pass = NULL;
1330 time_t exp;
1331 int pos, cancel = 0;
1332
1333 if (!k->key_pair) {
1334 msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1335 return FALSE;
1336 }
1337 pos = listview_get_curr_pos (lv);
1338 if (pos == -1) {
1339 msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
1340 return FALSE;
1341 }
1342
1343 /* If a key already expired, it is possible the user wants to
1344 set a new expiration date.. */
1345 listview_get_item_text (lv, pos, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1346 if (!strcmp (buf, _("Expired"))) {
1347 cancel = msg_box (dlg, _("Key already expired.\n\n"
1348 "Do you want to change the expiration date?"),
1349 _("Key Edit"), MB_QUEST_ASK);
1350 if (cancel == IDNO)
1351 return FALSE;
1352 cancel = 0;
1353 }
1354
1355 memset (&udd, 0, sizeof udd);
1356 udd.text = _("Key Expiration Date");
1357 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
1358 date_dlg_proc, (LPARAM)&udd,
1359 _("Key Expiration Date"), IDS_WINPT_DATE);
1360 if (udd.cancel == 1)
1361 return FALSE;
1362 if (!keygen_check_date (&udd.st)) {
1363 msg_box (dlg, _("The date you have chosen lies in the past."),
1364 _("Key Edit"), MB_ERR);
1365 return FALSE;
1366 }
1367 if (k->is_protected) {
1368 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1369 if (cancel)
1370 return FALSE;
1371 }
1372 exp = w32_mktime (&udd.st);
1373 ke = create_GpgKeyEdit (k->keyid);
1374 if (k->is_protected)
1375 ke->setPassphrase (pass);
1376 else
1377 ke->setNoPassphrase (true);
1378 err = ke->setKeyExpireDate (pos, exp, false);
1379 if (err)
1380 msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
1381 else {
1382 _snprintf (buf, sizeof (buf)-1, "%s", get_key_created (exp));
1383 listview_add_sub_item (lv, pos, SUBK_COL_EXPIRES, buf);
1384 k->update = 1;
1385 msg_box (dlg, _("Subkey expire date successfully set."),
1386 _("GnuPG status"), MB_OK);
1387 }
1388 sfree_if_alloc (pass);
1389 delete ke;
1390 return TRUE;
1391 }
1392
1393
1394 /* Revoke the selected key in the list view @lv. @k contains
1395 control information about the global key.
1396 Return value: TRUE on success. */
1397 static int
1398 do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1399 {
1400 gpgme_error_t err;
1401 GpgKeyEdit *ke;
1402 char buf[256];
1403 char *pass = NULL;
1404 int j, cancel = 0;
1405
1406 if (!k->key_pair) {
1407 msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1408 return FALSE;
1409 }
1410
1411 if ((j = listview_get_curr_pos (lv)) == -1) {
1412 msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1413 return FALSE;
1414 }
1415 else if (listview_count_items (lv, 0) == 1) {
1416 msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
1417 "whole key, please use the Key Manager command directly.\n\n"
1418 "This command is only available to revoke single subkeys"),
1419 _("Key Edit"), MB_INFO );
1420 return FALSE;
1421 }
1422
1423 listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1424 if (!strcmp (buf, _("Revoked"))) {
1425 msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1426 return FALSE;
1427 }
1428
1429 if (k->is_protected) {
1430 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1431 if (cancel)
1432 return FALSE;
1433 }
1434
1435 ke = create_GpgKeyEdit (k->keyid);
1436 if (k->is_protected)
1437 ke->setPassphrase (pass);
1438 else
1439 ke->setNoPassphrase (true);
1440 err = ke->revokeSubkey (j, 0, NULL);
1441 if (err)
1442 msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
1443 else {
1444 listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
1445 k->update = 1;
1446 msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1447 }
1448 sfree_if_alloc (pass);
1449 delete ke;
1450 return TRUE;
1451 }
1452
1453
1454 /* Revoked the selected userid in list view @lv.
1455 Return value: TRUE on success. */
1456 int
1457 do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1458 {
1459 gpgme_error_t err;
1460 GpgKeyEdit *ke;
1461 char buf[128], email[128];
1462 char inf[512];
1463 char *pass = NULL;
1464 int cancel = 0, id = 0, j;
1465
1466 if (!k->key_pair) {
1467 msg_box (dlg, _("There is no secret key available!"),
1468 _("Revoke user ID"), MB_ERR);
1469 return FALSE;
1470 }
1471
1472 if (listview_count_items (lv, 0) == 1) {
1473 msg_box (dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR);
1474 return FALSE;
1475 }
1476
1477 if( (j = listview_get_curr_pos( lv )) == -1 ) {
1478 msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1479 return FALSE;
1480 }
1481
1482 listview_get_item_text( lv, j, UID_COL_VALID, buf, sizeof buf - 1);
1483 if (strstr (buf, _("Revoked"))) {
1484 msg_box (dlg, _("This user ID has been already revoked."),
1485 _("Key Edit"), MB_INFO);
1486 return FALSE;
1487 }
1488
1489 listview_get_item_text (lv, j, UID_COL_NAME, buf, sizeof buf -1);
1490 _snprintf (inf, sizeof (inf) -1, _("user ID \"%s\".\n\n"
1491 "Do you really want to revoke this user ID?"), buf);
1492 if (msg_box (dlg, inf, _("Key Edit"), MB_WARN_ASK) == IDNO)
1493 return FALSE;
1494 if (k->is_protected) {
1495 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1496 if (cancel)
1497 return FALSE;
1498 }
1499 listview_get_item_text (lv, j, UID_COL_EMAIL, email, sizeof (email)-1);
1500 listview_get_item_text (lv, j, UID_COL_NAME, buf, sizeof (buf)-1);
1501 id = do_find_userid (k->keyid, email, buf, NULL);
1502 if (id == -1)
1503 BUG (NULL);
1504
1505 ke = create_GpgKeyEdit (k->keyid);
1506 if (k->is_protected)
1507 ke->setPassphrase (pass);
1508 else
1509 ke->setNoPassphrase (true);
1510 err = ke->revokeUserid (id);
1511 if (err)
1512 msg_box (dlg, gpgme_strerror (err), _("Revoke User ID"), MB_ERR);
1513 else {
1514 listview_add_sub_item (lv, j, 0, _("Revoked"));
1515 k->update = 1;
1516 status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1517 }
1518 sfree_if_alloc (pass);
1519 delete ke;
1520 return err? FALSE : TRUE;
1521 }
1522
1523
1524 static int
1525 do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1526 {
1527 gpgme_error_t err;
1528 GpgKeyEdit *ke;
1529 gpg_uid_info_t uidinf = NULL;
1530 char buf[256], *pass = NULL, *prefs = NULL;
1531 int pos, id, cancel=0, flags=0;
1532
1533 pos = listview_get_curr_pos (lv);
1534 if (pos == -1) {
1535 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1536 return FALSE;
1537 }
1538 listview_get_item_text (lv, pos, 2, buf, sizeof buf-1);
1539 id = do_find_userid (k->keyid, buf, NULL, &uidinf);
1540 if (id == -1)
1541 BUG (NULL);
1542 if (k->is_protected) {
1543 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1544 gpg_uid_info_release (uidinf);
1545 if (cancel)
1546 return FALSE;
1547 }
1548
1549 get_userid_preflist (uidinf->prefs, &prefs, &flags);
1550 gpg_uid_info_release (uidinf);
1551 if (!prefs) {
1552 sfree_if_alloc (pass);
1553 return FALSE;
1554 }
1555
1556 ke = create_GpgKeyEdit (k->keyid);
1557 if (k->is_protected)
1558 ke->setPassphrase (pass);
1559 else
1560 ke->setNoPassphrase (true);
1561 err = ke->setUseridPreferences (id, prefs);
1562 if (err)
1563 msg_box (dlg, gpgme_strerror (err), _("Set user ID preferences"), MB_ERR);
1564 else {
1565 k->update = 1;
1566 status_box (dlg, _("User ID preferences successfully updated"), _("GnuPG Status"));
1567 }
1568
1569 sfree_if_alloc (pass);
1570 free_if_alloc (prefs);
1571 delete ke;
1572 return err? FALSE: TRUE;
1573 }
1574
1575
1576 static int
1577 do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1578 {
1579 gpgme_error_t err;
1580 GpgKeyEdit *ke;
1581 int j, id, cancel=0;
1582 char valid[32];
1583 char buf[256], *pass = NULL;
1584
1585 if (listview_count_items (lv, 0) == 1)
1586 return TRUE;
1587 if ((j = listview_get_curr_pos (lv)) == -1) {
1588 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1589 return FALSE;
1590 }
1591 listview_get_item_text (lv, j, UID_COL_VALID, valid, sizeof (valid)-1);
1592 if (!strcmp (valid, _("Revoked")))
1593 return FALSE;
1594 listview_get_item_text (lv, j, UID_COL_EMAIL, buf, sizeof (buf)-1);
1595 id = do_find_userid (k->keyid, buf, NULL, NULL);
1596 if (id == -1)
1597 BUG (NULL);
1598 if (k->is_protected) {
1599 pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1600 if (cancel)
1601 return FALSE;
1602 }
1603
1604 ke = create_GpgKeyEdit (k->keyid);
1605 if (k->is_protected)
1606 ke->setPassphrase (pass);
1607 else
1608 ke->setNoPassphrase (true);
1609 err = ke->setPrimaryUserid (id);
1610 if (err)
1611 msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
1612 else {
1613 k->update = 1;
1614 status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
1615 }
1616
1617 sfree_if_alloc (pass);
1618 delete ke;
1619 return err? FALSE : TRUE;
1620 }
1621
1622
1623
1624 #define CIPHER 11
1625 #define HASH 11
1626 #define COMPR 4
1627
1628 static int
1629 parse_preflist (HWND dlg, const char *list)
1630 {
1631 char buf[128] = {0};
1632 char *p, *pbuf = buf;
1633 const char *ciphers[CIPHER] = {"", "IDEA", "3DES",
1634 "CAST5", "BLOWFISH", "", "",
1635 "AES", "AES192", "AES256", "TWOFISH"};
1636 const char *hash[HASH] = {"", "MD5", "SHA1", "RMD160", "",
1637 "", "", "", "SHA256", "SHA384", "SHA512"};
1638 const char *compress[COMPR] = {"", "ZIP", "ZLIB", "BZIP2"};
1639 int n=0;
1640
1641 strncpy (buf, list, 127);
1642 p = strtok (pbuf, " ");
1643 while (p != NULL) {
1644 int algid = atol (p+1);
1645 n++;
1646 switch (*p) {
1647 case 'S':
1648 SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0,
1649 (LPARAM)(const char*)ciphers[algid % CIPHER]);
1650 break;
1651
1652 case 'H':
1653 SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0,
1654 (LPARAM)(const char*)hash[algid % HASH]);
1655 break;
1656
1657 case 'Z':
1658 SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0,
1659 (LPARAM)(const char*)compress[algid % COMPR]);
1660 break;
1661
1662 default:
1663 n--;
1664 }
1665 p = strtok (NULL, " ");
1666 }
1667 return n;
1668 }
1669
1670
1671 /* Dialog box procedure to show the key preferences. */
1672 BOOL CALLBACK
1673 showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1674 {
1675 static keyedit_cb_t cb = NULL;
1676 gpg_uid_info_t inf=NULL, u;
1677 gpgme_key_t key;
1678 char buf[128];
1679 int pos;
1680
1681 switch (msg) {
1682 case WM_INITDIALOG:
1683 cb = (keyedit_cb_t)lparam;
1684 if (!cb)
1685 BUG (NULL);
1686 key = (gpgme_key_t)cb->opaque;
1687 listview_get_item_text (cb->lv, cb->lv_pos,
1688 UID_COL_EMAIL, buf, sizeof (buf)-1);
1689 pos = do_find_userid (cb->keyid, buf, NULL, &inf);
1690 if (pos < 0 || !inf) {
1691 gpg_uid_info_release (inf);
1692 EndDialog (dlg, FALSE);
1693 break;
1694 }
1695 for (u=inf; u; u = u->next) {
1696 if (u->index == pos && u->prefs && *u->prefs) {
1697 _snprintf (buf, sizeof (buf)-1, "%s", u->name);
1698 SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1699 if (parse_preflist (dlg, u->prefs) <= 0)
1700 pos = -1;
1701 if (u->flags.mdc)
1702 CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1703 break;
1704 }
1705 }
1706 gpg_uid_info_release (inf);
1707 if (pos == -1) {
1708 msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1709 EndDialog (dlg, FALSE);
1710 break;
1711 }
1712 SetDlgItemText (dlg, IDC_SHOWPREF_MDC, _("MDC feature"));
1713 SetDlgItemText (dlg, IDC_SHOWPREF_PREFINF, _("Preferences"));
1714 SetDlgItemText (dlg, IDC_SHOWPREF_UIDHINT, _("user ID:"));
1715 SetWindowText (dlg, _("Key Preferences"));
1716 SetForegroundWindow (dlg);
1717 center_window (dlg, cb->parent);
1718 break;
1719
1720 case WM_COMMAND:
1721 switch (LOWORD (wparam)) {
1722 case IDOK:
1723 EndDialog (dlg, TRUE);
1724 break;
1725
1726 case IDCANCEL:
1727 EndDialog (dlg, FALSE);
1728 break;
1729 }
1730 break;
1731 }
1732 return FALSE;
1733 }
1734
1735
1736 static int
1737 do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1738 {
1739 struct keyedit_cb_s cb;
1740 char status[32];
1741
1742 if (k->is_v3)
1743 return TRUE;
1744
1745 if (listview_get_curr_pos (lv) == -1) {
1746 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1747 return FALSE;
1748 }
1749 memset (&cb, 0, sizeof (cb));
1750 cb.parent = dlg;
1751 cb.opaque = k->ctx;
1752 cb.keyid = k->keyid;
1753 cb.lv = lv;
1754 cb.lv_pos = listview_get_curr_pos (lv);
1755
1756 listview_get_item_text (lv, cb.lv_pos, UID_COL_VALID,
1757 status, sizeof (status)-1);
1758 if (!strcmp (status, _("Revoked")))
1759 return TRUE;
1760
1761 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1762 showpref_dlg_proc, (LPARAM)&cb);
1763 return TRUE;
1764 }
1765
1766
1767 static int
1768 do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1769 {
1770 gpgme_error_t err;
1771 GpgKeyEdit *ke;
1772 char email[128], name[128];
1773 char inf[384];
1774 int pos, id = 0;
1775
1776 if (!k->key_pair)
1777 return FALSE;
1778
1779 if (listview_count_items (lv, 0) == 1) {
1780 msg_box (dlg, _("Primary user ID can not be deleted!"),
1781 _("Key Edit"), MB_ERR);
1782 return FALSE;
1783 }
1784 pos = listview_get_curr_pos (lv);
1785 if (pos == -1) {
1786 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1787 return FALSE;
1788 }
1789
1790 listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM(name) -1);
1791 _snprintf (inf, DIM (inf)-1, _("user ID \"%s\".\n\n"
1792 "All signatures on this user ID will be also deleted."
1793 "\n\n"
1794 "Do you really want to delete this user ID?"),
1795 name);
1796 if (msg_box (dlg, inf, _("Key Edit"), MB_YESNO|MB_ICONWARNING) == IDNO)
1797 return FALSE;
1798
1799 listview_get_item_text (lv, pos, UID_COL_EMAIL, email, DIM (email)-1);
1800 listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM (name)-1);
1801 id = do_find_userid (k->keyid, email, name, NULL);
1802 if (id == -1)
1803 BUG (NULL);
1804
1805 ke = create_GpgKeyEdit (k->keyid);
1806 err = ke->delUserid (id);
1807 if (err)
1808 msg_box (dlg, gpgme_strerror (err), _("Delete User ID"), MB_ERR);
1809 else {
1810 listview_del_item (lv, pos);
1811 k->update = 1;
1812 status_box (dlg, _("User ID successfully deleted"), _("GnuPG Status"));
1813 }
1814 delete ke;
1815 return err? FALSE : TRUE;
1816 }
1817
1818
1819 /* Subclass routine for the subkey listview control to allow shortcuts. */
1820 static BOOL CALLBACK
1821 subkey_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1822 {
1823 int virt_key = 0;
1824 winpt_key_t key;
1825
1826 switch (msg) {
1827 case WM_KEYUP:
1828 virt_key = (int)wparam;
1829 key = (winpt_key_t)keyedit_subkey_proc.opaque;
1830 if (!key || !key->key_pair)
1831 break;
1832
1833 switch (virt_key) {
1834 case VK_DELETE:
1835 SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1836 CB_SETCURSEL, CMD_DELKEY, 0);
1837 send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
1838 break;
1839
1840 case VK_INSERT:
1841 SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1842 CB_SETCURSEL, CMD_ADDKEY, 0);
1843 send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
1844 break;
1845 }
1846 }
1847 return CallWindowProc (keyedit_subkey_proc.old, dlg, msg, wparam, lparam);
1848 }
1849
1850
1851 static BOOL CALLBACK
1852 uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1853 {
1854 int virt_key = 0;
1855 winpt_key_t key;
1856
1857 switch (msg) {
1858 case WM_KEYUP:
1859 virt_key = (int)wparam;
1860 key = (winpt_key_t)keyedit_uid_proc.opaque;
1861 if (!key || !key->key_pair)
1862 break;
1863
1864 switch (virt_key) {
1865 case VK_DELETE:
1866 SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1867 CB_SETCURSEL, CMD_DELUID, 0);
1868 send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1869 break;
1870
1871 case VK_INSERT:
1872 SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1873 CB_SETCURSEL, CMD_ADDUID, 0);
1874 send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1875 break;
1876 }
1877 }
1878 return CallWindowProc (keyedit_uid_proc.old, dlg, msg, wparam, lparam);
1879 }
1880
1881
1882 /* Enable the key @k when @enable is 1, disable it otherwise. */
1883 static void
1884 do_editkey_enable_disable (winpt_key_t k, HWND dlg,
1885 listview_ctrl_t lv, int enable)
1886 {
1887 km_enable_disable_key (lv, dlg, 0, enable);
1888 k->update = 1;
1889 }
1890
1891
1892 static void
1893 do_editkey_minimize (winpt_key_t k, HWND dlg)
1894 {
1895 gpgme_error_t err;
1896 GpgKeyEdit *ke;
1897
1898 ke = create_GpgKeyEdit (k->keyid);
1899 err = ke->minimizeKey ();
1900 if (err)
1901 msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
1902 else {
1903 msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
1904 k->update = 1;
1905 }
1906 delete ke;
1907 }
1908
1909
1910 static void
1911 do_editkey_clean (winpt_key_t k, HWND dlg)
1912 {
1913 gpgme_error_t err;
1914 GpgKeyEdit *ke;
1915
1916 ke = create_GpgKeyEdit (k->keyid);
1917 err = ke->cleanKey ();
1918 if (err)
1919 msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
1920 else {
1921 msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
1922 k->update = 1;
1923 }
1924 delete ke;
1925 }
1926
1927
1928 /* Start the dialog to list and display the status of all
1929 signatures for this key. */
1930 static void
1931 do_editkey_check (winpt_key_t k, HWND dlg)
1932 {
1933 if (!k->ctx)
1934 get_pubkey (k->keyid, &k->ctx);
1935 if (!k->uid && k->ctx)
1936 k->uid = k->ctx->uids->uid;
1937 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYSIG_TREE, dlg,
1938 sigtree_dlg_proc, (LPARAM)k);
1939 }
1940
1941
1942 static int
1943 do_editkey_sign_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv, int mode)
1944 {
1945 gpgme_error_t err;
1946 winpt_key_s signer;
1947 GpgKeyEdit *ke;
1948 char *pass = NULL;
1949 char *defkey;
1950 char email[64], name[128], valid[32];
1951 int uid_index;
1952 int cancel = 0;
1953
1954 uid_index = listview_get_curr_pos (lv);
1955 if (uid_index == -1) {
1956 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1957 return FALSE;
1958 }
1959 listview_get_item_text (lv, uid_index, UID_COL_VALID, valid, sizeof (valid)-1);
1960 if (!strcmp (valid, _("Revoked")))
1961 return TRUE;
1962 if (mode == CMD_SIGN) {
1963 cancel = msg_box (dlg, _("Do you really want to make this sig exportable?"),
1964 _("Key Edit"), MB_QUEST_ASK);
1965 if (cancel == IDNO)
1966 return FALSE;
1967 }
1968 listview_get_item_text (lv, uid_index, UID_COL_EMAIL, email, sizeof (email)-1);
1969 listview_get_item_text (lv, uid_index, UID_COL_NAME, name, sizeof (name)-1);
1970 uid_index = do_find_userid (k->keyid, email, name, NULL);
1971
1972 defkey = get_gnupg_default_key ();
1973 memset (&signer, 0, sizeof (signer));
1974 if (winpt_get_seckey (defkey, &signer)) {
1975 log_debug ("do_editkey_sign_userid: no default secret key.\r\n");
1976 free_if_alloc (defkey);
1977 return FALSE;
1978 }
1979 if (signer.is_protected) {
1980 pass = request_key_passphrase (signer.ctx, _("Key Edit"), &cancel);
1981 if (cancel)
1982 return FALSE;
1983 }
1984 ke = create_GpgKeyEdit (k->keyid);
1985 if (signer.is_protected)
1986 ke->setPassphrase (pass);
1987 else
1988 ke->setNoPassphrase (true);
1989 ke->setLocalUser (signer.ctx);
1990 err = ke->signUserid (uid_index,
1991 mode == CMD_SIGN? GPG_EDITKEY_SIGN : GPG_EDITKEY_LSIGN,
1992 0, NULL);
1993 if (!err) {
1994 msg_box (dlg, _("Key successfully signed."), _("Key Edit"), MB_OK);
1995 k->update = 1;
1996 }
1997 else
1998 msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
1999 delete ke;
2000 sfree_if_alloc (pass);
2001 return !err? TRUE : FALSE;
2002 }
2003
2004
2005 static int
2006 lookup_cmd (HWND dlg)
2007 {
2008 char buf[64];
2009 int i;
2010
2011 i = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
2012 if (i == LB_ERR)
2013 return LB_ERR;
2014 GetDlgItemText (dlg, IDC_KEYEDIT_CMD, buf, sizeof (buf)-1);
2015 for (i=0; cmdlist[i].name != NULL; i++) {
2016 if (!strcmp (buf, cmdlist[i].name))
2017 return cmdlist[i].id;
2018 }
2019 return LB_ERR;
2020 }
2021
2022
2023
2024 gpgme_error_t key_get_revokers (winpt_key_t key, int reload,
2025 gpg_desig_rev_t *r_rev);
2026
2027 /* Check if the key supports designated revokers and if
2028 secret keys exist to generate such a revoke cert. */
2029 static bool
2030 check_desig_rev (winpt_key_t key)
2031 {
2032 gpg_desig_rev_t rev, u;
2033 struct winpt_key_s sk;
2034
2035 if (!key->ext->gloflags.has_desig_rev)
2036 return false;
2037 key_get_revokers (key, 0, &rev);
2038 for (u = rev; u; u = u->next) {
2039 memset (&sk, 0, sizeof (sk));
2040 if (!winpt_get_seckey (u->fpr+32, &sk))
2041 return true;
2042 }
2043 return false;
2044 }
2045
2046
2047 /* Use the gpg --desig-revoker command to create a revocation
2048 cert for a key that lists our key as a designated revoker. */
2049 static void
2050 gen_desig_revoke_cert (winpt_key_t key, HWND dlg)
2051 {
2052 const char *warn;
2053 char *inf, *p;
2054 int id;
2055
2056 inf = km_key_get_info (key, 0);
2057 warn = _("Your keys is listed as a designated revoker for the key\n\n"
2058 "%s\n\n"
2059 "Are you sure you want to create a revocation certificate\n"
2060 "which allow to revoke the key listed above?");
2061 p = new char[strlen (inf)+1+strlen (warn)+1];
2062 sprintf (p, warn, inf);
2063 free_if_alloc (inf);
2064
2065 id = msg_box (dlg, p, _("Key Edit"), MB_YESNO|MB_ICONWARNING);
2066 free_if_alloc (p);
2067 if (id == IDNO)
2068 return;
2069
2070 key->internal = 1;
2071 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKE, dlg,
2072 key_revoke_dlg_proc, (LPARAM)key);
2073 }
2074
2075
2076 /* Create tooltip control for the listview header. */
2077 static HWND
2078 create_header_tooltip (HWND dlg)
2079 {
2080 TOOLINFO ti;
2081 HWND tt;
2082
2083 tt = CreateWindow (TOOLTIPS_CLASS, (LPSTR) NULL, TTS_ALWAYSTIP,
2084 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2085 CW_USEDEFAULT,
2086 NULL, (HMENU) NULL, glob_hinst, NULL);
2087 if (!tt)
2088 BUG (NULL);
2089 memset (&ti, 0, sizeof (ti));
2090 ti.cbSize = sizeof(TOOLINFO);
2091 ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;
2092 ti.hwnd = dlg;
2093 ti.uId = (UINT) ListView_GetHeader (GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
2094 ti.hinst = 0;
2095 ti.lpszText = (char*)_("Capabilties: C = Certify, S = Sign, E = Encrypt, A = Authenticate");
2096 SendMessage(tt, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
2097 return tt;
2098 }
2099
2100
2101 /* Dialog box procedure for the edit key dialog. */
2102 BOOL CALLBACK
2103 keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
2104 {
2105 static winpt_key_t k;
2106 static listview_ctrl_t lvsub = NULL, lvuid = NULL;
2107 static HWND tt;
2108 int cmd;
2109 HWND item;
2110
2111 switch (msg) {
2112 case WM_INITDIALOG:
2113 k = (winpt_key_t)lparam;
2114 if (!k)
2115 BUG (NULL);
2116 do_init_cmdlist (dlg, k->key_pair);
2117 lvsub = subkey_list_init (dlg, k);
2118 lvuid = userid_list_init (dlg, k);
2119 item = GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST);
2120 keyedit_subkey_proc.opaque = (void*)k;
2121 keyedit_subkey_proc.dlg = dlg;
2122 keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
2123 keyedit_subkey_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
2124 if (keyedit_subkey_proc.old) {
2125 if (!SetWindowLong (item, GWL_WNDPROC,
2126 (LONG)keyedit_subkey_proc.current)) {
2127 msg_box (dlg, "Could not set subkey window procedure.",
2128 _("Key Edit"), MB_ERR);
2129 BUG (NULL);
2130 }
2131 }
2132 tt = create_header_tooltip (dlg);
2133 item = GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST);
2134 keyedit_uid_proc.opaque = (void*)k;
2135 keyedit_uid_proc.dlg = dlg;
2136 keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
2137 keyedit_uid_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
2138 if (keyedit_uid_proc.old) {
2139 if (!SetWindowLong (item, GWL_WNDPROC,
2140 (LONG)keyedit_uid_proc.current)) {
2141 msg_box (dlg, "Could not set user ID window procedure.",
2142 _("Key Edit"), MB_ERR);
2143 BUG (NULL);
2144 }
2145 }
2146 if (k->ctx->revoked) {
2147 EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
2148 EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
2149 }
2150 SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
2151 SetDlgItemText (dlg, IDCANCEL, _("&Close"));
2152 SetDlgItemText (dlg, IDC_KEYEDIT_HELP, _("&Help"));
2153 SetDlgItemText (dlg, IDC_KEYEDIT_REVOKE, _("&Revoke..."));
2154 SetDlgItemText (dlg, IDOK, _("&OK"));
2155 if (!check_desig_rev (k))
2156 ShowWindow (GetDlgItem (dlg, IDC_KEYEDIT_REVOKE), SW_HIDE);
2157 SetWindowText (dlg, _("Key Edit"));
2158 SetForegroundWindow (dlg);
2159 center_window (dlg, NULL);
2160 return TRUE;
2161
2162 case WM_DESTROY:
2163 if (lvsub) {
2164 listview_release (lvsub);
2165 lvsub = NULL;
2166 }
2167 if (lvuid) {
2168 listview_release (lvuid);
2169 lvuid = NULL;
2170 }
2171 break;
2172
2173 case WM_NOTIFY:
2174 NMHDR *notify;
2175 notify = (NMHDR *)lparam;
2176 if (!notify || notify->idFrom != IDC_KEYEDIT_UIDLIST)
2177 break;
2178 if (notify->code == NM_DBLCLK)
2179 do_editkey_showpref (k, dlg, lvuid);
2180 else if (notify->code == NM_RCLICK && k->key_pair) {
2181 HMENU hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYEDIT));
2182 HMENU popup = GetSubMenu (hm, 0);
2183 POINT p;
2184
2185 GetCursorPos (&p);
2186 TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
2187 DestroyMenu (hm);
2188 DestroyMenu (popup);
2189 }
2190 break;
2191
2192 case WM_COMMAND:
2193 switch (LOWORD (wparam)) {
2194 case IDOK:
2195 cmd = lookup_cmd (dlg);
2196 if (cmd == LB_ERR) {
2197 msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
2198 return FALSE;
2199 }
2200 if (k->is_v3 && is_cmd_openpgp (cmd)) {
2201 msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
2202 _("Key Edit"), MB_ERR);
2203 return FALSE;
2204 }
2205 switch (cmd) {
2206 case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
2207 case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
2208 case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
2209 case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
2210 case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
2211 case CMD_SETPREF:/*do_editkey_setpref (k, dlg, lvuid);*/ break;
2212 case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
2213 case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
2214 case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
2215 case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
2216 case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
2217 case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;
2218 case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;
2219 case CMD_ENABLE: do_editkey_enable_disable (k, dlg, lvsub, 1); break;
2220 case CMD_DISABLE: do_editkey_enable_disable (k, dlg, lvsub, 0); break;
2221 case CMD_CHECK: do_editkey_check (k, dlg); break;
2222 case CMD_TRUST: keyedit_change_ownertrust (k, dlg); break;
2223 case CMD_SIGN:
2224 case CMD_LSIGN: do_editkey_sign_userid (k, dlg,
2225 lvuid, cmd);
2226 break;
2227 case CMD_CLEAN: do_editkey_clean (k, dlg); break;
2228 case CMD_MINIMIZE: do_editkey_minimize (k, dlg); break;
2229 }
2230 break;
2231
2232 case IDCANCEL:
2233 EndDialog (dlg, FALSE);
2234 break;
2235
2236 case IDC_KEYEDIT_HELP:
2237 do_show_help (dlg);
2238 break;
2239
2240 case IDC_KEYEDIT_REVOKE:
2241 gen_desig_revoke_cert (k, dlg);
2242 break;
2243
2244 case ID_KEYEDIT_UID_PRIM:
2245 do_editkey_primary (k, dlg, lvuid);
2246 break;
2247
2248 case ID_KEYEDIT_UID_DEL:
2249 do_editkey_deluid (k, dlg, lvuid);
2250 break;
2251
2252 case ID_KEYEDIT_UID_REV:
2253 do_editkey_revuid (k, dlg, lvuid);
2254 break;
2255 }
2256 break;
2257 }
2258 return FALSE;
2259 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26