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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26