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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (show annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 27305 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26