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

Contents of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 49431 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

1 /* wptKeyEditDlgs.cpp - GPG key edit dialogs
2 * Copyright (C) 2002-2005 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with WinPT; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <windows.h>
26 #include <oleauto.h>
27 #include <commctrl.h>
28 #include <time.h>
29
30 #include "resource.h"
31
32 #include "wptTypes.h"
33 #include "wptW32API.h"
34 #include "wptVersion.h"
35 #include "wptGPG.h"
36 #include "wptCommonCtl.h"
37 #include "wptContext.h"
38 #include "wptDlgs.h"
39 #include "wptNLS.h"
40 #include "wptUTF8.h"
41 #include "wptErrors.h"
42 #include "wptKeylist.h"
43 #include "wptKeyManager.h"
44 #include "wptRegistry.h"
45 #include "wptKeyEdit.h"
46
47 /* All edit key commands. */
48 enum keyedit_commands {
49 CMD_ADDKEY = 0,
50 CMD_ADDUID,
51 CMD_ADDPHOTO,
52 CMD_ADDREVOKER,
53 /*CMD_FPR,*/
54 CMD_DELUID,
55 CMD_DELKEY,
56 CMD_DELPHOTO,
57 /*CMD_DELSIG,*/
58 CMD_EXPIRE,
59 /*CMD_PREF,*/
60 CMD_SHOWPREF,
61 /*CMD_SETPREF,*/
62 /*CMD_UPDPREF,*/
63 CMD_PASSWD,
64 CMD_PRIMARY,
65 CMD_TRUST,
66 /*CMD_REVSIG,*/
67 CMD_REVUID,
68 CMD_REVKEY,
69 CMD_DISABLE,
70 CMD_ENABLE,
71 /*CMD_SHOWPHOTO,*/
72 };
73
74
75 /* Symbolic ids for the subkey columns. */
76 enum subk_col_t {
77 SUBK_COL_DESC = 0,
78 SUBK_COL_KEYID = 1,
79 SUBK_COL_CREATION = 2,
80 SUBK_COL_EXPIRES = 3,
81 SUBK_COL_STATUS = 4,
82 SUBK_COL_C_FLAG = 5,
83 SUBK_COL_S_FLAG = 6,
84 SUBK_COL_E_FLAG = 7,
85 SUBK_COL_A_FLAG = 8
86 };
87
88 /* Symbolic ids for the userid columns. */
89 enum uid_col_t {
90 UID_COL_VALID = 0,
91 UID_COL_NAME = 1,
92 UID_COL_EMAIL = 2,
93 UID_COL_CREATION = 3
94 };
95
96 struct keyedit_callback_s {
97 const char *keyid;
98 const char *pass;
99 listview_ctrl_t lv;
100 void *opaque;
101 unsigned int finished:1;
102 };
103 typedef struct keyedit_callback_s KEYEDIT_CB;
104
105 struct keygen_callback_s {
106 int bits;
107 int algo;
108 u32 expire;
109 char *fpr;
110 };
111 typedef struct keygen_callback_s KEYGEN_CB;
112
113
114 static subclass_s keyedit_subkey_proc;
115 static subclass_s keyedit_uid_proc;
116
117 int keygen_check_date (SYSTEMTIME *st);
118 void get_userid_preflist (char **r_prefs, int * r_flags);
119 char* get_subkey_fingerprint (const char *keyid);
120
121
122 /* Associate each key with a combo box entry.
123 Skip the key in @k. */
124 static void
125 do_init_keylist (HWND dlg, winpt_key_t k)
126 {
127 gpg_keycache_t pub;
128 gpgme_key_t key;
129 const char * s, * kid;
130 char * u;
131 int i, n;
132
133 pub = keycache_get_ctx (1);
134 if (!pub)
135 BUG (0);
136
137 gpg_keycache_rewind (pub);
138 while( !gpg_keycache_next_key( pub, 0, &key ) ) {
139 s = key->uids->uid;
140 kid = key->subkeys->keyid;
141 if (!s || !strcmp (kid+8, k->keyid+2))
142 continue;
143 u = utf8_to_wincp (s, strlen (s));
144 SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_ADDSTRING,
145 0, (WPARAM)(char *)u);
146 free (u);
147 }
148 gpg_keycache_rewind (pub);
149 n = SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0 );
150 for (i = 0; i < n; i++) {
151 gpg_keycache_next_key (pub, 0, &key);
152 SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
153 (WPARAM)(int)i, (LPARAM)key);
154 }
155 SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
156 }
157
158
159 /* Add a new user-id to the list view @lv. */
160 static void
161 do_add_new_userid (listview_ctrl_t lv,
162 const char * name, const char *email, const char * comment)
163 {
164 char * p;
165 size_t n;
166
167 n = strlen (name) + strlen (email) + 16;
168 if (comment)
169 n += strlen (comment);
170 p = new char[n+1];
171 if (!p)
172 BUG( NULL );
173 if (comment)
174 sprintf (p, "%s (%s)", name, comment);
175 else
176 sprintf (p, "%s", name);
177
178 listview_add_item (lv, "");
179 listview_add_sub_item (lv, 0, 0, _("Ultimate" ));
180 listview_add_sub_item (lv, 0, 1, p);
181 listview_add_sub_item (lv, 0, 2, email && *email? email : "");
182 listview_add_sub_item (lv, 0, 3, get_key_created (time (NULL)));
183 free_if_alloc (p);
184 } /* do_add_new_userid */
185
186
187 static void
188 do_add_new_subkey (listview_ctrl_t lv, KEYGEN_CB *keygen, unsigned int flags)
189 {
190 char info[128], keyid[32];
191 const char * expdate, * s;
192 int n;
193
194 expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
195 _snprintf (info, sizeof info-1, "%d-bit %s",
196 keygen->bits,
197 get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
198 _snprintf (keyid, sizeof keyid-1, "0x%s", keygen->fpr+32);
199 n = listview_count_items (lv, 0);
200 listview_add_item_pos (lv, n);
201 listview_add_sub_item (lv, n, 0, info);
202 listview_add_sub_item (lv, n, 1, keyid);
203 listview_add_sub_item (lv, n, 2, get_key_created (time (NULL)));
204 listview_add_sub_item (lv, n, 3, expdate);
205 if (flags & KM_FLAG_REVOKED) s = _("Revoked");
206 else if (flags & KM_FLAG_EXPIRED) s = _("Expired");
207 else s = _("OK");
208 listview_add_sub_item (lv, n, 4, s);
209 } /* do_add_new_subkey */
210
211
212 /* Try to find the GPG edit key index which belongs to the user ID
213 given by @name. If @r_inf != NULL, the info context will be returned.
214 Return value: index of the user ID or -1 on error. */
215 static int
216 do_find_userid (const char *keyid, const char *name, gpg_uid_info_t *r_inf)
217 {
218 GpgKeyEdit *ke;
219 gpgme_error_t err;
220 gpg_uid_info_t inf, ui;
221 int pos = -1;
222
223 ke = new GpgKeyEdit (keyid);
224 if (!ke)
225 BUG (NULL);
226 err = ke->getUseridInfo (&inf);
227 delete ke;
228 if (err) {
229 log_box (_("user ID"), MB_ERR,
230 _("Could not get key information for: \"%s\":\n%s"),
231 name, gpgme_strerror (err));
232 return -1;
233 }
234
235 for (ui = inf; ui; ui = ui->next) {
236 if (!strcmp (ui->email, name)) {
237 pos = ui->index;
238 break;
239 }
240 }
241 if (r_inf)
242 *r_inf = inf;
243 else
244 gpg_uid_info_release (inf);
245 return pos;
246 }
247
248
249 /* Dialog box procedure to add a photo. */
250 BOOL CALLBACK
251 keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
252 {
253 static winpt_key_t k;
254 GpgKeyEdit *ke;
255 gpgme_error_t ec;
256 const char * s;
257 char pwd[128], file[128];
258 int id;
259
260 switch( msg ) {
261 case WM_INITDIALOG:
262 k = (winpt_key_t)lparam;
263 if (!k)
264 BUG (NULL);
265 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."));
266 SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
267 SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
268 SetForegroundWindow( dlg );
269 break;
270
271 case WM_DESTROY:
272 break;
273
274 case WM_SYSCOMMAND:
275 if( LOWORD (wparam) == SC_CLOSE )
276 EndDialog( dlg, TRUE );
277 break;
278
279 case WM_COMMAND:
280 switch( LOWORD( wparam ) ) {
281
282 case IDC_ADDPHOTO_SELFILE:
283 s = get_fileopen_dlg( dlg, _("Select Image File"), _("JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0"), NULL );
284 if( s && *s )
285 SetDlgItemText( dlg, IDC_ADDPHOTO_FILE, s );
286 break;
287
288 case IDOK:
289 if( !GetDlgItemText( dlg, IDC_ADDPHOTO_FILE, file, sizeof file-1 ) ){
290 msg_box( dlg, _("Please enter a file name."), _("Add Photo"), MB_ERR );
291 return FALSE;
292 }
293 if( get_file_size( file ) == 0 || get_file_size( file ) > 6144 ) {
294 id = msg_box( dlg, _("The JPEG is really large.\n"
295 "Are you sure you want to use it?"),
296 _("Add Photo"), MB_YESNO|MB_INFO );
297 if( id == IDNO )
298 return TRUE;
299 }
300 if( k->is_protected ) {
301 if( !GetDlgItemText( dlg, IDC_ADDPHOTO_PASS, pwd, sizeof pwd-1 ) ) {
302 msg_box( dlg, _("Please enter a passphrase."), _("Add Photo"), MB_ERR );
303 return FALSE;
304 }
305 }
306 ke = new GpgKeyEdit (k->keyid);
307 if (!ke)
308 BUG (NULL);
309
310 if (k->is_protected)
311 ke->setPassphrase (pwd);
312 ec = ke->addPhotoid (file);
313 delete ke;
314 memset (pwd, 0, sizeof pwd);
315 if (ec) {
316 msg_box (dlg, gpgme_strerror (ec), _("Add Photo"), MB_ERR );
317 return FALSE;
318 }
319 else {
320 k->update = 1;
321 msg_box (dlg, _("Photo successfully added."), _("GnuPG Status"), MB_OK);
322 }
323 EndDialog (dlg, TRUE);
324 break;
325
326 case IDCANCEL:
327 EndDialog (dlg, FALSE);
328 break;
329 }
330 break;
331 }
332 return FALSE;
333 }
334
335
336 /* Dialog box procedure to add a designated revoker. */
337 BOOL CALLBACK
338 keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
339 {
340 static winpt_key_t k;
341 static gpgme_key_t seckey;
342 GpgKeyEdit *ke;
343 gpgme_error_t err;
344 char uid[128], pwd[128];
345
346
347 switch( msg ) {
348 case WM_INITDIALOG:
349 k = (winpt_key_t)lparam;
350 if( !k )
351 BUG( NULL );
352 if( get_seckey( k->keyid, &seckey ) )
353 BUG( NULL );
354 if (!k->is_protected)
355 EnableWindow (GetDlgItem (dlg, IDC_ADDREV_PASS), FALSE);
356 do_init_keylist (dlg, k);
357 SetDlgItemText (dlg, IDC_ADDREV_INF, _("Appointing a key as designated revoker cannot be undone."));
358 SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));
359 SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
360 SetForegroundWindow( dlg );
361 break;
362
363 case WM_DESTROY:
364 break;
365
366 case WM_SYSCOMMAND:
367 if( LOWORD (wparam) == SC_CLOSE )
368 EndDialog( dlg, TRUE );
369 break;
370
371 case WM_COMMAND:
372 switch( LOWORD( wparam ) ) {
373 case IDOK:
374 if( !GetDlgItemText( dlg, IDC_ADDREV_KEYLIST, uid, sizeof uid-1 ) ) {
375 msg_box( dlg, _("Please select a user ID."), _("Add Revoker"), MB_ERR );
376 return FALSE;
377 }
378
379 if( k->is_protected ) {
380 if( !GetDlgItemText( dlg, IDC_ADDREV_PASS, pwd, sizeof pwd-1 ) ) {
381 msg_box( dlg, _("Please enter the passphrase."), _("Add Revoker"), MB_ERR );
382 return FALSE;
383 }
384 }
385 ke = new GpgKeyEdit (k->keyid);
386 if (k->is_protected)
387 ke->setPassphrase (pwd);
388 err = ke->addDesignatedRevoker (uid);
389 delete ke;
390 memset (pwd, 0, sizeof pwd);
391 if (err) {
392 msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
393 return TRUE;
394 }
395 else {
396 k->update = 1;
397 msg_box (dlg, _("Revoker successfully addded."), _("GnuPG Status"), MB_OK);
398 }
399 EndDialog( dlg, TRUE );
400 break;
401
402 case IDCANCEL:
403 EndDialog( dlg, FALSE );
404 break;
405 }
406 break;
407 }
408 return FALSE;
409 }
410
411
412 /* Dialog box procedure to add a new user-ID. */
413 BOOL CALLBACK
414 keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
415 {
416 static KEYEDIT_CB *ctx;
417 gpgme_error_t err;
418 GpgKeyEdit *ke;
419 char *utf8_name = NULL;
420 char name[128], email[128], comment[128];
421 int rc;
422
423 switch ( msg ) {
424 case WM_INITDIALOG:
425 ctx = (KEYEDIT_CB *)lparam;
426 if( !ctx )
427 dlg_fatal_error(dlg, "Could not get dialog param!");
428 #ifndef LANG_DE
429 SetWindowText (dlg, _("Add new User ID"));
430 SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name"));
431 SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email"));
432 SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment"));
433 #endif
434 SetForegroundWindow (dlg);
435 return FALSE;
436
437 case WM_SYSCOMMAND:
438 if (LOWORD (wparam) == SC_CLOSE) {
439 EndDialog(dlg, TRUE);
440 }
441 return FALSE;
442
443 case WM_COMMAND:
444 switch ( LOWORD( wparam ) ) {
445 case IDOK:
446 rc = GetDlgItemText( dlg, IDC_ADDUID_NAME, name, sizeof name-1 );
447 if (!rc || rc < 5) {
448 msg_box( dlg, _("Please enter a name (min. 5 chars.)"), _("UserID"), MB_ERR );
449 return FALSE;
450 }
451 if (strchr (name, '@')) {
452 msg_box( dlg, _("Please enter the email address in the email field and not in the name field"), _("UserID"), MB_INFO );
453 return FALSE;
454 }
455
456 if( !GetDlgItemText( dlg, IDC_ADDUID_EMAIL, email, sizeof email -1 ) ) {
457 msg_box( dlg, _("Please enter an email address."), _("UserID"), MB_ERR );
458 return FALSE;
459 }
460 if( !strchr( email, '@' ) || strchr (email, ' ')) {
461 msg_box( dlg, _("Invalid email address."), _("UserID"), MB_ERR );
462 return FALSE;
463 }
464
465 rc = GetDlgItemText( dlg, IDC_ADDUID_COMMENT, comment, sizeof comment -1 );
466
467 /* XXX: something is wrong with the encoding :-( */
468 utf8_name = wincp_to_utf8 (name, strlen (name));
469
470 ke = new GpgKeyEdit (ctx->keyid);
471 if (!ke)
472 BUG (NULL);
473 if (ctx->pass)
474 ke->setPassphrase (ctx->pass);
475 err = ke->addUserid (utf8_name? utf8_name : name,
476 rc > 0? comment : NULL, email);
477 if (err)
478 msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
479 else {
480 msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
481 ctx->finished = 1;
482 }
483 delete ke;
484 free (utf8_name);
485 if (!err && ctx->lv)
486 do_add_new_userid (ctx->lv, name, email, rc?comment : NULL);
487 EndDialog (dlg, TRUE);
488 return TRUE;
489
490 case IDCANCEL:
491 EndDialog (dlg, FALSE);
492 return FALSE;
493 }
494 break;
495 }
496
497 return FALSE;
498 }
499
500
501 static int
502 diff_time (HWND dt, SYSTEMTIME *in_exp)
503 {
504 SYSTEMTIME exp, now;
505 double e=0, n=0;
506
507 if (in_exp)
508 memcpy (&exp, in_exp, sizeof (SYSTEMTIME));
509 else
510 DateTime_GetSystemtime (dt, &exp);
511 GetSystemTime (&now);
512 SystemTimeToVariantTime (&exp, &e);
513 SystemTimeToVariantTime (&now, &n);
514 if (n > e)
515 return 0;
516 return (int)(e-n);
517 }
518
519
520 static void
521 init_keysize_box (HWND dlg, int ctlid)
522 {
523 const char *sizelist[] = {
524 "1024", "1536", "2048", "2560", "3072", "3854", "4096", NULL
525 };
526 int i;
527 for (i=0; sizelist[i] != NULL; i++)
528 SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0, (LPARAM)(char*)sizelist[i]);
529 SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);
530 }
531
532 static int
533 get_keysize_from_box (HWND dlg, int ctlid)
534 {
535 int pos;
536 char buf[32];
537
538 pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
539 if (pos == CB_ERR)
540 return -1;
541 SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
542 return atol (buf);
543 }
544
545
546 BOOL CALLBACK
547 keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
548 {
549 static KEYEDIT_CB *ctx;
550 static KEYGEN_CB *keygen;
551 GpgKeyEdit *ke;
552 gpgme_error_t err;
553 HWND lb;
554 int index, size, valid;
555
556 switch (msg) {
557 case WM_INITDIALOG:
558 ctx = (KEYEDIT_CB *)lparam;
559 if (!ctx)
560 dlg_fatal_error (dlg, "Could not get dialog param!");
561 keygen = (KEYGEN_CB *)ctx->opaque;
562 #ifndef LANG_DE
563 SetWindowText (dlg, _("Add new Subkey"));
564 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));
565 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));
566 SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration"));
567 #endif
568 lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
569 listbox_add_string (lb, "DSA (sign only)");
570 listbox_add_string (lb, "ElGamal (encrypt only)");
571 listbox_add_string (lb, "RSA (sign only)");
572 listbox_add_string (lb, "RSA (encrypt only)");
573 CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
574 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
575 init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
576 SetForegroundWindow( dlg );
577 return FALSE;
578
579 case WM_SYSCOMMAND:
580 if( LOWORD (wparam) == SC_CLOSE ) {
581 EndDialog( dlg, TRUE );
582 }
583 return FALSE;
584
585 case WM_COMMAND:
586 if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
587 if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
588 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
589 else
590 EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
591 }
592 if (HIWORD (wparam) == LBN_SELCHANGE && LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
593 index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
594 if (index == 0)
595 SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL, 0, 0);
596 }
597
598 switch ( LOWORD(wparam) ) {
599 case IDOK:
600 lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
601 switch (listbox_get_cursel (lb)) {
602 case 0: index = 2; break;
603 case 1: index = 4; break;
604 case 2: index = 5; break;
605 case 3: index = 6; break;
606 default:
607 msg_box( dlg, _("Please select one entry."), _("Add Subkey"), MB_ERR );
608 return FALSE;
609 }
610 size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
611 if (index == 2 && size != 1024) {
612 msg_box( dlg,_("DSS uses a fixed keysize of 1024. Size changed."), _("Add Subkey"), MB_INFO );
613 size = 1024;
614 }
615 valid = diff_time (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), NULL);
616
617 keygen->bits = size;
618 switch (index) {
619 case 2: keygen->algo = GPGME_PK_DSA; break;
620 case 4: keygen->algo = GPGME_PK_ELG_E; break;
621 case 5: keygen->algo = GPGME_PK_RSA_S; break;
622 case 6: keygen->algo = GPGME_PK_RSA_E; break;
623 }
624 if (valid > 0)
625 keygen->expire = time (NULL) + valid*24*60*60;
626
627 ke = new GpgKeyEdit (ctx->keyid);
628 if (!ke)
629 BUG (NULL);
630 ke->setCallback (keygen_cb, NULL);
631 if (ctx->pass)
632 ke->setPassphrase (ctx->pass);
633 keygen_cb_dlg_create ();
634
635 err = ke->addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
636 keygen->fpr = get_subkey_fingerprint (ctx->keyid);
637 keygen_cb_dlg_destroy ();
638 keygen_cb (NULL, NULL, 0, 0, 0); /* flush */
639 if (err)
640 msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
641 else {
642 msg_box (dlg, _("Subkey successfully added."), _("GnuPG Status"), MB_OK);
643 if (ctx->lv)
644 do_add_new_subkey (ctx->lv, keygen, /*XXXk->flags*/0);
645 ctx->finished = 1;
646 }
647 delete ke;
648 EndDialog (dlg, TRUE);
649 return TRUE;
650
651 case IDCANCEL:
652 EndDialog( dlg, FALSE );
653 return FALSE;
654 }
655 break;
656 }
657
658 return FALSE;
659 } /* keyedit_addsubkey_dlg_proc */
660
661
662 BOOL
663 keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
664 {
665 KEYEDIT_CB cb;
666 char *pass = NULL;
667 int cancel = 0;
668
669 if (!k->key_pair) {
670 msg_box( dlg, _("There is no secret key available!"), _("Add user ID"), MB_ERR );
671 return FALSE;
672 }
673
674 if (k->is_protected) {
675 pass = request_passphrase( _("Key Edit"), 1, &cancel );
676 if (cancel)
677 return FALSE;
678 }
679
680 memset (&cb, 0, sizeof cb);
681 cb.pass = k->is_protected? pass : NULL;
682 cb.lv = lv;
683 cb.keyid = k->keyid;
684 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
685 dlg, keyedit_adduid_dlg_proc,
686 (LPARAM)&cb, _("Add user ID"),
687 IDS_WINPT_KEYEDIT_ADDUID);
688
689 if (cb.finished)
690 k->update = 1;
691
692 sfree_if_alloc (pass);
693 return TRUE;
694 }
695
696
697 char*
698 get_subkey_fingerprint (const char *keyid)
699 {
700 gpgme_error_t err;
701 gpgme_key_t key, main;
702 gpgme_ctx_t ctx;
703 gpgme_subkey_t last_sk, k, new_sk;
704 int n;
705
706 err = gpgme_new (&ctx);
707 if (err)
708 return NULL;
709 err = gpgme_get_key (ctx, keyid, &key, 0);
710 if (err)
711 return NULL;
712 /* XXX: this is very slow and complicated */
713
714 n = count_subkeys (key);
715 last_sk = get_nth_key (key, n-1);
716 new_sk = (gpgme_subkey_t)calloc (1, sizeof *new_sk);
717 if (!new_sk)
718 BUG (NULL);
719 memcpy (new_sk, last_sk, sizeof *last_sk);
720 new_sk->fpr = strdup (last_sk->fpr);
721 new_sk->keyid = strdup (last_sk->keyid);
722
723 get_pubkey (keyid, &main);
724 for (k=main->subkeys; k->next; k=k->next)
725 ;
726 k->next = new_sk;
727
728 gpgme_key_release (key);
729 return new_sk->fpr;
730 }
731
732
733 BOOL
734 keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
735 {
736 KEYEDIT_CB cb;
737 KEYGEN_CB keygen;
738 char *pass = NULL;
739 int cancel = 0;
740
741 if (!k->key_pair) {
742 msg_box (dlg, _("There is no secret key available!"), _("Add Subkey"), MB_ERR);
743 return FALSE;
744 }
745 if (k->is_protected) {
746 pass = request_passphrase (_("Key Edit"), 1, &cancel);
747 if (cancel)
748 return FALSE;
749 }
750
751 memset (&keygen, 0, sizeof (keygen));
752 memset (&cb, 0, sizeof (cb));
753 cb.keyid = k->keyid;
754 cb.pass = k->is_protected? pass : NULL;
755 cb.opaque = &keygen;
756 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,
757 dlg, keyedit_addsubkey_dlg_proc,
758 (LPARAM)&cb, _("Add new Subkey"),
759 IDS_WINPT_KEYEDIT_ADDSUBKEY);
760 if (cb.finished)
761 k->update = 1;
762
763 sfree_if_alloc (pass);
764 return cb.finished? TRUE: FALSE;
765 }
766
767
768 BOOL
769 keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
770 {
771 GpgKeyEdit *ke;
772 gpgme_error_t err;
773 struct URL_ctx_s *url;
774 char *pass;
775
776 url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
777 if (url->cancel == 1) {
778 delete url;
779 return FALSE;
780 }
781
782 pass = request_passphrase (_("Key Edit"), 1, &url->cancel);
783 if (url->cancel) {
784 delete url;
785 return FALSE;
786 }
787
788 ke = new GpgKeyEdit (k->keyid);
789 if (!ke)
790 BUG (NULL);
791 ke->setPassphrase (pass);
792 err = ke->setPreferredKeyserver (0 /* XXX */, url->url);
793 if (!err)
794 msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);
795
796 sfree_if_alloc (pass);
797 delete ke;
798 delete url;
799 return err == 0? 0 : WPTERR_GENERAL;
800 }
801
802
803 /* Add a photo-ID to the key specified in @k. @dlg is the handle of
804 the calling dialog. */
805 BOOL
806 keyedit_add_photo (winpt_key_t k, HWND dlg)
807 {
808 if (!k->key_pair) {
809 msg_box (dlg, _("There is no secret key available!"), _("Add Photo"), MB_ERR);
810 return FALSE;
811 }
812 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
813 keyedit_addphoto_dlg_proc, (LPARAM)k);
814 return TRUE;
815 }
816
817
818 BOOL
819 keyedit_add_revoker (winpt_key_t k, HWND dlg)
820 {
821 if( !k->key_pair ) {
822 msg_box( dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR );
823 return FALSE;
824 }
825 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
826 keyedit_addrevoker_dlg_proc, (LPARAM)k);
827 return TRUE;
828 } /* keyedit_add_revoker */
829
830
831 static int
832 is_idea_protect_algo (const char * keyid)
833 {
834 winpt_key_s k;
835 const unsigned char *sym_prefs;
836 size_t n;
837
838 memset (&k, 0, sizeof (k));
839 if (winpt_get_pubkey (keyid, &k))
840 BUG (NULL);
841 sym_prefs = k.ext->sym_prefs;
842 if (!sym_prefs)
843 return 1; /* assume that only v3 keys have no symmetric cipher preferences
844 and thus IDEA is explicit. */
845 for (n = 0; sym_prefs[n]; n++)
846 ;
847 if ((n == 0 || n == 1) && *sym_prefs == 0x01)
848 return 1;
849 return 0;
850 } /* is_idea_protect_algo */
851
852
853 BOOL
854 keyedit_change_passwd( winpt_key_t k, HWND dlg )
855 {
856 GpgKeyEdit *ke;
857 gpgme_error_t ec;
858 char *old_pass = NULL, *new_pass = NULL;
859 int cancel = 0;
860
861 if( !k->key_pair ) {
862 msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );
863 return FALSE;
864 }
865
866 if( !idea_available && is_idea_protect_algo( k->keyid ) ) {
867 msg_box( dlg, _("Cannot change passphrase because the key\n"
868 "is protected with the IDEA encryption algorithm."),
869 _("Key Edit"), MB_ERR );
870 return FALSE;
871 }
872
873 if( k->is_protected ) {
874 old_pass = request_passphrase( _("Current (old) Passphrase"), 1, &cancel );
875 if( cancel )
876 return FALSE;
877 }
878 new_pass = request_passphrase( _("New Passphrase" ), 1, &cancel );
879 if( cancel ) {
880 free_if_alloc( old_pass );
881 return FALSE;
882 }
883
884 if( is_8bit_string( new_pass ) ) {
885 msg_box( dlg, _("The passphrase contains 8-bit characters.\n"
886 "It is not suggested to use charset specific characters."),
887 _("Key Edit"), MB_ERR );
888 free_if_alloc( old_pass );
889 free_if_alloc( new_pass );
890 return FALSE;
891 }
892
893 ke = new GpgKeyEdit (k->keyid);
894 if (!ke)
895 BUG (NULL);
896
897 ke->setPassphrase (k->is_protected? old_pass : NULL);
898 ec = ke->changePassphrase (new_pass, 0);
899 if( ec )
900 msg_box (dlg, gpgme_strerror (ec), _("Change Passwd"), MB_ERR);
901 else
902 msg_box (dlg, _("Passphrase successfully changed."), _("GnuPG status"), MB_OK);
903 sfree_if_alloc (old_pass);
904 sfree_if_alloc (new_pass);
905 delete ke;
906 return TRUE;
907 }
908
909
910 listview_ctrl_t
911 subkey_list_init( HWND dlg, winpt_key_t k )
912 {
913 LV_ITEM lvi;
914 gpgme_key_t key;
915 gpgme_subkey_t sub;
916 struct listview_column_s cols[] = {
917 {0, 80, (char *)_("Description")},
918 {1, 78, (char *)_("Key ID")},
919 {2, 66, (char *)_("Creation")},
920 {3, 66, (char *)_("Expires")},
921 {4, 64, (char *)_("Status")},
922 {5, 16, "C"/*ertify*/},
923 {6, 16, "S"/*ign*/},
924 {7, 16, "E"/*ncrypt*/},
925 {8, 16, "A"/*uth*/},
926 {0, 0, 0}
927 };
928 listview_ctrl_t lv;
929 char buf[256], tmp[128];
930 const char *t;
931 int nkeys = 0, rc = 0, i, bits;
932
933 if( get_pubkey( k->keyid, &key ) ) {
934 msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
935 return NULL;
936 }
937 nkeys = count_subkeys (key);
938 if( !nkeys ) {
939 msg_box( dlg, _("No subkey(s) found."), _("Key Edit"), MB_ERR );
940 return NULL;
941 }
942
943 rc = listview_new( &lv );
944 if( rc )
945 BUG( dlg );
946
947 lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );
948 for( i = 0; cols[i].fieldname != NULL; i++ )
949 listview_add_column( lv, &cols[i] );
950
951 for( i = 0; i < nkeys; i++ ) {
952 listview_add_item( lv, "" );
953 listview_add_sub_item( lv, 0, 1, "" );
954 memset( &lvi, 0, sizeof lvi );
955 lvi.mask = LVIF_PARAM;
956 lvi.lParam = (LPARAM )key;
957 if( ListView_SetItem( lv->ctrl, &lvi ) == FALSE )
958 return NULL;
959 }
960
961 listview_set_ext_style( lv );
962 for( i = 0, sub = key->subkeys; i < nkeys; i++, sub = sub->next ) {
963 memset( buf, 0, sizeof buf );
964
965 bits = sub->length;
966 _snprintf( tmp, sizeof tmp-1, "%d-bit ", bits );
967 strcat( buf, tmp );
968
969 _snprintf( tmp, sizeof tmp-1, "%s", get_key_pubalgo (sub->pubkey_algo));
970 strcat( buf, tmp );
971
972 listview_add_sub_item( lv, i, 0, buf );
973 t = sub->keyid;
974 if( !t )
975 t = "DEADBEEFDEADBEEF";
976 _snprintf( tmp, sizeof tmp-1, "0x%s", t+8 );
977 listview_add_sub_item( lv, i, 1, tmp );
978
979 t = get_key_created (sub->timestamp);
980 if( !t )
981 t = "????-??-??";
982 listview_add_sub_item( lv, i, 2, t );
983
984 if( sub->expires ) {
985 t = get_key_created (sub->expires);
986 listview_add_sub_item( lv, i, 3, t );
987 }
988 else
989 listview_add_sub_item( lv, i, 3, _("Never") );
990
991 if( sub->expired )
992 t = _("Expired");
993 else if( sub->revoked )
994 t = _("Revoked");
995 else
996 t = _("OK");
997 listview_add_sub_item( lv, i, 4, t );
998
999 if (sub->can_certify) t = "*"; else t = "";
1000 listview_add_sub_item (lv, i, 5, t);
1001 if (sub->can_sign) t = "*"; else t = "";
1002 listview_add_sub_item( lv, i, 6, t );
1003 if (sub->can_encrypt) t = "*"; else t = "";
1004 listview_add_sub_item( lv, i, 7, t );
1005 if (sub->can_authenticate) t = "*"; else t = "";
1006 listview_add_sub_item (lv, i, 8, t);
1007 }
1008 return lv;
1009 } /* subkey_list_init */
1010
1011
1012 static listview_ctrl_t
1013 userid_list_init (HWND dlg, winpt_key_t k)
1014 {
1015 listview_ctrl_t lv = NULL;
1016 gpgme_key_t key;
1017 gpgme_key_sig_t ks;
1018 gpgme_user_id_t u;
1019 int nuids = 0, rc, j, u_attr;
1020 struct listview_column_s cols[] = {
1021 {0, 72, (char *)_("Validity")},
1022 {1, 150, (char *)_("Name")},
1023 {2, 110, (char *)_("Email")},
1024 {3, 76, (char *)_("Creation")},
1025 {0, 0, 0}
1026 };
1027 const char *attr;
1028
1029 if (get_pubkey( k->keyid, &key)) {
1030 msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
1031 return NULL;
1032 }
1033
1034 nuids = count_userids (key);
1035 if (!nuids) {
1036 msg_box (dlg, _("No user ID(s) found."), _("Key Edit"), MB_ERR);
1037 return NULL;
1038 }
1039
1040 rc = listview_new (&lv);
1041 if( rc )
1042 BUG( dlg );
1043 lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );
1044 for( j = 0; cols[j].fieldname != NULL; j++ )
1045 listview_add_column( lv, &cols[j] );
1046
1047 for( j = 0; j < nuids; j++ ) {
1048 listview_add_item( lv, " " );
1049 listview_add_sub_item( lv, 0, 1, " " );
1050 }
1051
1052 listview_set_ext_style (lv);
1053 for (j = 0, u=key->uids; j < nuids; u=u->next, j++) {
1054 if (u->revoked)
1055 attr = _("Revoked");
1056 else {
1057 u_attr = (int)u->validity;
1058 attr = get_key_trust2 (NULL, u_attr, 0, 0);
1059 }
1060 listview_add_sub_item( lv, j, 0, (char *)attr );
1061
1062 /* XXX: add comment if available */
1063 attr = u->name;
1064 if (attr) {
1065 char * uid = utf8_to_wincp (attr, strlen (attr));
1066 if (uid) {
1067 listview_add_sub_item( lv, j, 1, uid );
1068 free( uid );
1069 }
1070 }
1071 else
1072 listview_add_sub_item( lv, j, 1, _("Invalid user ID") );
1073 attr = u->email;
1074 if (attr)
1075 listview_add_sub_item (lv, j, 2, attr);
1076
1077 ks = get_selfsig (u, k->keyid+2, 1);
1078 if (ks)
1079 listview_add_sub_item (lv, j, 3, get_key_created (ks->timestamp));
1080 }
1081 if( !k->key_pair ) {
1082 CheckDlgButton( dlg, IDC_KEYUID_ADD, BST_INDETERMINATE );
1083 CheckDlgButton( dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE );
1084 }
1085 return lv;
1086 } /* userid_list_init */
1087
1088
1089 static void
1090 do_init_cmdlist( HWND dlg )
1091 {
1092 const char *cmdlist[] = {
1093 "ADDKEY",
1094 "ADDUID",
1095 "ADDPHOTO",
1096 "ADDREVOKER",
1097 /*"FPR",*/
1098 "DELUID",
1099 "DELKEY",
1100 "DELPHOTO",
1101 /*"DELSIG",*/
1102 "EXPIRE",
1103 /*"PREF",*/
1104 "SHOWPREF",
1105 /*"SETPREF",*/
1106 "PASSWD",
1107 "PRIMARY",
1108 "TRUST",
1109 /*"REVSIG",*/
1110 "REVUID",
1111 "REVKEY",
1112 "DISABLE",
1113 "ENABLE",
1114 "SHOWPHOTO",
1115 NULL
1116 };
1117 const char * s;
1118 int i = 0;
1119
1120 for( i = 0; (s=cmdlist[i]); i++ ) {
1121 SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1122 (LPARAM)(char *)s );
1123 }
1124 SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0 );
1125 } /* do_init_cmdlist */
1126
1127
1128 static int
1129 is_cmd_openpgp( int cmdid )
1130 {
1131 switch( cmdid ) {
1132 case CMD_ADDKEY:
1133 case CMD_ADDPHOTO:
1134 case CMD_ADDREVOKER:
1135 case CMD_DELPHOTO:
1136 /*case CMD_SHOWPHOTO:*/
1137 /*case CMD_SETPREF:*/
1138 return 1;
1139 }
1140 return 0;
1141 } /* is_cmd_openpgp */
1142
1143
1144 static void
1145 do_show_help( HWND dlg )
1146 {
1147 char helptext[2048];
1148
1149 _snprintf( helptext, sizeof helptext-1,
1150 _(/*"FPR \t\tshow fingerprint\r\n"*/
1151 "ADDUID \t\tadd a user ID\r\n"
1152 "ADDPHOTO \t\tadd a photo ID\r\n"
1153 "DELUID \t\tdelete a user ID\r\n"
1154 "ADDKEY \t\tadd a secondard key\r\n"
1155 "DELKEY \t\tdelete a secondary key\r\n"
1156 "ADDREVOKER\t\tadd a revocation key\r\n"
1157 /*"DELSIG \t\tdelete signatures\r\n"*/
1158 "EXPIRE \t\tchange the expire date\r\n"
1159 /*"PREF \t\tlist preferences (expert)\r\n"
1160 "SHOWPREF \t\tlist preferences (verbose)\r\n"
1161 "SETPREF \t\tset preference list\r\n"*/
1162 "UPDPREF \t\tupdated preferences\r\n"
1163 "PASSWD \t\tchange the passphrase\r\n"
1164 "PRIMARY \t\tflag user ID as primary\r\n"
1165 "TRUST \t\tchange the ownertrust\r\n"
1166 /*"REVSIG \t\trevoke signatures\r\n"*/
1167 "REVUID \t\trevoke a user ID\r\n"
1168 "REVKEY \t\trevoke a secondary key\r\n"
1169 "DISABLE \t\tdisable a key\r\n"
1170 "ENABLE \t\tenable a key\r\n"
1171 /*"SHOWPHOTO \t\tshow photo ID\r\n"*/) );
1172 msg_box( dlg, helptext, _("Key Edit Help"), MB_OK );
1173 } /* do_show_help */
1174
1175
1176 static int
1177 do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1178 {
1179 gpgme_error_t err;
1180 GpgKeyEdit *ke;
1181 int j, id;
1182 char tmp[64];
1183
1184 if (!k->key_pair)
1185 return FALSE; /* XXX: shall we allow to modify non-secret keys?? */
1186
1187 if( listview_count_items( lv, 0 ) == 1 ) {
1188 msg_box( dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
1189 return FALSE;
1190 }
1191 if( (j = listview_get_curr_pos( lv )) == -1 ) {
1192 msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1193 return FALSE;
1194 }
1195 if( j == 0 ) {
1196 msg_box( dlg, _("Primary subkey can not be deleted!"), _("Key Edit"), MB_ERR );
1197 return FALSE;
1198 }
1199
1200 listview_get_item_text( lv, j, 0, tmp, sizeof tmp -1 );
1201 id = log_box( _("Key Edit"), MB_YESNO|MB_ICONWARNING,
1202 _("\"Subkey %s.\"\n\n"
1203 "Anything encrypted to the selected subkey will no longer\n"
1204 "be able to be decrypted.\n\n"
1205 "Do you really want to delete this subkey?"), tmp );
1206 if( id == IDNO )
1207 return FALSE;
1208
1209 ke = new GpgKeyEdit (k->keyid);
1210 if (!ke)
1211 BUG (NULL);
1212 err = ke->delKey (j);
1213 if (err)
1214 msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
1215 else {
1216 listview_del_item (lv, j);
1217 k->update = 1;
1218 status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));
1219 }
1220 delete ke;
1221 return err? FALSE : TRUE;
1222 } /* do_editkey_delkey */
1223
1224
1225 /* Set the expiration date for the selected key in list view @lv.
1226 Return value: TRUE on success. */
1227 static int
1228 do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1229 {
1230 gpgme_error_t err;
1231 GpgKeyEdit *ke;
1232 date_s udd = {0};
1233 char buf[256], * pass = NULL;
1234 int j, cancel = 0;
1235
1236 if (!k->key_pair) {
1237 msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1238 return FALSE;
1239 }
1240 if ((j = listview_get_curr_pos (lv)) == -1) {
1241 msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1242 return FALSE;
1243 }
1244
1245 /* If a key already expired, it is possible the user wants to
1246 set a new expiration date.. */
1247 listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof buf -1);
1248 if (!strcmp (buf, _("Expired"))) {
1249 cancel = msg_box (dlg, _("Key already expired.\n\n"
1250 "Do you want to change the expiration date?"),
1251 _("Key Edit"), MB_QUEST_ASK);
1252 if (cancel == IDNO)
1253 return FALSE;
1254 cancel = 0;
1255 }
1256
1257 memset (&udd, 0, sizeof udd);
1258 udd.text = _("Key Expiration Date");
1259 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
1260 date_dlg_proc, (LPARAM)&udd,
1261 _("Key Expiration Date"), IDS_WINPT_DATE);
1262 if (udd.cancel == 1)
1263 return FALSE;
1264 if (!keygen_check_date (&udd.st)) {
1265 msg_box (dlg, _("The date you have chosen lies in the past."),
1266 _("Key Edit"), MB_ERR);
1267 return FALSE;
1268 }
1269 if( k->is_protected ) {
1270 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1271 if (cancel)
1272 return FALSE;
1273 }
1274
1275 ke = new GpgKeyEdit (k->keyid);
1276 if (!ke)
1277 BUG (NULL);
1278 if (k->is_protected)
1279 ke->setPassphrase (pass);
1280 err = ke->setKeyExpireDate (j, diff_time (NULL, &udd.st), true);
1281 if (err)
1282 msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
1283 else {
1284 _snprintf (buf, sizeof buf - 1, "%04d-%02d-%02d",
1285 udd.st.wYear, udd.st.wMonth, udd.st.wDay);
1286 listview_add_sub_item (lv, j, SUBK_COL_EXPIRES, buf);
1287 k->update = 1;
1288 msg_box (dlg, _("Subkey expire date successfully set."),
1289 _("GnuPG status"), MB_OK);
1290 }
1291 sfree_if_alloc (pass);
1292 delete ke;
1293 return TRUE;
1294 }
1295
1296
1297 /* Revoke the selected key in the list view @lv. @k contains
1298 control information about the global key.
1299 Return value: TRUE on success. */
1300 static int
1301 do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1302 {
1303 gpgme_error_t err;
1304 GpgKeyEdit *ke;
1305 char buf[256];
1306 char *pass = NULL;
1307 int j, cancel = 0;
1308
1309 if (!k->key_pair) {
1310 msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1311 return FALSE;
1312 }
1313
1314 if ((j = listview_get_curr_pos (lv)) == -1) {
1315 msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1316 return FALSE;
1317 }
1318 else if (listview_count_items (lv, 0) == 1) {
1319 msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
1320 "whole key, please use the Key Manager command directly.\n\n"
1321 "This command is only available to revoke single subkeys"),
1322 _("Key Edit"), MB_INFO );
1323 return FALSE;
1324 }
1325
1326 listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1327 if (!strcmp (buf, _("Revoked"))) {
1328 msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1329 return FALSE;
1330 }
1331
1332 if (k->is_protected) {
1333 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1334 if (cancel)
1335 return FALSE;
1336 }
1337
1338 ke = new GpgKeyEdit (k->keyid);
1339 if (!ke)
1340 BUG (NULL);
1341 if (k->is_protected)
1342 ke->setPassphrase (pass);
1343 err = ke->revokeSubkey (j, 0, NULL);
1344 if (err)
1345 msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
1346 else {
1347 listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
1348 k->update = 1;
1349 msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1350 }
1351 sfree_if_alloc (pass);
1352 delete ke;
1353 return TRUE;
1354 }
1355
1356
1357 /* Revoked the selected userid in list view @lv.
1358 Return value: TRUE on success. */
1359 int
1360 do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1361 {
1362 gpgme_error_t err;
1363 GpgKeyEdit *ke;
1364 char buf[256], t[512];
1365 char *pass=NULL;
1366 int cancel = 0, id = 0, j;
1367
1368 if (!k->key_pair) {
1369 msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );
1370 return FALSE;
1371 }
1372
1373 if( listview_count_items( lv, 0 ) == 1 ) {
1374 msg_box( dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR );
1375 return FALSE;
1376 }
1377
1378 if( (j = listview_get_curr_pos( lv )) == -1 ) {
1379 msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1380 return FALSE;
1381 }
1382
1383 listview_get_item_text( lv, j, 0, buf, sizeof buf - 1 );
1384 if( strstr( buf, _("Revoked") ) ) {
1385 msg_box( dlg, _("This user ID has been already revoked."), _("Key Edit"), MB_INFO );
1386 return FALSE;
1387 }
1388
1389 listview_get_item_text (lv, j, 1, buf, sizeof buf -1);
1390 _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"
1391 "Do you really want to revoke this user ID?"), buf );
1392 if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )
1393 return FALSE;
1394 if( k->is_protected ) {
1395 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1396 if (cancel)
1397 return FALSE;
1398 }
1399 listview_get_item_text (lv, j, 2, buf, sizeof (buf)-1);
1400 id = do_find_userid (k->keyid, buf, NULL);
1401 if (id == -1)
1402 BUG (NULL);
1403
1404 ke = new GpgKeyEdit (k->keyid);
1405 if (!ke)
1406 BUG (NULL);
1407 if (k->is_protected)
1408 ke->setPassphrase (pass);
1409 err = ke->revokeUserid (id);
1410 if (err)
1411 msg_box (dlg, gpgme_strerror (err), _("Revoke Signature"), MB_ERR);
1412 else {
1413 listview_add_sub_item (lv, j, 0, _("Revoked"));
1414 k->update = 1;
1415 status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1416 }
1417 sfree_if_alloc (pass);
1418 delete ke;
1419 return err? FALSE : TRUE;
1420 }
1421
1422
1423 static int
1424 do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1425 {
1426 gpgme_error_t rc;
1427 GpgKeyEdit *ke;
1428 char buf[256], * pass = NULL, * prefs;
1429 int j, id, cancel=0, flags=0;
1430
1431 if ((j = listview_get_curr_pos (lv)) == -1) {
1432 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1433 return FALSE;
1434 }
1435 listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1436 id = do_find_userid (k->keyid, buf, NULL);
1437 if (id == -1)
1438 BUG (dlg);
1439 if (k->is_protected) {
1440 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1441 if (cancel)
1442 return FALSE;
1443 }
1444
1445 ke = new GpgKeyEdit (k->keyid);
1446 if (!ke)
1447 BUG (NULL);
1448 if (k->is_protected)
1449 ke->setPassphrase (pass);
1450
1451 get_userid_preflist (&prefs, &flags);
1452
1453 rc = ke->setUseridPreferences (id, prefs);
1454 /* XXX */
1455
1456 sfree_if_alloc (pass);
1457 free_if_alloc (prefs);
1458 delete ke;
1459 return 0;
1460 }
1461
1462
1463 static int
1464 do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1465 {
1466 gpgme_error_t err;
1467 GpgKeyEdit *ke;
1468 int j, id, cancel=0;
1469 char buf[256], * pass = NULL;
1470
1471 if (listview_count_items (lv, 0) == 1)
1472 return TRUE;
1473 if ((j = listview_get_curr_pos (lv)) == -1) {
1474 msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1475 return FALSE;
1476 }
1477 listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1478 id = do_find_userid (k->keyid, buf, NULL);
1479 if (id == -1)
1480 BUG (dlg);
1481 if (k->is_protected) {
1482 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1483 if( cancel )
1484 return FALSE;
1485 }
1486
1487 ke = new GpgKeyEdit (k->keyid);
1488 if (k->is_protected)
1489 ke->setPassphrase (pass);
1490 err = ke->setPrimaryUserid (id);
1491 if (err)
1492 msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
1493 else {
1494 k->update = 1;
1495 status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
1496 }
1497
1498 sfree_if_alloc (pass);
1499 delete ke;
1500 return err? FALSE : TRUE;
1501 }
1502
1503
1504 static int
1505 parse_preflist (HWND dlg, const char *list)
1506 {
1507 char *p, buf[128] = {0}, *pbuf = buf;
1508 const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};
1509 const char *hash[11] = {0, "MD5", "SHA1", "RMD160", 0, 0, 0, 0, "SHA256", "SHA384", "SHA512"};
1510 const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};
1511 int n=0;
1512
1513 strncpy (buf, list, 127);
1514 p = strtok (pbuf, " ");
1515 while (p != NULL) {
1516 int algid = atol (p+1);
1517 n++;
1518 switch (*p) {
1519 case 'S':
1520 SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0, (LPARAM)(const char*)ciphers[algid % 11]);
1521 break;
1522
1523 case 'H':
1524 SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 10]);
1525 break;
1526
1527 case 'Z':
1528 SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0, (LPARAM)(const char*)compress[algid % 4]);
1529 break;
1530
1531 default:
1532 n--;
1533 }
1534 p = strtok (NULL, " ");
1535 }
1536 return n;
1537 }
1538
1539
1540 /* Dialog box procedure to show the key preferences. */
1541 BOOL CALLBACK
1542 showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1543 {
1544 static keyedit_callback_s *cb = NULL;
1545 gpg_uid_info_t inf=NULL;
1546 char buf[128];
1547 int pos;
1548
1549 switch (msg) {
1550 case WM_INITDIALOG:
1551 cb = (keyedit_callback_s *)lparam;
1552 if (cb == NULL)
1553 BUG (dlg);
1554 listview_get_item_text (cb->lv, listview_get_curr_pos (cb->lv), 2, buf, DIM (buf)-1);
1555 SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1556 pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);
1557 if (inf) {
1558 const char *prefs = inf->prefs;
1559 if (prefs && *prefs) {
1560 if (parse_preflist (dlg, prefs) <= 0)
1561 pos = -1;
1562 }
1563 else
1564 pos = -1;
1565 gpg_uid_info_release (inf);
1566 if (pos == -1) {
1567 msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1568 EndDialog (dlg, TRUE);
1569 }
1570 if (inf->flags.mdc)
1571 CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1572 }
1573 SetWindowText (dlg, _("Key Preferences"));
1574 SetForegroundWindow (dlg);
1575 break;
1576
1577 case WM_COMMAND:
1578 switch (LOWORD (wparam)) {
1579 case IDOK:
1580 EndDialog (dlg, TRUE);
1581 break;
1582 }
1583 break;
1584 }
1585 return FALSE;
1586 }
1587
1588
1589 static int
1590 do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1591 {
1592 struct keyedit_callback_s cb;
1593
1594 if (k->is_v3)
1595 return TRUE;
1596
1597 if (listview_get_curr_pos (lv) == -1) {
1598 msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1599 return FALSE;
1600 }
1601
1602 memset (&cb, 0, sizeof (cb));
1603 cb.lv = lv;
1604 cb.opaque = k;
1605 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1606 showpref_dlg_proc, (LPARAM)&cb);
1607 return TRUE;
1608 }
1609
1610
1611 static int
1612 do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1613 {
1614 gpgme_error_t err;
1615 GpgKeyEdit *ke;
1616 char buf[256], t[512];
1617 int j, id = 0;
1618
1619 if (!k->key_pair)
1620 return FALSE; /* XXX: see do_editkey_delsubkey */
1621
1622 if( listview_count_items( lv, 0 ) == 1 ) {
1623 msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );
1624 return FALSE;
1625 }
1626 if( (j = listview_get_curr_pos( lv )) == -1 ) {
1627 msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1628 return FALSE;
1629 }
1630
1631 /* XXX: add a hint that also all signatures will be deleted? */
1632 listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );
1633 _snprintf( t, DIM (t)-1, _("user ID \"%s\".\n\n"
1634 "Do you really want to delete this user ID?"),
1635 buf);
1636 if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )
1637 return FALSE;
1638
1639 listview_get_item_text (lv, j, 2, buf, DIM (buf)-1);
1640 id = do_find_userid (k->keyid, buf, NULL);
1641 if (id == -1)
1642 BUG (dlg);
1643
1644 ke = new GpgKeyEdit (k->keyid);
1645 if (!ke)
1646 BUG (NULL);
1647
1648 err = ke->delUserid (id);
1649 if( err )
1650 msg_box( dlg, gpgme_strerror (err), _("Delete user ID"), MB_ERR );
1651 else {
1652 listview_del_item( lv, j );
1653 k->update = 1;
1654 status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );
1655 }
1656 delete ke;
1657 return err? FALSE : TRUE;
1658 } /* do_editkey_deluid */
1659
1660
1661
1662 static BOOL CALLBACK
1663 subkey_subclass_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )
1664 {
1665 switch( msg ) {
1666 case WM_KEYUP:
1667 int virt_key = (int)wparam;
1668 switch( virt_key ) {
1669 case VK_DELETE:
1670 SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1671 CB_SETCURSEL, CMD_DELKEY, 0 );
1672 send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1673 break;
1674
1675 case VK_INSERT:
1676 SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1677 CB_SETCURSEL, CMD_ADDKEY, 0 );
1678 send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1679 break;
1680 }
1681 }
1682 return CallWindowProc( keyedit_subkey_proc.old, dlg, msg, wparam, lparam );
1683 } /* subkey_subclass_proc */
1684
1685
1686 static BOOL CALLBACK
1687 uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1688 {
1689 switch( msg ) {
1690 case WM_KEYUP:
1691 int virt_key = (int)wparam;
1692 switch (virt_key) {
1693 case VK_DELETE:
1694 SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1695 CB_SETCURSEL, CMD_DELUID, 0);
1696 send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1697 break;
1698
1699 case VK_INSERT:
1700 SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1701 CB_SETCURSEL, CMD_ADDUID, 0);
1702 send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1703 break;
1704 }
1705 }
1706 return CallWindowProc( keyedit_uid_proc.old, dlg, msg, wparam, lparam );
1707 } /* uid_subclass_proc */
1708
1709
1710 BOOL CALLBACK
1711 keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1712 {
1713 static winpt_key_t k;
1714 static listview_ctrl_t lvsub = NULL, lvuid = NULL;
1715 int cmd, idxsub = 0;
1716 HWND item;
1717
1718 switch( msg ) {
1719 case WM_INITDIALOG:
1720 k = (winpt_key_t)lparam;
1721 if (!k)
1722 BUG (NULL);
1723 do_init_cmdlist (dlg);
1724 lvsub = subkey_list_init (dlg, k);
1725 if( !lvsub )
1726 BUG( NULL );
1727 lvuid = userid_list_init (dlg, k);
1728 if( !lvuid )
1729 BUG( NULL );
1730 item = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );
1731 keyedit_subkey_proc.dlg = dlg;
1732 keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
1733 keyedit_subkey_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1734 if( keyedit_subkey_proc.old ) {
1735 if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_subkey_proc.current ) ) {
1736 msg_box( dlg, _("Could not set subkey window procedure."), _("Key Edit"), MB_ERR );
1737 BUG( NULL );
1738 }
1739 }
1740 item = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );
1741 keyedit_uid_proc.dlg = dlg;
1742 keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
1743 keyedit_uid_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1744 if( keyedit_uid_proc.old ) {
1745 if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_uid_proc.current ) ) {
1746 msg_box( dlg, _("Could not set user ID window procedure."), _("Key Edit"), MB_ERR );
1747 BUG( NULL );
1748 }
1749 }
1750 if (!k->key_pair) {
1751 EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
1752 EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
1753 }
1754 SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
1755 SetForegroundWindow( dlg );
1756 center_window( dlg, NULL );
1757 return TRUE;
1758
1759 case WM_DESTROY:
1760 if( lvsub ) {
1761 listview_release( lvsub );
1762 lvsub = NULL;
1763 }
1764 if( lvuid ) {
1765 listview_release( lvuid );
1766 lvuid = NULL;
1767 }
1768 break;
1769
1770 case WM_NOTIFY:
1771 NMHDR * notify;
1772 notify = (NMHDR *)lparam;
1773 if (notify && notify->code == NM_DBLCLK &&
1774 notify->idFrom == IDC_KEYEDIT_UIDLIST)
1775 do_editkey_showpref (k, dlg, lvuid);
1776 break;
1777
1778 case WM_COMMAND:
1779 switch( LOWORD( wparam ) ) {
1780 case IDOK:
1781 cmd = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
1782 if (cmd == LB_ERR) {
1783 msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
1784 return FALSE;
1785 }
1786 idxsub = listview_get_curr_pos (lvsub);
1787 if (k->is_v3 && is_cmd_openpgp (cmd)) {
1788 msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
1789 _("Key Edit"), MB_ERR);
1790 return FALSE;
1791 }
1792 switch (cmd) {
1793 case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
1794 case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
1795 case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
1796 case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
1797 case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
1798 /*case CMD_SETPREF:do_editkey_setpref( k, dlg, lvuid ); break;*/
1799 case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
1800 case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
1801 case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
1802 case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
1803 case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
1804 case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;
1805 case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;
1806 case CMD_ENABLE: km_enable_disable_key( lvsub, dlg, idxsub, 1 ); break;
1807 case CMD_DISABLE: km_enable_disable_key( lvsub, dlg, idxsub, 0 ); break;
1808 }
1809 break;
1810
1811 case IDCANCEL:
1812 EndDialog (dlg, FALSE);
1813 break;
1814
1815 case IDC_KEYEDIT_HELP:
1816 do_show_help (dlg);
1817 break;
1818 }
1819 break;
1820 }
1821 return FALSE;
1822 } /* keyedit_main_dlg_proc */

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26