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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 207 - (hide annotations)
Fri Apr 28 10:28:24 2006 UTC (18 years, 10 months ago) by twoaday
File size: 27412 byte(s)
Bug fixes and cleanups.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26