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

Contents of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26