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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 260 - (hide annotations)
Wed Aug 16 10:01:30 2006 UTC (18 years, 6 months ago) by twoaday
File size: 27508 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 twoaday 260 gpg_keylist_to_pattern (gpgme_key_t *rset, size_t n)
251 werner 36 {
252     char *p;
253 twoaday 260 size_t i;
254 werner 36
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 twoaday 260 size_t n=0;
278 werner 36 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 twoaday 260 size_t n = 0;
322 werner 36
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 twoaday 260 safe_free (rset);
344 werner 36 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 twoaday 260 size_t n;
357 werner 36
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     /* Import keys from the clipboard. */
406     int
407 twoaday 165 km_clip_import (HWND dlg, int *r_newkeys, int *r_newsks)
408 werner 36 {
409 twoaday 260 gpgme_error_t err;
410 twoaday 165 gpgme_import_result_t res;
411 twoaday 260 GPGME *gpg = NULL;
412 twoaday 165 fm_state_s fm_stat;
413 werner 36 int pgptype;
414 twoaday 165 int id, has_data = 0;
415     int new_keys = 0, new_sks = 0;
416    
417 werner 36 if (!gpg_clip_istext_avail (&has_data) && !has_data) {
418 twoaday 121 msg_box (dlg, winpt_strerror (WPTERR_CLIP_ISEMPTY),
419     _("Key Manager"), MB_ERR);
420 werner 36 return WPTERR_CLIP_ISEMPTY;
421     }
422     err = gpg_clip_is_secured (&pgptype, &has_data);
423     if (err)
424     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
425     if (!has_data) {
426 twoaday 121 msg_box (dlg, _("No valid OpenPGP data found."),
427     _("Key Manager"), MB_ERR);
428 twoaday 161 return WPTERR_NODATA;
429 werner 36 }
430     if (!(pgptype & PGP_PUBKEY) && !(pgptype & PGP_SECKEY)) {
431 twoaday 121 msg_box (dlg, _("No valid OpenPGP keys found."),
432     _("Key Manager"), MB_ERR);
433 twoaday 161 return WPTERR_NODATA;
434 werner 36 }
435     if (pgptype & PGP_DASH_ESCAPED) {
436 twoaday 248 id = msg_box (dlg, _("The key you want to import is dash escaped.\n"
437 werner 36 "Do you want to extract the key?"),
438     _("Key Manager"), MB_YESNO);
439     if (id == IDYES)
440     extract_dash_escaped_key ();
441     else
442     msg_box (dlg, _("Cannot import dash escaped OpenPGP keys."),
443     _("Key Manager"), MB_INFO);
444     }
445    
446 twoaday 165 memset (&fm_stat, 0, sizeof (fm_stat));
447     fm_stat.opaque = m_strdup ("Clipboard");
448     fm_stat.import.is_clip = 1;
449     has_data = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
450     file_import_dlg_proc, (LPARAM)&fm_stat,
451 twoaday 150 _("Key Import"), IDS_WINPT_IMPORT);
452 twoaday 165 if (!has_data)
453     goto leave;
454    
455 twoaday 260 gpg = new GPGME ();
456     err = gpg->importFromClipboard ();
457 twoaday 165 if (err) {
458     msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
459     goto leave;
460     }
461    
462 twoaday 260 res = gpg->importGetResult ();
463 twoaday 165 print_import_status (res);
464     new_keys = res->considered - res->unchanged;
465     new_sks = res->secret_imported - res->secret_unchanged;
466     if (res->no_user_id > 0) {
467     msg_box (dlg, _("Key without a self signature was dectected!\n"
468     "(This key is NOT usable for encryption, etc)\n"),
469     _("Import"), MB_WARN);
470     }
471    
472     leave:
473 twoaday 260 if (gpg)
474     delete gpg;
475 twoaday 165 free_if_alloc (fm_stat.opaque);
476 twoaday 164 if (r_newkeys)
477     *r_newkeys = new_keys;
478 twoaday 165 if (r_newsks)
479     *r_newsks = new_sks;
480     if (!new_keys || !has_data)
481 twoaday 161 return WPTERR_NODATA;
482 twoaday 165 return (int)err;
483 werner 36 }
484    
485    
486     /* Import a key from the http URL @url. */
487     int
488     km_http_import (HWND dlg, const char *url)
489     {
490     FILE *fp;
491 twoaday 181 wHTTP *hd;
492 twoaday 260 char tmpfile[MAX_PATH+64];
493 werner 36 int rc = 0;
494    
495     if (strncmp (url, "http://", 7)) {
496     log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);
497     return WPTERR_GENERAL;
498     }
499    
500 twoaday 193 get_temp_name (tmpfile, sizeof (tmpfile)-1, "winpt_http.tmp");
501 twoaday 175 fp = fopen (tmpfile, "wb");
502 werner 36 if (!fp) {
503 twoaday 175 log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", tmpfile,
504 twoaday 121 winpt_strerror (WPTERR_FILE_CREAT));
505 werner 36 return WPTERR_FILE_CREAT;
506     }
507    
508 twoaday 181 hd = new wHTTP (url);
509     if (hd->getStatusCode () == HTTP_STAT_200)
510     hd->readData (fp);
511     else {
512     log_box (_("Key Import HTTP"), MB_ERR,
513     _("Could not fetch key from URL: %s"), url);
514 werner 36 rc = WPTERR_GENERAL;
515     }
516 twoaday 181
517     delete hd;
518     fclose (fp);
519     if (!rc)
520     km_file_import (dlg, tmpfile, NULL, NULL);
521 twoaday 175 DeleteFile (tmpfile);
522 werner 36 return rc;
523     }
524    
525    
526 twoaday 165 /* Import a key from the given file @fname, if @fname is
527     NULL use the common 'file open' dialog.
528 werner 36 On success an import statistics dialog is shown. */
529     int
530 twoaday 165 km_file_import (HWND dlg, const char *fname, int *r_newkeys, int *r_newsks)
531 twoaday 260 {
532     gpgme_error_t err;
533 werner 36 gpgme_import_result_t res;
534 twoaday 260 GPGME *gpg;
535     fm_state_s fm_stat;
536 twoaday 165 const char *name;
537 twoaday 150 int no_data = 0;
538 twoaday 165 int new_keys = 0, new_sks = 0;
539    
540     if (!fname) {
541     name = get_fileopen_dlg (dlg, _("Choose Name of the Key File"),
542     NULL, NULL);
543     if (!name)
544     return WPTERR_GENERAL;
545     }
546     else
547     name = fname;
548    
549 werner 36 memset (&fm_stat, 0, sizeof (fm_stat));
550 twoaday 165 fm_stat.opaque = m_strdup (name);
551 werner 36
552     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
553     file_import_dlg_proc, (LPARAM)&fm_stat,
554     _("File Import"), IDS_WINPT_IMPORT);
555     if (fm_stat.cancel == 1) {
556     free_if_alloc (fm_stat.opaque);
557     return WPTERR_GENERAL;
558     }
559    
560 twoaday 260 gpg = new GPGME ();
561     err = gpg->importFromFile (name);
562 werner 36 if (err) {
563 twoaday 260 msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
564     goto leave;
565 werner 36 }
566    
567 twoaday 260 res = gpg->importGetResult ();
568 twoaday 165 if (res->unchanged == res->considered &&
569     res->secret_unchanged == res->secret_imported)
570 twoaday 150 no_data = 1;
571 twoaday 165 new_keys = res->considered - res->unchanged;
572     new_sks = res->secret_imported - res->secret_unchanged;
573 werner 36 if (res->new_revocations == 0 && fm_stat.import.revcert == 1)
574     res->new_revocations = 1;
575     if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)
576     res->secret_imported = 1;
577    
578     print_import_status (res);
579     if (res->no_user_id > 0) {
580     msg_box (dlg, _("Key without a self signature was dectected!\n"
581 twoaday 165 "(This key is NOT usable for encryption, etc)\n"),
582     _("Import"), MB_WARN);
583 werner 36 }
584    
585     leave:
586 twoaday 260 delete gpg;
587 werner 36 free_if_alloc (fm_stat.opaque);
588 twoaday 165 if (r_newkeys)
589     *r_newkeys = new_keys;
590     if (r_newsks)
591     *r_newsks = new_sks;
592 twoaday 150 if (no_data)
593 twoaday 161 return WPTERR_NODATA;
594 werner 36 return (int)err;
595     }
596    
597    
598 twoaday 166 /* Import all dropped files. */
599     int
600     km_dropped_file_import (HWND dlg, HDROP hdrop,
601     int *r_newkeys, int *r_newsks)
602     {
603     char name[MAX_PATH+1];
604     UINT n = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
605     UINT i;
606     int newk=0, newsk=0, err=0;
607    
608     for (i=0; i < n; i++) {
609     DragQueryFile (hdrop, i, name, MAX_PATH);
610     err = km_file_import (dlg, name, &newk, &newsk);
611     *r_newkeys = (*r_newkeys) + newk;
612     *r_newsks = (*r_newsks) + newsk;
613     }
614 twoaday 167 DragFinish (hdrop);
615 twoaday 166 return err;
616     }
617    
618    
619 werner 36 /* Mark the keys in @rset as deleted in the keycache. */
620     static void
621     delete_keys_from_cache (gpgme_key_t *rset, size_t n)
622     {
623     gpg_keycache_t pub = keycache_get_ctx (1);
624 twoaday 164 gpg_keycache_t sec = keycache_get_ctx (0);
625     gpgme_key_t sk;
626 werner 36 int i=0;
627    
628 twoaday 164 while (n-- > 0) {
629     if (!get_seckey (rset[i]->subkeys->keyid, &sk))
630     gpg_keycache_delete_key (sec, sk->subkeys->keyid);
631     gpg_keycache_delete_key (pub, rset[i]->subkeys->keyid);
632     i++;
633     }
634 werner 36 }
635    
636    
637 twoaday 179 /* Check that the selected default secret key is still
638     available. If not, delete the entry in gpg.conf. */
639     static void
640     check_exist_default_key (void)
641     {
642     gpgme_key_t sk;
643     char *defkey;
644    
645     defkey = get_gnupg_default_key ();
646     if (defkey && get_seckey (defkey, &sk))
647     set_gnupg_default_key (NULL);
648     free_if_alloc (defkey);
649     }
650    
651    
652 twoaday 248 /* Delete the list view items which match a key ptr
653     inside the @rset array. */
654     static void
655 twoaday 250 lv_del_confirmed_keys (listview_ctrl_t lv, gpgme_key_t *rset, int n_rset)
656 twoaday 248 {
657     winpt_key_s key2;
658     int j, i, n = listview_count_items (lv, 0);
659 twoaday 250
660     for (i = n; i > -1; i--) {
661 twoaday 248 if (listview_get_item_state (lv, i)) {
662     km_get_key (lv, i, &key2);
663 twoaday 250 for (j=0; j < n_rset; j++) {
664     if (rset[j] == key2.ctx) {
665 twoaday 248 listview_del_item (lv, i);
666 twoaday 250 }
667 twoaday 248 }
668     }
669     }
670     }
671    
672    
673 werner 36 /* Delete all selected keys from the list view @lv. */
674     int
675     km_delete_keys (listview_ctrl_t lv, HWND dlg)
676     {
677     gpgme_error_t err;
678     gpgme_ctx_t ctx;
679 twoaday 128 gpgme_key_t *rset;
680 twoaday 207 winpt_key_s key2;
681 twoaday 128 char *p;
682 werner 36 int with_seckey=0, seckey_type=0, confirm=0;
683     int i, rc, n, k_pos=0;
684    
685     if (listview_get_curr_pos (lv) == -1) {
686     msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
687 twoaday 121 return -1;
688 werner 36 }
689    
690     if (listview_count_items (lv, 1) > 8) {
691     i = msg_box (NULL, _("Do you really want to confirm each key?"),
692     _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);
693     if (i == IDCANCEL)
694     return 0;
695     if (i != IDNO)
696     confirm = 1;
697     }
698     else
699     confirm = 1;
700    
701 twoaday 133 /* n = total amount of keys, i is the selected amount. */
702 werner 36 n = listview_count_items (lv, 0);
703 twoaday 133 i = listview_count_items (lv, 1);
704     rset = (gpgme_key_t *)calloc (i+1, sizeof (gpgme_key_t));
705 werner 36 if (!rset)
706     BUG (NULL);
707 twoaday 121 for (i = 0; i < n; i++) {
708 twoaday 212 if (listview_get_item_state(lv, i)) {
709     km_get_key (lv, i, &key2);
710 twoaday 207
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 250 lv_del_confirmed_keys (lv, rset, k_pos);
769 werner 36 delete_keys_from_cache (rset, k_pos);
770 twoaday 248 safe_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 212 winpt_key_s 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 212 km_get_key (lv, id, &key);
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 212 key.keyid, host);
795 twoaday 128 if (id == IDYES)
796 twoaday 212 hkp_send_key (dlg, host, port, key.keyid);
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 255 char *fname, *uid;
811     int pos, n;
812 werner 36
813 twoaday 121 if (listview_count_items (lv, 1) > 1) {
814 twoaday 77 msg_box (dlg, _("Please only select one key."),
815     _("Key Manager"), MB_INFO|MB_OK);
816 werner 36 return WPTERR_GENERAL;
817     }
818 twoaday 77 pos = listview_get_curr_pos (lv);
819     if (pos == -1) {
820     msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
821 werner 36 return WPTERR_GENERAL;
822     }
823 twoaday 205 key = km_get_key_ptr (lv, pos, &c);
824 twoaday 255 uid = m_strdup (c->uids->name);
825     secure_filename (uid, strlen (uid));
826     n = strlen (uid) + 1 + MAX_PATH + 5;
827 twoaday 175 fname = new char[n+1];
828 twoaday 255 get_temp_name (fname, n-5-strlen (uid)-1, uid);
829 twoaday 175 strcat (fname, ".asc");
830     ctx = new GPGME ();
831     ctx->setArmor (true);
832     rc = ctx->exportToFile (key->subkeys->keyid, fname);
833 werner 36 if (rc)
834     msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
835 twoaday 175 else
836 twoaday 128 mapi_send_pubkey (key->subkeys->keyid+8, fname);
837 werner 36
838 twoaday 175 delete ctx;
839 twoaday 121 free_if_alloc (fname);
840 twoaday 255 free_if_alloc (uid);
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 twoaday 255 static int
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 twoaday 255 return err;
881 werner 36 }
882    
883    
884 twoaday 133 /* Refresh the selected keys from the default keyserver. */
885 twoaday 244 int
886 werner 36 km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
887     {
888 twoaday 255 int cnt, id, i;
889     int err = 0;
890 twoaday 133
891     cnt = listview_count_items (lv, 0);
892     if (listview_count_items (lv, 1) == cnt) {
893     id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"),
894 twoaday 121 _("Key Manager"), MB_YESNO);
895 werner 36 if (id == IDNO)
896 twoaday 244 return -1;
897 twoaday 175 if (kserver_check_inet_connection ()) {
898     msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
899     _("Key Manager"), MB_ERR);
900 twoaday 244 return -1;
901 twoaday 175 }
902 werner 36 }
903 twoaday 133 if (listview_count_items (lv, 1) == 1)
904 twoaday 255 err = km_refresh_one_key (lv, dlg, listview_get_curr_pos (lv), 0);
905 werner 36 else {
906 twoaday 133 for (i=0; i < cnt; i++) {
907 werner 36 if (listview_get_item_state (lv, i))
908 twoaday 133 km_refresh_one_key (lv, dlg, i, KM_KS_REFRESH);
909 werner 36 }
910     }
911 twoaday 255 return err;
912 twoaday 121 }
913 werner 36
914    
915     void
916     km_set_clip_info (const char *uid)
917     {
918     char buf[256];
919    
920 twoaday 129 key_get_clip_info (uid, buf, sizeof (buf)-1);
921 werner 36 set_clip_text (NULL, buf, strlen (buf));
922 twoaday 121 }
923 werner 36
924    
925    
926     /* Return TRUE if the key in the list @lv at pos @pos is an
927     old version 3 key. */
928     int
929     km_key_is_v3 (listview_ctrl_t lv, int pos)
930     {
931     gpgme_key_t pk;
932    
933 twoaday 205 pk = km_get_key_ptr (lv, pos, NULL);
934 werner 36 if (strlen (pk->subkeys->fpr) == 32 &&
935     pk->subkeys->pubkey_algo == GPGME_PK_RSA)
936     return -1;
937     return 0;
938     }
939    
940    
941     /* Set trust of selected key in @lv (at @pos) to ultimate. */
942     int
943     km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
944     {
945 twoaday 128 gpgme_error_t err;
946     gpgme_key_t key;
947 werner 36 GpgKeyEdit *ke;
948    
949 twoaday 205 key = km_get_key_ptr (lv, pos, NULL);
950 twoaday 128 ke = new GpgKeyEdit (key->subkeys->keyid);
951 werner 36 if (!ke)
952     BUG (0);
953    
954     err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
955     if (err)
956     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
957     else
958     show_msg (dlg, 1500, _("GnuPG Status: Finished"));
959    
960     delete ke;
961     return (int)err;
962     }
963    
964    
965 twoaday 241 /* Provide a search dialog and try to find and select
966     the key which matches the entered pattern. */
967 werner 36 void
968     km_find_key (HWND dlg, listview_ctrl_t lv)
969     {
970     int oldpos = listview_get_curr_pos (lv);
971     int n;
972     char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
973 twoaday 241
974     if (!name)
975 werner 36 return;
976     if (oldpos < 0)
977     oldpos = 0;
978 twoaday 241 n = listview_find (lv, name, 1);
979 werner 36 if (n != -1) {
980     listview_select_one (lv, n);
981     listview_scroll (lv, oldpos, n);
982     }
983     else {
984     const char *s = _("String pattern \"%s\" not found.");
985     char *p = new char[strlen (s) + strlen (name) + 2];
986     if (!p)
987     BUG (0);
988     sprintf (p, s, name);
989     msg_box (dlg, p, _("Key Manager"), MB_INFO);
990     free_if_alloc (p);
991     }
992     free_if_alloc (name);
993     }
994 twoaday 129
995    
996     /* Return a user-friendly name for a key derrived from
997     name. If @is_secret is 1, a secret key name will be generated. */
998     char*
999     km_gen_export_filename (const char *keyid, int is_secret)
1000     {
1001 twoaday 205 winpt_key_s key;
1002     char *p;
1003 twoaday 129
1004 twoaday 205 memset (&key, 0, sizeof (key));
1005     if (winpt_get_pubkey (keyid, &key))
1006 twoaday 129 return m_strdup (keyid);
1007 twoaday 205
1008     p = new char[strlen (key.ext->uids->name) + 8 + 16];
1009 twoaday 129 if (!p)
1010     BUG (0);
1011 twoaday 205 sprintf (p, "%s%s.asc", key.ext->uids->name, is_secret? "_sec" : "");
1012 twoaday 244 secure_filename (p, strlen (p));
1013 twoaday 129 return p;
1014     }
1015 twoaday 200
1016    
1017     /* Retrieve the GPGME pointer from the selected list view
1018     item and return the WinPT specific key context. */
1019     int
1020     km_get_key (listview_ctrl_t lv, int pos, winpt_key_t k)
1021     {
1022 twoaday 207 struct keycache_s *c;
1023 twoaday 200 gpgme_key_t key;
1024    
1025     if (pos == -1)
1026     return -1;
1027 twoaday 207 key = km_get_key_ptr (lv, pos, &c);
1028 twoaday 200 memset (k, 0, sizeof (*k));
1029     strncpy (k->tmp_keyid, key->subkeys->keyid+8, 8);
1030     k->keyid = k->tmp_keyid;
1031     k->is_protected = km_check_if_protected (lv, pos);
1032     k->key_pair = km_check_for_seckey (lv, pos, NULL);
1033     k->is_v3 = km_key_is_v3 (lv, pos);
1034     k->flags = km_get_key_status (lv, pos);
1035     k->ctx = key;
1036 twoaday 207 k->ext = c;
1037     k->uid = c->uids->uid;
1038 twoaday 200 return 0;
1039     }
1040    
1041    
1042     /* Show details of the revocation of the key @k. */
1043     void
1044     km_key_show_revoc_info (winpt_key_t k)
1045     {
1046     const char *desc;
1047     char *val=NULL, *p;
1048     int len, reason;
1049     const char *reasons[] = {
1050     _("0. No reason specified"),
1051     _("1. Key has been compromised"),
1052     _("2. Key is superseded"),
1053     _("3. Key is no longer used"),
1054     NULL
1055     };
1056    
1057     /* spk:29:1:19:%00This key is kaputt */
1058     gpg_find_key_subpacket (k->keyid, 29, &val);
1059     if (!val || strlen (val) < 3) {
1060     safe_free (val);
1061     return;
1062     }
1063    
1064     len = atoi (val+9);
1065     p = strchr (val+9, ':');
1066     assert (p);
1067     p++;
1068     reason = atoi (p+1);
1069     if (strlen (p+1) > 0)
1070     desc = p+3;
1071     else
1072     desc = "none";
1073     log_box (_("Key Manager"), MB_OK,
1074     "Key revocation info for '%s':\n"
1075     "Reason for revocation: %s\n"
1076     "Description: %s\n",
1077     k->ctx->uids->name, reasons[reason % 4]+3,
1078     desc);
1079     safe_free (val);
1080     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26