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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 214 - (hide annotations)
Sun May 14 18:40:36 2006 UTC (18 years, 9 months ago) by twoaday
File size: 27476 byte(s)
2006-05-14  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptKeyCache.cpp (gpg_keycache_update_attr): Parse
        preferred keyserver URL.
        * wptHTTP.cpp (extractHostInfo): Fix segv.
        * wptGPGUtil.cpp (gpg_find_key_subpacket): Ignore default
        gpg.conf.
        * wptKeyserverSearchDlg.cpp (search_hkp_keys): Do not
        assume an existing user id.
        * wptPassphraseCB.cpp (passphrase_cb): Automatic cancel
        if no passphrase is available.

(for complete list of changes, see Src/ChangeLog)

About to release 0.12.1


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 121 for (i = 0; i < n; i++) {
705 twoaday 212 if (listview_get_item_state(lv, i)) {
706     km_get_key (lv, i, &key2);
707 twoaday 207
708 werner 36 seckey_type = km_check_for_seckey (lv, i, NULL);
709     if (confirm && !seckey_type) {
710 twoaday 207 p = km_key_get_info (&key2, 0);
711 twoaday 133 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
712 werner 36 _("Do you really want to delete this key?\n\n"
713 twoaday 128 "%s"), p);
714     if (rc == IDYES)
715 twoaday 207 rset[k_pos++] = key2.ctx;
716 twoaday 128 free_if_alloc (p);
717 werner 36 }
718     else if (confirm) {
719 twoaday 207 p = km_key_get_info (&key2, 1);
720 twoaday 121 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
721 werner 36 _("Do you really want to delete this KEY PAIR?\n\n"
722     "Please remember that you are not able to decrypt\n"
723     "messages you stored with this key any longer.\n"
724     "\n"
725 twoaday 128 "%s"), p);
726 twoaday 133 if (rc == IDYES) {
727 werner 36 if (seckey_type == 2)
728 twoaday 121 msg_box (dlg, _("The actual secret key is stored on a smartcard.\n"
729 werner 36 "Only the public key and the secret key \n"
730 twoaday 121 "placeholder will be deleted.\n"),
731     _("Key Manager"), MB_OK);
732 twoaday 207 rset[k_pos++] = key2.ctx;
733 werner 36 }
734     with_seckey = 1;
735 twoaday 128 free_if_alloc (p);
736 werner 36 }
737     else {
738     with_seckey = 1;
739 twoaday 207 rset[k_pos++] = key2.ctx;
740 werner 36 }
741     }
742     }
743    
744     if (k_pos == 0) {
745     free (rset);
746     return 0;
747     }
748    
749     err = gpgme_new (&ctx);
750     if (err)
751     BUG (NULL);
752 twoaday 128 n = k_pos;
753 twoaday 130 op_begin ();
754 werner 36 for (i=0; i < k_pos; i++) {
755     err = gpgme_op_delete (ctx, rset[i], with_seckey);
756     if (err)
757     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
758     else
759     n--;
760     }
761 twoaday 130 op_end ();
762 werner 36 if (n == 0)
763 twoaday 179 show_msg (dlg, 1500, _("GnuPG Status: Finished"));
764 werner 36 gpgme_release (ctx);
765 twoaday 150 listview_del_sel_items (lv);
766 werner 36 delete_keys_from_cache (rset, k_pos);
767     free (rset);
768 twoaday 179 if (with_seckey)
769     check_exist_default_key ();
770 werner 36 return (int)err;
771     }
772    
773    
774 twoaday 121 /* Send the select key in @lv to the keyserver @host:@port. */
775 werner 36 int
776 twoaday 181 km_send_to_keyserver (listview_ctrl_t lv, HWND dlg,
777     const char *host, WORD port)
778 werner 36 {
779 twoaday 212 winpt_key_s key;
780 werner 36 int id;
781    
782 twoaday 121 id = listview_get_curr_pos (lv);
783     if (id == -1) {
784 werner 36 msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
785     return WPTERR_GENERAL;
786     }
787    
788 twoaday 212 km_get_key (lv, id, &key);
789 werner 36 id = log_box (_("Key Manager"), MB_YESNO,
790 twoaday 195 _("Do you really want to send '0x%s' to keyserver %s?"),
791 twoaday 212 key.keyid, host);
792 twoaday 128 if (id == IDYES)
793 twoaday 212 hkp_send_key (dlg, host, port, key.keyid);
794 werner 36
795     return 0;
796 twoaday 121 }
797 werner 36
798    
799 twoaday 77 /* Send the selected key in @lv via MAPI to a mail recipient. */
800 werner 36 int
801 twoaday 77 km_send_to_mail_recipient (listview_ctrl_t lv, HWND dlg)
802 werner 36 {
803     gpgme_key_t key;
804     gpgme_error_t rc;
805 twoaday 175 GPGME *ctx;
806 twoaday 205 struct keycache_s *c;
807 twoaday 121 char *fname;
808 werner 36 int pos;
809 twoaday 175 int n;
810 werner 36
811 twoaday 121 if (listview_count_items (lv, 1) > 1) {
812 twoaday 77 msg_box (dlg, _("Please only select one key."),
813     _("Key Manager"), MB_INFO|MB_OK);
814 werner 36 return WPTERR_GENERAL;
815     }
816 twoaday 77 pos = listview_get_curr_pos (lv);
817     if (pos == -1) {
818     msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
819 werner 36 return WPTERR_GENERAL;
820     }
821 twoaday 205 key = km_get_key_ptr (lv, pos, &c);
822 werner 36
823 twoaday 205 n = strlen (c->uids->name)+1 + MAX_PATH + 5;
824 twoaday 175 fname = new char[n+1];
825 twoaday 205 get_temp_name (fname, n-5, c->uids->name);
826 twoaday 121 for (pos=0; pos < (int)strlen (fname); pos++) {
827     if (fname[pos] == ' ')
828     fname[pos] = '_';
829     }
830 twoaday 175 strcat (fname, ".asc");
831     ctx = new GPGME ();
832     ctx->setArmor (true);
833     rc = ctx->exportToFile (key->subkeys->keyid, fname);
834 werner 36 if (rc)
835     msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
836 twoaday 175 else
837 twoaday 128 mapi_send_pubkey (key->subkeys->keyid+8, fname);
838 werner 36
839 twoaday 175 delete ctx;
840 twoaday 121 free_if_alloc (fname);
841 werner 36 return rc;
842     }
843    
844    
845 twoaday 181 /* Refresh the selected key in the listview @lv at position @pos.
846     Legal flags are 0 = single key. */
847 werner 36 static void
848 twoaday 133 km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos, int flags)
849 werner 36 {
850 twoaday 181 winpt_key_s pk;
851 twoaday 128 gpgme_key_t key;
852 twoaday 181 const char *pref_kserv = default_keyserver;
853 twoaday 214 unsigned short pref_kserv_port = default_keyserver_port;
854 twoaday 165 char keyid[16+1];
855     int idx, err = 0;
856 twoaday 181
857 werner 36 if (pos != 0)
858     idx = pos;
859     else
860     idx = listview_get_curr_pos (lv);
861 twoaday 121 if (idx != -1) {
862 twoaday 205 key = km_get_key_ptr (lv, idx, NULL);
863 twoaday 214
864 twoaday 181 /* In single refresh mode, try to use the users preferred keyserver. */
865     if (flags == 0 &&
866     !winpt_get_pubkey (key->subkeys->keyid+8, &pk) &&
867 twoaday 214 !gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFKSERV, 0) &&
868     pk.ext->pref_keyserver &&
869     !strstr (pk.ext->pref_keyserver, "ldap://")) {
870 twoaday 181 pref_kserv = pk.ext->pref_keyserver;
871 twoaday 214 pref_kserv_port = pk.ext->pref_keyserver_port;
872     }
873 twoaday 165 _snprintf (keyid, sizeof (keyid)-1, "%s", key->subkeys->keyid+8);
874 twoaday 214 err = hkp_recv_key (dlg, pref_kserv, pref_kserv_port,
875 twoaday 165 keyid, 0, flags);
876     /* if we receive just a single key (no refresh mode), update it. */
877     if (!flags && !err)
878     keycache_update (0, keyid);
879 werner 36 }
880     }
881    
882    
883 twoaday 133 /* Refresh the selected keys from the default keyserver. */
884 werner 36 void
885     km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
886     {
887 twoaday 175 int cnt, id, i;
888 twoaday 133
889     cnt = listview_count_items (lv, 0);
890     if (listview_count_items (lv, 1) == cnt) {
891     id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"),
892 twoaday 121 _("Key Manager"), MB_YESNO);
893 werner 36 if (id == IDNO)
894     return;
895 twoaday 175 if (kserver_check_inet_connection ()) {
896     msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
897     _("Key Manager"), MB_ERR);
898     return;
899     }
900 werner 36 }
901 twoaday 133 if (listview_count_items (lv, 1) == 1)
902     km_refresh_one_key (lv, dlg, listview_get_curr_pos (lv), 0);
903 werner 36 else {
904 twoaday 133 for (i=0; i < cnt; i++) {
905 werner 36 if (listview_get_item_state (lv, i))
906 twoaday 133 km_refresh_one_key (lv, dlg, i, KM_KS_REFRESH);
907 werner 36 }
908     }
909 twoaday 121 }
910 werner 36
911    
912     void
913     km_set_clip_info (const char *uid)
914     {
915     char buf[256];
916    
917 twoaday 129 key_get_clip_info (uid, buf, sizeof (buf)-1);
918 werner 36 set_clip_text (NULL, buf, strlen (buf));
919 twoaday 121 }
920 werner 36
921    
922    
923     /* Return TRUE if the key in the list @lv at pos @pos is an
924     old version 3 key. */
925     int
926     km_key_is_v3 (listview_ctrl_t lv, int pos)
927     {
928     gpgme_key_t pk;
929    
930 twoaday 205 pk = km_get_key_ptr (lv, pos, NULL);
931 werner 36 if (strlen (pk->subkeys->fpr) == 32 &&
932     pk->subkeys->pubkey_algo == GPGME_PK_RSA)
933     return -1;
934     return 0;
935     }
936    
937    
938     /* Set trust of selected key in @lv (at @pos) to ultimate. */
939     int
940     km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
941     {
942 twoaday 128 gpgme_error_t err;
943     gpgme_key_t key;
944 werner 36 GpgKeyEdit *ke;
945    
946 twoaday 205 key = km_get_key_ptr (lv, pos, NULL);
947 twoaday 128 ke = new GpgKeyEdit (key->subkeys->keyid);
948 werner 36 if (!ke)
949     BUG (0);
950    
951     err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
952     if (err)
953     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
954     else
955     show_msg (dlg, 1500, _("GnuPG Status: Finished"));
956    
957     delete ke;
958     return (int)err;
959     }
960    
961    
962     void
963     km_find_key (HWND dlg, listview_ctrl_t lv)
964     {
965     int oldpos = listview_get_curr_pos (lv);
966     int n;
967     char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
968     if (name == NULL)
969     return;
970     if (oldpos < 0)
971     oldpos = 0;
972     n = listview_find (lv, name);
973     if (n != -1) {
974     listview_select_one (lv, n);
975     listview_scroll (lv, oldpos, n);
976     }
977     else {
978     const char *s = _("String pattern \"%s\" not found.");
979     char *p = new char[strlen (s) + strlen (name) + 2];
980     if (!p)
981     BUG (0);
982     sprintf (p, s, name);
983     msg_box (dlg, p, _("Key Manager"), MB_INFO);
984     free_if_alloc (p);
985     }
986     free_if_alloc (name);
987     }
988 twoaday 129
989    
990     /* Return a user-friendly name for a key derrived from
991     name. If @is_secret is 1, a secret key name will be generated. */
992     char*
993     km_gen_export_filename (const char *keyid, int is_secret)
994     {
995 twoaday 205 winpt_key_s key;
996     char *p;
997 twoaday 129
998 twoaday 205 memset (&key, 0, sizeof (key));
999     if (winpt_get_pubkey (keyid, &key))
1000 twoaday 129 return m_strdup (keyid);
1001 twoaday 205
1002     p = new char[strlen (key.ext->uids->name) + 8 + 16];
1003 twoaday 129 if (!p)
1004     BUG (0);
1005 twoaday 205 sprintf (p, "%s%s.asc", key.ext->uids->name, is_secret? "_sec" : "");
1006 twoaday 129 for (size_t i=0; i < strlen (p); i++) {
1007     if (p[i] == ' ' || p[i] == ':' || p[i] == '?' || p[i] == '|')
1008     p[i] = '_';
1009     }
1010     return p;
1011     }
1012 twoaday 200
1013    
1014     /* Retrieve the GPGME pointer from the selected list view
1015     item and return the WinPT specific key context. */
1016     int
1017     km_get_key (listview_ctrl_t lv, int pos, winpt_key_t k)
1018     {
1019 twoaday 207 struct keycache_s *c;
1020 twoaday 200 gpgme_key_t key;
1021    
1022     if (pos == -1)
1023     return -1;
1024 twoaday 207 key = km_get_key_ptr (lv, pos, &c);
1025 twoaday 200 memset (k, 0, sizeof (*k));
1026     strncpy (k->tmp_keyid, key->subkeys->keyid+8, 8);
1027     k->keyid = k->tmp_keyid;
1028     k->is_protected = km_check_if_protected (lv, pos);
1029     k->key_pair = km_check_for_seckey (lv, pos, NULL);
1030     k->is_v3 = km_key_is_v3 (lv, pos);
1031     k->flags = km_get_key_status (lv, pos);
1032     k->ctx = key;
1033 twoaday 207 k->ext = c;
1034     k->uid = c->uids->uid;
1035 twoaday 200 return 0;
1036     }
1037    
1038    
1039     /* Show details of the revocation of the key @k. */
1040     void
1041     km_key_show_revoc_info (winpt_key_t k)
1042     {
1043     const char *desc;
1044     char *val=NULL, *p;
1045     int len, reason;
1046     const char *reasons[] = {
1047     _("0. No reason specified"),
1048     _("1. Key has been compromised"),
1049     _("2. Key is superseded"),
1050     _("3. Key is no longer used"),
1051     NULL
1052     };
1053    
1054     /* spk:29:1:19:%00This key is kaputt */
1055     gpg_find_key_subpacket (k->keyid, 29, &val);
1056     if (!val || strlen (val) < 3) {
1057     safe_free (val);
1058     return;
1059     }
1060    
1061     len = atoi (val+9);
1062     p = strchr (val+9, ':');
1063     assert (p);
1064     p++;
1065     reason = atoi (p+1);
1066     if (strlen (p+1) > 0)
1067     desc = p+3;
1068     else
1069     desc = "none";
1070     log_box (_("Key Manager"), MB_OK,
1071     "Key revocation info for '%s':\n"
1072     "Reason for revocation: %s\n"
1073     "Description: %s\n",
1074     k->ctx->uids->name, reasons[reason % 4]+3,
1075     desc);
1076     safe_free (val);
1077     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26