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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 247 - (hide annotations)
Fri Jul 21 08:19:24 2006 UTC (18 years, 7 months ago) by twoaday
File size: 27902 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26