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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 314 - (show annotations)
Sun May 13 09:44:03 2007 UTC (17 years, 9 months ago) by twoaday
File size: 26940 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26