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

Contents of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 181 - (show annotations)
Tue Mar 14 11:01:22 2006 UTC (18 years, 11 months ago) by twoaday
File size: 26886 byte(s)
2006-03-12  Timo Schulz  <ts@g10code.de>
 
        * wptGPG.cpp (gnupg_load_config): Search for 'ask-cert-expire'.
        * wptKeyPropsDlg.cpp (display_key_info): Automatically update
        sym algorithm preferences if needed.
        * wptKeysignDlg.cpp (date_is_today): New.
        (keysign_dlg_proc): Only allow to set cert expire date if
        the option was found.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Allow to set
        'ask-cert-expire'.
         


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26