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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 241 - (show annotations)
Thu Jun 29 11:15:55 2006 UTC (18 years, 8 months ago) by twoaday
File size: 27612 byte(s)


1 /* wptKeyManager.cpp - Handy functions for the Key Manager dialog
2 * Copyright (C) 2001-2006 Timo Schulz
3 * Copyright (C) 2005 g10 Code GmbH
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <commctrl.h>
28 #include <assert.h>
29 #include <stdio.h>
30
31 #include "gpgme.h"
32 #include "resource.h"
33 #include "wptTypes.h"
34 #include "wptW32API.h"
35 #include "wptVersion.h"
36 #include "wptCommonCtl.h"
37 #include "wptNLS.h"
38 #include "wptErrors.h"
39 #include "wptContext.h"
40 #include "wptGPG.h"
41 #include "wptKeylist.h"
42 #include "wptFileManager.h"
43 #include "wptDlgs.h"
44 #include "wptKeyserver.h"
45 #include "wptKeyManager.h"
46 #include "wptKeylist.h"
47 #include "wptHTTP.h"
48 #include "wptKeyEdit.h"
49 #include "wptImport.h"
50 #include "wptCrypto.h"
51 #include "wptUTF8.h"
52 #include "wptGPGME.h"
53
54
55 /* Return a user friendly key representation in @buf of
56 the key given by @keyid. */
57 void
58 key_get_clip_info (const char *keyid, char *buf, size_t buflen)
59 {
60 winpt_key_s key;
61 gpgme_key_t pk;
62
63 memset (&key, 0, sizeof (key));
64 if (winpt_get_pubkey (keyid, &key))
65 BUG (NULL);
66 pk = key.ctx;
67 _snprintf (buf, buflen-1,
68 "pub %04d%s/%s %s %s\r\n"
69 " Primary key fingerprint: %s\r\n",
70 pk->subkeys->length,
71 get_key_pubalgo2 (pk->subkeys->pubkey_algo),
72 pk->subkeys->keyid+8,
73 get_key_created (pk->subkeys->timestamp),
74 key.ext->uids->uid,
75 get_key_fpr (pk));
76 }
77
78
79 /* Return a general description of the key @key. */
80 char*
81 km_key_get_info (winpt_key_t key, int is_sec)
82 {
83 gpgme_key_t pk;
84 const char *fmt = "%s %04d%s/0x%s %s\n \"%s\"";
85 char *p;
86 int n;
87
88 pk = key->ctx;
89 n = strlen (fmt) + 8 + 2 + 16 + 12 + strlen (pk->uids->uid) + 32;
90 p = new char[n+1];
91 if (!p)
92 BUG (NULL);
93 _snprintf (p, n, fmt, is_sec? "sec" : "pub",
94 pk->subkeys->length,
95 get_key_pubalgo2 (pk->subkeys->pubkey_algo),
96 pk->subkeys->keyid+8, get_key_created (pk->subkeys->timestamp),
97 key->ext->uids->uid);
98 return p;
99 }
100
101
102 /* Retrieve the opaque 32-bit param stored within the list view item
103 at position @idx and return the gpgme key context. */
104 gpgme_key_t
105 km_get_key_ptr (listview_ctrl_t lv, int idx, struct keycache_s **r_ctx)
106 {
107 struct keycache_s *ctx;
108
109 ctx = (struct keycache_s *)listview_get_item2 (lv, idx);
110 if (!ctx)
111 BUG (0);
112 if (r_ctx)
113 *r_ctx = ctx;
114 return ctx->key;
115 }
116
117
118 /* Check if list view @lv contains a secret key at position @pos.
119 If utrust is valid, set it to 1 if the key is valid -1 otherwise.
120 Return value: 1 normal key, 2 smart card key. */
121 int
122 km_check_for_seckey (listview_ctrl_t lv, int pos, int *utrust)
123 {
124 gpgme_key_t key;
125 winpt_key_s sk;
126 int type = 0;
127
128 key = km_get_key_ptr (lv, pos, NULL);
129 if (utrust)
130 *utrust = 0;
131 memset (&sk, 0, sizeof (sk));
132 if (!winpt_get_seckey (key->subkeys->keyid+8, &sk))
133 type = 1;
134 if (sk.ext && sk.ext->gloflags.divert_to_card)
135 type = 2;
136 if (utrust && (key->expired || key->revoked))
137 *utrust = -1;
138 else if (utrust && key->owner_trust == GPGME_VALIDITY_ULTIMATE)
139 *utrust = 1;
140 return type;
141 }
142
143
144 /* Check if the key at position @pos is protected with a passwd. */
145 int
146 km_check_if_protected (listview_ctrl_t lv, int pos)
147 {
148 gpgme_key_t key;
149 winpt_key_s k;
150
151 key = km_get_key_ptr (lv, pos, NULL);
152 if (!key)
153 return 1; /* assume yes */
154 winpt_get_pubkey (key->subkeys->keyid, &k);
155 return k.is_protected;
156 }
157
158
159 /* Check if the key has a good status.
160 Return value: 0 on success. */
161 int
162 km_check_key_status (listview_ctrl_t lv, int pos)
163 {
164 int flags = km_get_key_status (lv, pos);
165
166 if (flags & KM_FLAG_EXPIRED) {
167 msg_box (lv->ctrl, _("This key has expired!\n"
168 "Key check failed."), _("Key Manager"), MB_ERR);
169 return -1;
170 }
171 else if (flags & KM_FLAG_REVOKED) {
172 msg_box (lv->ctrl, _("This key has been revoked by its owner!\n"
173 "Key check failed."), _("Key Manager"), MB_ERR);
174 return -1;
175 }
176
177 return 0;
178 }
179
180
181 /* Return all key flags ORed. */
182 int
183 km_get_key_status (listview_ctrl_t lv, int pos)
184 {
185 gpgme_key_t key;
186 int flags = 0;
187
188 if (pos == -1)
189 return 0;
190 key = km_get_key_ptr (lv, pos, NULL);
191 if (!key)
192 return 0;
193
194 if (key->expired)
195 flags |= KM_FLAG_EXPIRED;
196 if (key->revoked)
197 flags |= KM_FLAG_REVOKED;
198 if (key->disabled)
199 flags |= KM_FLAG_DISABLED;
200 return flags;
201 }
202
203
204 /* Interface to enable or disable a key (@enable = 1 then enable).
205 The key is retrieved from a list control @lv at the pos @pos. */
206 int
207 km_enable_disable_key (listview_ctrl_t lv, HWND dlg, int pos, int enable)
208 {
209 gpgme_error_t err;
210 gpgme_key_t key;
211 GpgKeyEdit *ke;
212
213 key = km_get_key_ptr (lv, pos, NULL);
214 ke = new GpgKeyEdit (key->subkeys->keyid);
215 if (!ke)
216 BUG (NULL);
217
218 err = enable? ke->enable () : ke->disable ();
219 if (!err)
220 show_msg (dlg, 1500, _("Key status changed."));
221 else
222 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
223 delete ke;
224 return err? WPTERR_GENERAL : 0;
225 }
226
227
228
229 /* Create a string that contain all keyids from
230 the key list @rset separated by a space. */
231 char*
232 gpg_keylist_to_pattern (gpgme_key_t *rset, int n)
233 {
234 char *p;
235 int i;
236
237 if (!n)
238 return NULL;
239 p = (char *)calloc (1, n*(16+1)+n+2);
240 if (!p)
241 BUG (NULL);
242 for (i=0; i < n; i++) {
243 strcat (p, rset[i]->subkeys->keyid);
244 strcat (p, " ");
245 }
246 return p;
247 }
248
249
250 /* Export the selected keys in @lv to the clipboard. */
251 int
252 km_clip_export (HWND dlg, listview_ctrl_t lv)
253 {
254 gpgme_error_t err;
255 gpgme_key_t *rset;
256 GPGME *ctx;
257 char *patt=NULL;
258 char buf[256];
259 int n=0;
260 int rc=0;
261
262 rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
263 if (!n) {
264 msg_box (dlg, _("No key was selected for export."),
265 _("Key Manager"), MB_ERR);
266 return WPTERR_GENERAL;
267 }
268
269 patt = gpg_keylist_to_pattern (rset, n);
270
271 ctx = new GPGME ();
272 if (!ctx)
273 BUG (0);
274 ctx->setArmor (true);
275 err = ctx->exportToClipboard (patt);
276 if (err) {
277 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
278 rc = WPTERR_GENERAL;
279 goto leave;
280 }
281 if (n == 1) {
282 key_get_clip_info (rset[0]->subkeys->keyid, buf, sizeof (buf)-1);
283 set_clip_text2 (NULL, buf, strlen (buf), 0);
284 }
285
286 show_msg (dlg, 1500, _("GnuPG Status: Finished"));
287
288 leave:
289 safe_free (rset);
290 safe_free (patt);
291 delete ctx;
292 return rc;
293 }
294
295
296 /* Export the selected secret key from @lv into @fname.
297 It is only allowed to export a single secret key. */
298 int
299 km_privkey_export (HWND dlg, listview_ctrl_t lv, const char *fname)
300 {
301 gpgme_key_t *rset;
302 gpgme_error_t err;
303 int n = 0;
304
305 rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
306 if (!n) {
307 msg_box (dlg, _("No key was selected for export."),
308 _("Key Manager"), MB_ERR);
309 return WPTERR_GENERAL;
310 }
311 if (n > 1) {
312 msg_box (dlg, _("Only one secret key can be exported."),
313 _("Key Manager"), MB_ERR);
314 free (rset);
315 return 0; /* we checked this before, so we just quit */
316 }
317
318 err = gpg_export_seckey (rset[0]->subkeys->keyid, fname);
319 if (err)
320 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
321 else
322 log_box (_("Key Manager"), MB_OK,
323 _("Secret key successfully saved in '%s'."), fname);
324
325 free (rset);
326 return err? WPTERR_GENERAL : 0;
327 }
328
329
330 /* Export the selected recipients from @lv into the file @fname. */
331 int
332 km_file_export (HWND dlg, listview_ctrl_t lv, const char *fname)
333 {
334 GPGME *ctx;
335 gpgme_key_t *rset;
336 gpgme_error_t err;
337 char *patt;
338 int n;
339
340 rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
341 if (!n) {
342 msg_box (dlg, _("No key was selected for export."),
343 _("Key Manager"), MB_ERR);
344 return WPTERR_GENERAL;
345 }
346 patt = gpg_keylist_to_pattern (rset, n);
347
348 ctx = new GPGME ();
349 ctx->setArmor (true);
350 err = ctx->exportToFile (patt, fname);
351 if (err) {
352 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
353 goto leave;
354 }
355 else
356 log_box (_("Key Manager"), MB_OK,
357 _("Key(s) successfully saved in '%s'."), fname);
358
359 leave:
360 delete ctx;
361 safe_free (patt);
362 return (int)err;
363 }
364
365
366 /* Read a dash escaped key from the clipboard
367 unescape it and write it back. */
368 static int
369 extract_dash_escaped_key (void)
370 {
371 gpgme_data_t inp, plain;
372 gpgme_error_t err;
373
374 err = gpg_data_new_from_clipboard (&inp, 0);
375 if (err) {
376 msg_box (NULL, gpgme_strerror (err), _("Key Manager"), MB_ERR);
377 return -1;
378 }
379 gpg_data_extract_plaintext (inp, &plain);
380 gpg_data_release_and_set_clipboard (plain, 0);
381 gpgme_data_release (inp);
382
383 return 0;
384 }
385
386
387 /* Import the PGP key data from the clipboard.
388 Return value: 0 on success. */
389 static gpgme_error_t
390 gpg_op_clip_import (gpgme_ctx_t ctx)
391 {
392 gpgme_error_t err = 0;
393 gpgme_data_t keydata = NULL;
394
395 err = gpg_data_new_from_clipboard (&keydata, 0);
396 if (!err)
397 err = gpgme_op_import (ctx, keydata);
398
399 gpgme_data_release (keydata);
400 return err;
401 }
402
403 /* Import keys from the clipboard. */
404 int
405 km_clip_import (HWND dlg, int *r_newkeys, int *r_newsks)
406 {
407 gpgme_error_t err;
408 gpgme_ctx_t ctx = NULL;
409 gpgme_import_result_t res;
410 fm_state_s fm_stat;
411 int pgptype;
412 int id, has_data = 0;
413 int new_keys = 0, new_sks = 0;
414
415 if (!gpg_clip_istext_avail (&has_data) && !has_data) {
416 msg_box (dlg, winpt_strerror (WPTERR_CLIP_ISEMPTY),
417 _("Key Manager"), MB_ERR);
418 return WPTERR_CLIP_ISEMPTY;
419 }
420 err = gpg_clip_is_secured (&pgptype, &has_data);
421 if (err)
422 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
423 if (!has_data) {
424 msg_box (dlg, _("No valid OpenPGP data found."),
425 _("Key Manager"), MB_ERR);
426 return WPTERR_NODATA;
427 }
428 if (!(pgptype & PGP_PUBKEY) && !(pgptype & PGP_SECKEY)) {
429 msg_box (dlg, _("No valid OpenPGP keys found."),
430 _("Key Manager"), MB_ERR);
431 return WPTERR_NODATA;
432 }
433 if (pgptype & PGP_DASH_ESCAPED) {
434 id = msg_box (dlg, _("The key you want to import is dash escacped.\n"
435 "Do you want to extract the key?"),
436 _("Key Manager"), MB_YESNO);
437 if (id == IDYES)
438 extract_dash_escaped_key ();
439 else
440 msg_box (dlg, _("Cannot import dash escaped OpenPGP keys."),
441 _("Key Manager"), MB_INFO);
442 }
443
444 memset (&fm_stat, 0, sizeof (fm_stat));
445 fm_stat.opaque = m_strdup ("Clipboard");
446 fm_stat.import.is_clip = 1;
447 has_data = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
448 file_import_dlg_proc, (LPARAM)&fm_stat,
449 _("Key Import"), IDS_WINPT_IMPORT);
450 if (!has_data)
451 goto leave;
452
453 err = gpgme_new (&ctx);
454 if (err)
455 BUG (NULL);
456 op_begin ();
457 err = gpg_op_clip_import (ctx);
458 op_end ();
459 if (err) {
460 msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
461 goto leave;
462 }
463
464 res = gpgme_op_import_result (ctx);
465 print_import_status (res);
466 new_keys = res->considered - res->unchanged;
467 new_sks = res->secret_imported - res->secret_unchanged;
468 if (res->no_user_id > 0) {
469 msg_box (dlg, _("Key without a self signature was dectected!\n"
470 "(This key is NOT usable for encryption, etc)\n"),
471 _("Import"), MB_WARN);
472 }
473
474 leave:
475 if (ctx)
476 gpgme_release (ctx);
477 free_if_alloc (fm_stat.opaque);
478 if (r_newkeys)
479 *r_newkeys = new_keys;
480 if (r_newsks)
481 *r_newsks = new_sks;
482 if (!new_keys || !has_data)
483 return WPTERR_NODATA;
484 return (int)err;
485 }
486
487
488 /* Import a key from the http URL @url. */
489 int
490 km_http_import (HWND dlg, const char *url)
491 {
492 FILE *fp;
493 wHTTP *hd;
494 char tmpfile[500];
495 int rc = 0;
496
497 if (strncmp (url, "http://", 7)) {
498 log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);
499 return WPTERR_GENERAL;
500 }
501
502 get_temp_name (tmpfile, sizeof (tmpfile)-1, "winpt_http.tmp");
503 fp = fopen (tmpfile, "wb");
504 if (!fp) {
505 log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", tmpfile,
506 winpt_strerror (WPTERR_FILE_CREAT));
507 return WPTERR_FILE_CREAT;
508 }
509
510 hd = new wHTTP (url);
511 if (hd->getStatusCode () == HTTP_STAT_200)
512 hd->readData (fp);
513 else {
514 log_box (_("Key Import HTTP"), MB_ERR,
515 _("Could not fetch key from URL: %s"), url);
516 rc = WPTERR_GENERAL;
517 }
518
519 delete hd;
520 fclose (fp);
521 if (!rc)
522 km_file_import (dlg, tmpfile, NULL, NULL);
523 DeleteFile (tmpfile);
524 return rc;
525 }
526
527
528 /* Import a key from the given file @fname, if @fname is
529 NULL use the common 'file open' dialog.
530 On success an import statistics dialog is shown. */
531 int
532 km_file_import (HWND dlg, const char *fname, int *r_newkeys, int *r_newsks)
533 {
534 gpgme_data_t keydata = NULL;
535 gpgme_ctx_t ctx;
536 gpgme_error_t err;
537 fm_state_s fm_stat;
538 gpgme_import_result_t res;
539 const char *name;
540 int no_data = 0;
541 int new_keys = 0, new_sks = 0;
542
543 if (!fname) {
544 name = get_fileopen_dlg (dlg, _("Choose Name of the Key File"),
545 NULL, NULL);
546 if (!name)
547 return WPTERR_GENERAL;
548 }
549 else
550 name = fname;
551
552 memset (&fm_stat, 0, sizeof (fm_stat));
553 fm_stat.opaque = m_strdup (name);
554
555 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
556 file_import_dlg_proc, (LPARAM)&fm_stat,
557 _("File Import"), IDS_WINPT_IMPORT);
558 if (fm_stat.cancel == 1) {
559 free_if_alloc (fm_stat.opaque);
560 return WPTERR_GENERAL;
561 }
562
563 err = gpgme_new (&ctx);
564 if (err)
565 BUG (NULL);
566 err = gpgme_data_new_from_file (&keydata, name, 1);
567 if (err) {
568 msg_box (dlg, _("Could not read key-data from file."),
569 _("Key Manager"), MB_ERR);
570 goto leave;
571 }
572
573 op_begin ();
574 err = gpgme_op_import (ctx, keydata);
575 op_end ();
576 if (err) {
577 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
578 goto leave;
579 }
580
581 res = gpgme_op_import_result (ctx);
582 if (res->unchanged == res->considered &&
583 res->secret_unchanged == res->secret_imported)
584 no_data = 1;
585 new_keys = res->considered - res->unchanged;
586 new_sks = res->secret_imported - res->secret_unchanged;
587 if (res->new_revocations == 0 && fm_stat.import.revcert == 1)
588 res->new_revocations = 1;
589 if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)
590 res->secret_imported = 1;
591
592 /* XXX: if we import a key pair but the secret key comes first,
593 no_{valid}_user_id is 1 even so the public key, which comes
594 later is valid and self-signed. */
595 print_import_status (res);
596 if (res->no_user_id > 0) {
597 msg_box (dlg, _("Key without a self signature was dectected!\n"
598 "(This key is NOT usable for encryption, etc)\n"),
599 _("Import"), MB_WARN);
600 }
601
602 leave:
603 gpgme_data_release (keydata);
604 gpgme_release (ctx);
605 free_if_alloc (fm_stat.opaque);
606 if (r_newkeys)
607 *r_newkeys = new_keys;
608 if (r_newsks)
609 *r_newsks = new_sks;
610 if (no_data)
611 return WPTERR_NODATA;
612 return (int)err;
613 }
614
615
616 /* Import all dropped files. */
617 int
618 km_dropped_file_import (HWND dlg, HDROP hdrop,
619 int *r_newkeys, int *r_newsks)
620 {
621 char name[MAX_PATH+1];
622 UINT n = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
623 UINT i;
624 int newk=0, newsk=0, err=0;
625
626 for (i=0; i < n; i++) {
627 DragQueryFile (hdrop, i, name, MAX_PATH);
628 err = km_file_import (dlg, name, &newk, &newsk);
629 *r_newkeys = (*r_newkeys) + newk;
630 *r_newsks = (*r_newsks) + newsk;
631 }
632 DragFinish (hdrop);
633 return err;
634 }
635
636
637 /* Mark the keys in @rset as deleted in the keycache. */
638 static void
639 delete_keys_from_cache (gpgme_key_t *rset, size_t n)
640 {
641 gpg_keycache_t pub = keycache_get_ctx (1);
642 gpg_keycache_t sec = keycache_get_ctx (0);
643 gpgme_key_t sk;
644 int i=0;
645
646 while (n-- > 0) {
647 if (!get_seckey (rset[i]->subkeys->keyid, &sk))
648 gpg_keycache_delete_key (sec, sk->subkeys->keyid);
649 gpg_keycache_delete_key (pub, rset[i]->subkeys->keyid);
650 i++;
651 }
652 }
653
654
655 /* Check that the selected default secret key is still
656 available. If not, delete the entry in gpg.conf. */
657 static void
658 check_exist_default_key (void)
659 {
660 gpgme_key_t sk;
661 char *defkey;
662
663 defkey = get_gnupg_default_key ();
664 if (defkey && get_seckey (defkey, &sk))
665 set_gnupg_default_key (NULL);
666 free_if_alloc (defkey);
667 }
668
669
670 /* Delete all selected keys from the list view @lv. */
671 int
672 km_delete_keys (listview_ctrl_t lv, HWND dlg)
673 {
674 gpgme_error_t err;
675 gpgme_ctx_t ctx;
676 gpgme_key_t *rset;
677 winpt_key_s key2;
678 char *p;
679 int with_seckey=0, seckey_type=0, confirm=0;
680 int i, rc, n, k_pos=0;
681
682 if (listview_get_curr_pos (lv) == -1) {
683 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
684 return -1;
685 }
686
687 if (listview_count_items (lv, 1) > 8) {
688 i = msg_box (NULL, _("Do you really want to confirm each key?"),
689 _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);
690 if (i == IDCANCEL)
691 return 0;
692 if (i != IDNO)
693 confirm = 1;
694 }
695 else
696 confirm = 1;
697
698 /* n = total amount of keys, i is the selected amount. */
699 n = listview_count_items (lv, 0);
700 i = listview_count_items (lv, 1);
701 rset = (gpgme_key_t *)calloc (i+1, sizeof (gpgme_key_t));
702 if (!rset)
703 BUG (NULL);
704 for (i = 0; i < n; i++) {
705 if (listview_get_item_state(lv, i)) {
706 km_get_key (lv, i, &key2);
707
708 seckey_type = km_check_for_seckey (lv, i, NULL);
709 if (confirm && !seckey_type) {
710 p = km_key_get_info (&key2, 0);
711 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
712 _("Do you really want to delete this key?\n\n"
713 "%s"), p);
714 if (rc == IDYES)
715 rset[k_pos++] = key2.ctx;
716 free_if_alloc (p);
717 }
718 else if (confirm) {
719 p = km_key_get_info (&key2, 1);
720 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
721 _("Do you really want to delete this KEY PAIR?\n\n"
722 "Please remember that you are not able to decrypt\n"
723 "messages you stored with this key any longer.\n"
724 "\n"
725 "%s"), p);
726 if (rc == IDYES) {
727 if (seckey_type == 2)
728 msg_box (dlg, _("The actual secret key is stored on a smartcard.\n"
729 "Only the public key and the secret key \n"
730 "placeholder will be deleted.\n"),
731 _("Key Manager"), MB_OK);
732 rset[k_pos++] = key2.ctx;
733 }
734 with_seckey = 1;
735 free_if_alloc (p);
736 }
737 else {
738 with_seckey = 1;
739 rset[k_pos++] = key2.ctx;
740 }
741 }
742 }
743
744 if (k_pos == 0) {
745 free (rset);
746 return 0;
747 }
748
749 err = gpgme_new (&ctx);
750 if (err)
751 BUG (NULL);
752 n = k_pos;
753 op_begin ();
754 for (i=0; i < k_pos; i++) {
755 err = gpgme_op_delete (ctx, rset[i], with_seckey);
756 if (err)
757 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
758 else
759 n--;
760 }
761 op_end ();
762 if (n == 0)
763 show_msg (dlg, 1500, _("GnuPG Status: Finished"));
764 gpgme_release (ctx);
765 listview_del_sel_items (lv);
766 delete_keys_from_cache (rset, k_pos);
767 free (rset);
768 if (with_seckey)
769 check_exist_default_key ();
770 return (int)err;
771 }
772
773
774 /* Send the select key in @lv to the keyserver @host:@port. */
775 int
776 km_send_to_keyserver (listview_ctrl_t lv, HWND dlg,
777 const char *host, WORD port)
778 {
779 winpt_key_s key;
780 int id;
781
782 id = listview_get_curr_pos (lv);
783 if (id == -1) {
784 msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
785 return WPTERR_GENERAL;
786 }
787
788 km_get_key (lv, id, &key);
789 id = log_box (_("Key Manager"), MB_YESNO,
790 _("Do you really want to send '0x%s' to keyserver %s?"),
791 key.keyid, host);
792 if (id == IDYES)
793 hkp_send_key (dlg, host, port, key.keyid);
794
795 return 0;
796 }
797
798
799 /* Send the selected key in @lv via MAPI to a mail recipient. */
800 int
801 km_send_to_mail_recipient (listview_ctrl_t lv, HWND dlg)
802 {
803 gpgme_key_t key;
804 gpgme_error_t rc;
805 GPGME *ctx;
806 struct keycache_s *c;
807 char *fname;
808 int pos;
809 int n;
810
811 if (listview_count_items (lv, 1) > 1) {
812 msg_box (dlg, _("Please only select one key."),
813 _("Key Manager"), MB_INFO|MB_OK);
814 return WPTERR_GENERAL;
815 }
816 pos = listview_get_curr_pos (lv);
817 if (pos == -1) {
818 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
819 return WPTERR_GENERAL;
820 }
821 key = km_get_key_ptr (lv, pos, &c);
822
823 n = strlen (c->uids->name)+1 + MAX_PATH + 5;
824 fname = new char[n+1];
825 get_temp_name (fname, n-5, c->uids->name);
826 for (pos=0; pos < (int)strlen (fname); pos++) {
827 if (fname[pos] == ' ')
828 fname[pos] = '_';
829 }
830 strcat (fname, ".asc");
831 ctx = new GPGME ();
832 ctx->setArmor (true);
833 rc = ctx->exportToFile (key->subkeys->keyid, fname);
834 if (rc)
835 msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
836 else
837 mapi_send_pubkey (key->subkeys->keyid+8, fname);
838
839 delete ctx;
840 free_if_alloc (fname);
841 return rc;
842 }
843
844
845 /* Refresh the selected key in the listview @lv at position @pos.
846 Legal flags are 0 = single key. */
847 static void
848 km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos, int flags)
849 {
850 winpt_key_s pk;
851 gpgme_key_t key;
852 const char *pref_kserv = default_keyserver;
853 unsigned short pref_kserv_port = default_keyserver_port;
854 char keyid[16+1];
855 int idx, err = 0;
856
857 if (pos != 0)
858 idx = pos;
859 else
860 idx = listview_get_curr_pos (lv);
861 if (idx != -1) {
862 key = km_get_key_ptr (lv, idx, NULL);
863
864 /* In single refresh mode, try to use the users preferred keyserver. */
865 if (flags == 0 &&
866 !winpt_get_pubkey (key->subkeys->keyid+8, &pk) &&
867 !gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFKSERV, 0) &&
868 pk.ext->pref_keyserver &&
869 !strstr (pk.ext->pref_keyserver, "ldap://")) {
870 pref_kserv = pk.ext->pref_keyserver;
871 pref_kserv_port = pk.ext->pref_keyserver_port;
872 }
873 _snprintf (keyid, sizeof (keyid)-1, "%s", key->subkeys->keyid+8);
874 err = hkp_recv_key (dlg, pref_kserv, pref_kserv_port,
875 keyid, 0, flags);
876 /* if we receive just a single key (no refresh mode), update it. */
877 if (!flags && !err)
878 keycache_update (0, keyid);
879 }
880 }
881
882
883 /* Refresh the selected keys from the default keyserver. */
884 void
885 km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
886 {
887 int cnt, id, i;
888
889 cnt = listview_count_items (lv, 0);
890 if (listview_count_items (lv, 1) == cnt) {
891 id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"),
892 _("Key Manager"), MB_YESNO);
893 if (id == IDNO)
894 return;
895 if (kserver_check_inet_connection ()) {
896 msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
897 _("Key Manager"), MB_ERR);
898 return;
899 }
900 }
901 if (listview_count_items (lv, 1) == 1)
902 km_refresh_one_key (lv, dlg, listview_get_curr_pos (lv), 0);
903 else {
904 for (i=0; i < cnt; i++) {
905 if (listview_get_item_state (lv, i))
906 km_refresh_one_key (lv, dlg, i, KM_KS_REFRESH);
907 }
908 }
909 }
910
911
912 void
913 km_set_clip_info (const char *uid)
914 {
915 char buf[256];
916
917 key_get_clip_info (uid, buf, sizeof (buf)-1);
918 set_clip_text (NULL, buf, strlen (buf));
919 }
920
921
922
923 /* Return TRUE if the key in the list @lv at pos @pos is an
924 old version 3 key. */
925 int
926 km_key_is_v3 (listview_ctrl_t lv, int pos)
927 {
928 gpgme_key_t pk;
929
930 pk = km_get_key_ptr (lv, pos, NULL);
931 if (strlen (pk->subkeys->fpr) == 32 &&
932 pk->subkeys->pubkey_algo == GPGME_PK_RSA)
933 return -1;
934 return 0;
935 }
936
937
938 /* Set trust of selected key in @lv (at @pos) to ultimate. */
939 int
940 km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
941 {
942 gpgme_error_t err;
943 gpgme_key_t key;
944 GpgKeyEdit *ke;
945
946 key = km_get_key_ptr (lv, pos, NULL);
947 ke = new GpgKeyEdit (key->subkeys->keyid);
948 if (!ke)
949 BUG (0);
950
951 err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
952 if (err)
953 msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
954 else
955 show_msg (dlg, 1500, _("GnuPG Status: Finished"));
956
957 delete ke;
958 return (int)err;
959 }
960
961
962 /* Provide a search dialog and try to find and select
963 the key which matches the entered pattern. */
964 void
965 km_find_key (HWND dlg, listview_ctrl_t lv)
966 {
967 int oldpos = listview_get_curr_pos (lv);
968 int n;
969 char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
970
971 if (!name)
972 return;
973 if (oldpos < 0)
974 oldpos = 0;
975 n = listview_find (lv, name, 1);
976 if (n != -1) {
977 listview_select_one (lv, n);
978 listview_scroll (lv, oldpos, n);
979 }
980 else {
981 const char *s = _("String pattern \"%s\" not found.");
982 char *p = new char[strlen (s) + strlen (name) + 2];
983 if (!p)
984 BUG (0);
985 sprintf (p, s, name);
986 msg_box (dlg, p, _("Key Manager"), MB_INFO);
987 free_if_alloc (p);
988 }
989 free_if_alloc (name);
990 }
991
992
993 /* Return a user-friendly name for a key derrived from
994 name. If @is_secret is 1, a secret key name will be generated. */
995 char*
996 km_gen_export_filename (const char *keyid, int is_secret)
997 {
998 winpt_key_s key;
999 size_t i;
1000 char *p;
1001
1002 memset (&key, 0, sizeof (key));
1003 if (winpt_get_pubkey (keyid, &key))
1004 return m_strdup (keyid);
1005
1006 p = new char[strlen (key.ext->uids->name) + 8 + 16];
1007 if (!p)
1008 BUG (0);
1009 sprintf (p, "%s%s.asc", key.ext->uids->name, is_secret? "_sec" : "");
1010 for (i=0; i < strlen (p); i++) {
1011 if (p[i] == ' ' || p[i] == ':' || p[i] == '?' || p[i] == '|' ||
1012 p[i] == '\\' || p[i] == '/')
1013 p[i] = '_';
1014 }
1015 return p;
1016 }
1017
1018
1019 /* Retrieve the GPGME pointer from the selected list view
1020 item and return the WinPT specific key context. */
1021 int
1022 km_get_key (listview_ctrl_t lv, int pos, winpt_key_t k)
1023 {
1024 struct keycache_s *c;
1025 gpgme_key_t key;
1026
1027 if (pos == -1)
1028 return -1;
1029 key = km_get_key_ptr (lv, pos, &c);
1030 memset (k, 0, sizeof (*k));
1031 strncpy (k->tmp_keyid, key->subkeys->keyid+8, 8);
1032 k->keyid = k->tmp_keyid;
1033 k->is_protected = km_check_if_protected (lv, pos);
1034 k->key_pair = km_check_for_seckey (lv, pos, NULL);
1035 k->is_v3 = km_key_is_v3 (lv, pos);
1036 k->flags = km_get_key_status (lv, pos);
1037 k->ctx = key;
1038 k->ext = c;
1039 k->uid = c->uids->uid;
1040 return 0;
1041 }
1042
1043
1044 /* Show details of the revocation of the key @k. */
1045 void
1046 km_key_show_revoc_info (winpt_key_t k)
1047 {
1048 const char *desc;
1049 char *val=NULL, *p;
1050 int len, reason;
1051 const char *reasons[] = {
1052 _("0. No reason specified"),
1053 _("1. Key has been compromised"),
1054 _("2. Key is superseded"),
1055 _("3. Key is no longer used"),
1056 NULL
1057 };
1058
1059 /* spk:29:1:19:%00This key is kaputt */
1060 gpg_find_key_subpacket (k->keyid, 29, &val);
1061 if (!val || strlen (val) < 3) {
1062 safe_free (val);
1063 return;
1064 }
1065
1066 len = atoi (val+9);
1067 p = strchr (val+9, ':');
1068 assert (p);
1069 p++;
1070 reason = atoi (p+1);
1071 if (strlen (p+1) > 0)
1072 desc = p+3;
1073 else
1074 desc = "none";
1075 log_box (_("Key Manager"), MB_OK,
1076 "Key revocation info for '%s':\n"
1077 "Reason for revocation: %s\n"
1078 "Description: %s\n",
1079 k->ctx->uids->name, reasons[reason % 4]+3,
1080 desc);
1081 safe_free (val);
1082 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26