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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 278 - (show annotations)
Mon Jan 15 22:02:04 2007 UTC (18 years, 1 month ago) by twoaday
File size: 27237 byte(s)
See ChangeLog.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26