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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 262 - (hide annotations)
Sat Sep 30 10:24:34 2006 UTC (18 years, 5 months ago) by twoaday
File size: 27590 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 twoaday 262 key_get_clip_info (rset[0]->subkeys->keyid, buf, DIM (buf)-1);
301 werner 36 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 twoaday 262 int rc = 0, err = 0;
494 werner 36
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 262 get_temp_name (tmpfile, DIM (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 262 op_begin ();
509 twoaday 181 hd = new wHTTP (url);
510     if (hd->getStatusCode () == HTTP_STAT_200)
511 twoaday 262 err = hd->readData (fp);
512     else
513     err = WPTERR_KEYSERVER_NOTFOUND;
514     op_end ();
515     if (err) {
516     log_box (_("HTTP Key Import"), MB_ERR,
517 twoaday 181 _("Could not fetch key from URL: %s"), url);
518 werner 36 rc = WPTERR_GENERAL;
519     }
520 twoaday 181
521     delete hd;
522     fclose (fp);
523     if (!rc)
524     km_file_import (dlg, tmpfile, NULL, NULL);
525 twoaday 175 DeleteFile (tmpfile);
526 werner 36 return rc;
527     }
528    
529    
530 twoaday 165 /* Import a key from the given file @fname, if @fname is
531     NULL use the common 'file open' dialog.
532 werner 36 On success an import statistics dialog is shown. */
533     int
534 twoaday 165 km_file_import (HWND dlg, const char *fname, int *r_newkeys, int *r_newsks)
535 twoaday 260 {
536     gpgme_error_t err;
537 werner 36 gpgme_import_result_t res;
538 twoaday 260 GPGME *gpg;
539     fm_state_s fm_stat;
540 twoaday 165 const char *name;
541 twoaday 150 int no_data = 0;
542 twoaday 165 int new_keys = 0, new_sks = 0;
543    
544     if (!fname) {
545     name = get_fileopen_dlg (dlg, _("Choose Name of the Key File"),
546     NULL, NULL);
547     if (!name)
548     return WPTERR_GENERAL;
549     }
550     else
551     name = fname;
552    
553 werner 36 memset (&fm_stat, 0, sizeof (fm_stat));
554 twoaday 165 fm_stat.opaque = m_strdup (name);
555 werner 36
556     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
557     file_import_dlg_proc, (LPARAM)&fm_stat,
558     _("File Import"), IDS_WINPT_IMPORT);
559     if (fm_stat.cancel == 1) {
560     free_if_alloc (fm_stat.opaque);
561     return WPTERR_GENERAL;
562     }
563    
564 twoaday 260 gpg = new GPGME ();
565     err = gpg->importFromFile (name);
566 werner 36 if (err) {
567 twoaday 260 msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
568     goto leave;
569 werner 36 }
570    
571 twoaday 260 res = gpg->importGetResult ();
572 twoaday 165 if (res->unchanged == res->considered &&
573     res->secret_unchanged == res->secret_imported)
574 twoaday 150 no_data = 1;
575 twoaday 165 new_keys = res->considered - res->unchanged;
576     new_sks = res->secret_imported - res->secret_unchanged;
577 werner 36 if (res->new_revocations == 0 && fm_stat.import.revcert == 1)
578     res->new_revocations = 1;
579     if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)
580     res->secret_imported = 1;
581    
582     print_import_status (res);
583     if (res->no_user_id > 0) {
584     msg_box (dlg, _("Key without a self signature was dectected!\n"
585 twoaday 165 "(This key is NOT usable for encryption, etc)\n"),
586     _("Import"), MB_WARN);
587 werner 36 }
588    
589     leave:
590 twoaday 260 delete gpg;
591 werner 36 free_if_alloc (fm_stat.opaque);
592 twoaday 165 if (r_newkeys)
593     *r_newkeys = new_keys;
594     if (r_newsks)
595     *r_newsks = new_sks;
596 twoaday 150 if (no_data)
597 twoaday 161 return WPTERR_NODATA;
598 werner 36 return (int)err;
599     }
600    
601    
602 twoaday 166 /* Import all dropped files. */
603     int
604     km_dropped_file_import (HWND dlg, HDROP hdrop,
605     int *r_newkeys, int *r_newsks)
606     {
607     char name[MAX_PATH+1];
608     UINT n = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
609     UINT i;
610     int newk=0, newsk=0, err=0;
611    
612     for (i=0; i < n; i++) {
613     DragQueryFile (hdrop, i, name, MAX_PATH);
614     err = km_file_import (dlg, name, &newk, &newsk);
615     *r_newkeys = (*r_newkeys) + newk;
616     *r_newsks = (*r_newsks) + newsk;
617     }
618 twoaday 167 DragFinish (hdrop);
619 twoaday 166 return err;
620     }
621    
622    
623 werner 36 /* Mark the keys in @rset as deleted in the keycache. */
624     static void
625     delete_keys_from_cache (gpgme_key_t *rset, size_t n)
626     {
627     gpg_keycache_t pub = keycache_get_ctx (1);
628 twoaday 164 gpg_keycache_t sec = keycache_get_ctx (0);
629     gpgme_key_t sk;
630 werner 36 int i=0;
631    
632 twoaday 164 while (n-- > 0) {
633     if (!get_seckey (rset[i]->subkeys->keyid, &sk))
634     gpg_keycache_delete_key (sec, sk->subkeys->keyid);
635     gpg_keycache_delete_key (pub, rset[i]->subkeys->keyid);
636     i++;
637     }
638 werner 36 }
639    
640    
641 twoaday 179 /* Check that the selected default secret key is still
642     available. If not, delete the entry in gpg.conf. */
643     static void
644     check_exist_default_key (void)
645     {
646     gpgme_key_t sk;
647     char *defkey;
648    
649     defkey = get_gnupg_default_key ();
650     if (defkey && get_seckey (defkey, &sk))
651     set_gnupg_default_key (NULL);
652     free_if_alloc (defkey);
653     }
654    
655    
656 twoaday 248 /* Delete the list view items which match a key ptr
657     inside the @rset array. */
658     static void
659 twoaday 250 lv_del_confirmed_keys (listview_ctrl_t lv, gpgme_key_t *rset, int n_rset)
660 twoaday 248 {
661     winpt_key_s key2;
662     int j, i, n = listview_count_items (lv, 0);
663 twoaday 250
664     for (i = n; i > -1; i--) {
665 twoaday 248 if (listview_get_item_state (lv, i)) {
666     km_get_key (lv, i, &key2);
667 twoaday 250 for (j=0; j < n_rset; j++) {
668     if (rset[j] == key2.ctx) {
669 twoaday 248 listview_del_item (lv, i);
670 twoaday 250 }
671 twoaday 248 }
672     }
673     }
674     }
675    
676    
677 werner 36 /* Delete all selected keys from the list view @lv. */
678     int
679     km_delete_keys (listview_ctrl_t lv, HWND dlg)
680     {
681     gpgme_error_t err;
682     gpgme_ctx_t ctx;
683 twoaday 128 gpgme_key_t *rset;
684 twoaday 207 winpt_key_s key2;
685 twoaday 128 char *p;
686 werner 36 int with_seckey=0, seckey_type=0, confirm=0;
687     int i, rc, n, k_pos=0;
688    
689     if (listview_get_curr_pos (lv) == -1) {
690     msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
691 twoaday 121 return -1;
692 werner 36 }
693    
694     if (listview_count_items (lv, 1) > 8) {
695     i = msg_box (NULL, _("Do you really want to confirm each key?"),
696     _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);
697     if (i == IDCANCEL)
698     return 0;
699     if (i != IDNO)
700     confirm = 1;
701     }
702     else
703     confirm = 1;
704    
705 twoaday 133 /* n = total amount of keys, i is the selected amount. */
706 werner 36 n = listview_count_items (lv, 0);
707 twoaday 133 i = listview_count_items (lv, 1);
708     rset = (gpgme_key_t *)calloc (i+1, sizeof (gpgme_key_t));
709 werner 36 if (!rset)
710     BUG (NULL);
711 twoaday 121 for (i = 0; i < n; i++) {
712 twoaday 212 if (listview_get_item_state(lv, i)) {
713     km_get_key (lv, i, &key2);
714 twoaday 207
715 werner 36 seckey_type = km_check_for_seckey (lv, i, NULL);
716     if (confirm && !seckey_type) {
717 twoaday 207 p = km_key_get_info (&key2, 0);
718 twoaday 133 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
719 werner 36 _("Do you really want to delete this key?\n\n"
720 twoaday 128 "%s"), p);
721     if (rc == IDYES)
722 twoaday 207 rset[k_pos++] = key2.ctx;
723 twoaday 128 free_if_alloc (p);
724 werner 36 }
725     else if (confirm) {
726 twoaday 207 p = km_key_get_info (&key2, 1);
727 twoaday 121 rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
728 werner 36 _("Do you really want to delete this KEY PAIR?\n\n"
729     "Please remember that you are not able to decrypt\n"
730     "messages you stored with this key any longer.\n"
731     "\n"
732 twoaday 128 "%s"), p);
733 twoaday 133 if (rc == IDYES) {
734 werner 36 if (seckey_type == 2)
735 twoaday 121 msg_box (dlg, _("The actual secret key is stored on a smartcard.\n"
736 werner 36 "Only the public key and the secret key \n"
737 twoaday 121 "placeholder will be deleted.\n"),
738     _("Key Manager"), MB_OK);
739 twoaday 207 rset[k_pos++] = key2.ctx;
740 werner 36 }
741     with_seckey = 1;
742 twoaday 128 free_if_alloc (p);
743 werner 36 }
744     else {
745     with_seckey = 1;
746 twoaday 207 rset[k_pos++] = key2.ctx;
747 werner 36 }
748     }
749     }
750    
751     if (k_pos == 0) {
752     free (rset);
753     return 0;
754     }
755    
756     err = gpgme_new (&ctx);
757     if (err)
758     BUG (NULL);
759 twoaday 128 n = k_pos;
760 twoaday 130 op_begin ();
761 werner 36 for (i=0; i < k_pos; i++) {
762     err = gpgme_op_delete (ctx, rset[i], with_seckey);
763     if (err)
764     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
765     else
766     n--;
767     }
768 twoaday 130 op_end ();
769 werner 36 if (n == 0)
770 twoaday 179 show_msg (dlg, 1500, _("GnuPG Status: Finished"));
771 werner 36 gpgme_release (ctx);
772 twoaday 250 lv_del_confirmed_keys (lv, rset, k_pos);
773 werner 36 delete_keys_from_cache (rset, k_pos);
774 twoaday 248 safe_free (rset);
775 twoaday 179 if (with_seckey)
776     check_exist_default_key ();
777 werner 36 return (int)err;
778     }
779    
780    
781 twoaday 121 /* Send the select key in @lv to the keyserver @host:@port. */
782 werner 36 int
783 twoaday 181 km_send_to_keyserver (listview_ctrl_t lv, HWND dlg,
784     const char *host, WORD port)
785 werner 36 {
786 twoaday 212 winpt_key_s key;
787 werner 36 int id;
788    
789 twoaday 121 id = listview_get_curr_pos (lv);
790     if (id == -1) {
791 werner 36 msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
792     return WPTERR_GENERAL;
793     }
794    
795 twoaday 212 km_get_key (lv, id, &key);
796 werner 36 id = log_box (_("Key Manager"), MB_YESNO,
797 twoaday 195 _("Do you really want to send '0x%s' to keyserver %s?"),
798 twoaday 212 key.keyid, host);
799 twoaday 128 if (id == IDYES)
800 twoaday 212 hkp_send_key (dlg, host, port, key.keyid);
801 werner 36
802     return 0;
803 twoaday 121 }
804 werner 36
805    
806 twoaday 77 /* Send the selected key in @lv via MAPI to a mail recipient. */
807 werner 36 int
808 twoaday 77 km_send_to_mail_recipient (listview_ctrl_t lv, HWND dlg)
809 werner 36 {
810     gpgme_key_t key;
811     gpgme_error_t rc;
812 twoaday 175 GPGME *ctx;
813 twoaday 205 struct keycache_s *c;
814 twoaday 255 char *fname, *uid;
815     int pos, n;
816 werner 36
817 twoaday 121 if (listview_count_items (lv, 1) > 1) {
818 twoaday 77 msg_box (dlg, _("Please only select one key."),
819     _("Key Manager"), MB_INFO|MB_OK);
820 werner 36 return WPTERR_GENERAL;
821     }
822 twoaday 77 pos = listview_get_curr_pos (lv);
823     if (pos == -1) {
824     msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
825 werner 36 return WPTERR_GENERAL;
826     }
827 twoaday 205 key = km_get_key_ptr (lv, pos, &c);
828 twoaday 255 uid = m_strdup (c->uids->name);
829     secure_filename (uid, strlen (uid));
830     n = strlen (uid) + 1 + MAX_PATH + 5;
831 twoaday 175 fname = new char[n+1];
832 twoaday 255 get_temp_name (fname, n-5-strlen (uid)-1, uid);
833 twoaday 175 strcat (fname, ".asc");
834     ctx = new GPGME ();
835     ctx->setArmor (true);
836     rc = ctx->exportToFile (key->subkeys->keyid, fname);
837 werner 36 if (rc)
838     msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
839 twoaday 175 else
840 twoaday 128 mapi_send_pubkey (key->subkeys->keyid+8, fname);
841 werner 36
842 twoaday 175 delete ctx;
843 twoaday 121 free_if_alloc (fname);
844 twoaday 255 free_if_alloc (uid);
845 werner 36 return rc;
846     }
847    
848    
849 twoaday 181 /* Refresh the selected key in the listview @lv at position @pos.
850     Legal flags are 0 = single key. */
851 twoaday 255 static int
852 twoaday 133 km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos, int flags)
853 werner 36 {
854 twoaday 181 winpt_key_s pk;
855 twoaday 128 gpgme_key_t key;
856 twoaday 181 const char *pref_kserv = default_keyserver;
857 twoaday 214 unsigned short pref_kserv_port = default_keyserver_port;
858 twoaday 165 char keyid[16+1];
859     int idx, err = 0;
860 twoaday 181
861 werner 36 if (pos != 0)
862     idx = pos;
863     else
864     idx = listview_get_curr_pos (lv);
865 twoaday 121 if (idx != -1) {
866 twoaday 205 key = km_get_key_ptr (lv, idx, NULL);
867 twoaday 214
868 twoaday 181 /* In single refresh mode, try to use the users preferred keyserver. */
869     if (flags == 0 &&
870     !winpt_get_pubkey (key->subkeys->keyid+8, &pk) &&
871 twoaday 214 !gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFKSERV, 0) &&
872     pk.ext->pref_keyserver &&
873     !strstr (pk.ext->pref_keyserver, "ldap://")) {
874 twoaday 181 pref_kserv = pk.ext->pref_keyserver;
875 twoaday 214 pref_kserv_port = pk.ext->pref_keyserver_port;
876     }
877 twoaday 262 _snprintf (keyid, DIM (keyid)-1, "%s", key->subkeys->keyid+8);
878 twoaday 214 err = hkp_recv_key (dlg, pref_kserv, pref_kserv_port,
879 twoaday 165 keyid, 0, flags);
880     /* if we receive just a single key (no refresh mode), update it. */
881     if (!flags && !err)
882     keycache_update (0, keyid);
883 werner 36 }
884 twoaday 255 return err;
885 werner 36 }
886    
887    
888 twoaday 133 /* Refresh the selected keys from the default keyserver. */
889 twoaday 244 int
890 werner 36 km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
891     {
892 twoaday 255 int cnt, id, i;
893     int err = 0;
894 twoaday 133
895     cnt = listview_count_items (lv, 0);
896     if (listview_count_items (lv, 1) == cnt) {
897     id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"),
898 twoaday 121 _("Key Manager"), MB_YESNO);
899 werner 36 if (id == IDNO)
900 twoaday 244 return -1;
901 twoaday 175 if (kserver_check_inet_connection ()) {
902     msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
903     _("Key Manager"), MB_ERR);
904 twoaday 244 return -1;
905 twoaday 175 }
906 werner 36 }
907 twoaday 133 if (listview_count_items (lv, 1) == 1)
908 twoaday 255 err = km_refresh_one_key (lv, dlg, listview_get_curr_pos (lv), 0);
909 werner 36 else {
910 twoaday 133 for (i=0; i < cnt; i++) {
911 werner 36 if (listview_get_item_state (lv, i))
912 twoaday 133 km_refresh_one_key (lv, dlg, i, KM_KS_REFRESH);
913 werner 36 }
914     }
915 twoaday 255 return err;
916 twoaday 121 }
917 werner 36
918    
919     void
920     km_set_clip_info (const char *uid)
921     {
922     char buf[256];
923    
924 twoaday 262 key_get_clip_info (uid, buf, DIM (buf)-1);
925 werner 36 set_clip_text (NULL, buf, strlen (buf));
926 twoaday 121 }
927 werner 36
928    
929    
930     /* Return TRUE if the key in the list @lv at pos @pos is an
931     old version 3 key. */
932     int
933     km_key_is_v3 (listview_ctrl_t lv, int pos)
934     {
935     gpgme_key_t pk;
936    
937 twoaday 205 pk = km_get_key_ptr (lv, pos, NULL);
938 werner 36 if (strlen (pk->subkeys->fpr) == 32 &&
939     pk->subkeys->pubkey_algo == GPGME_PK_RSA)
940     return -1;
941     return 0;
942     }
943    
944    
945     /* Set trust of selected key in @lv (at @pos) to ultimate. */
946     int
947     km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
948     {
949 twoaday 128 gpgme_error_t err;
950     gpgme_key_t key;
951 werner 36 GpgKeyEdit *ke;
952    
953 twoaday 205 key = km_get_key_ptr (lv, pos, NULL);
954 twoaday 128 ke = new GpgKeyEdit (key->subkeys->keyid);
955 werner 36 if (!ke)
956     BUG (0);
957    
958     err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
959     if (err)
960     msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
961     else
962     show_msg (dlg, 1500, _("GnuPG Status: Finished"));
963    
964     delete ke;
965     return (int)err;
966     }
967    
968    
969 twoaday 241 /* Provide a search dialog and try to find and select
970     the key which matches the entered pattern. */
971 werner 36 void
972     km_find_key (HWND dlg, listview_ctrl_t lv)
973     {
974     int oldpos = listview_get_curr_pos (lv);
975     int n;
976     char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
977 twoaday 241
978     if (!name)
979 werner 36 return;
980     if (oldpos < 0)
981     oldpos = 0;
982 twoaday 241 n = listview_find (lv, name, 1);
983 werner 36 if (n != -1) {
984     listview_select_one (lv, n);
985     listview_scroll (lv, oldpos, n);
986     }
987     else {
988     const char *s = _("String pattern \"%s\" not found.");
989     char *p = new char[strlen (s) + strlen (name) + 2];
990     if (!p)
991     BUG (0);
992     sprintf (p, s, name);
993     msg_box (dlg, p, _("Key Manager"), MB_INFO);
994     free_if_alloc (p);
995     }
996     free_if_alloc (name);
997     }
998 twoaday 129
999    
1000     /* Return a user-friendly name for a key derrived from
1001     name. If @is_secret is 1, a secret key name will be generated. */
1002     char*
1003     km_gen_export_filename (const char *keyid, int is_secret)
1004     {
1005 twoaday 205 winpt_key_s key;
1006     char *p;
1007 twoaday 129
1008 twoaday 205 memset (&key, 0, sizeof (key));
1009     if (winpt_get_pubkey (keyid, &key))
1010 twoaday 129 return m_strdup (keyid);
1011 twoaday 205
1012     p = new char[strlen (key.ext->uids->name) + 8 + 16];
1013 twoaday 129 if (!p)
1014     BUG (0);
1015 twoaday 205 sprintf (p, "%s%s.asc", key.ext->uids->name, is_secret? "_sec" : "");
1016 twoaday 244 secure_filename (p, strlen (p));
1017 twoaday 129 return p;
1018     }
1019 twoaday 200
1020    
1021     /* Retrieve the GPGME pointer from the selected list view
1022     item and return the WinPT specific key context. */
1023     int
1024     km_get_key (listview_ctrl_t lv, int pos, winpt_key_t k)
1025     {
1026 twoaday 207 struct keycache_s *c;
1027 twoaday 200 gpgme_key_t key;
1028    
1029     if (pos == -1)
1030     return -1;
1031 twoaday 207 key = km_get_key_ptr (lv, pos, &c);
1032 twoaday 200 memset (k, 0, sizeof (*k));
1033     strncpy (k->tmp_keyid, key->subkeys->keyid+8, 8);
1034     k->keyid = k->tmp_keyid;
1035     k->is_protected = km_check_if_protected (lv, pos);
1036     k->key_pair = km_check_for_seckey (lv, pos, NULL);
1037     k->is_v3 = km_key_is_v3 (lv, pos);
1038     k->flags = km_get_key_status (lv, pos);
1039     k->ctx = key;
1040 twoaday 207 k->ext = c;
1041     k->uid = c->uids->uid;
1042 twoaday 200 return 0;
1043     }
1044    
1045    
1046     /* Show details of the revocation of the key @k. */
1047     void
1048     km_key_show_revoc_info (winpt_key_t k)
1049     {
1050     const char *desc;
1051     char *val=NULL, *p;
1052     int len, reason;
1053     const char *reasons[] = {
1054     _("0. No reason specified"),
1055     _("1. Key has been compromised"),
1056     _("2. Key is superseded"),
1057     _("3. Key is no longer used"),
1058     NULL
1059     };
1060    
1061     /* spk:29:1:19:%00This key is kaputt */
1062     gpg_find_key_subpacket (k->keyid, 29, &val);
1063     if (!val || strlen (val) < 3) {
1064     safe_free (val);
1065     return;
1066     }
1067    
1068     len = atoi (val+9);
1069     p = strchr (val+9, ':');
1070     assert (p);
1071     p++;
1072     reason = atoi (p+1);
1073     if (strlen (p+1) > 0)
1074     desc = p+3;
1075     else
1076     desc = "none";
1077     log_box (_("Key Manager"), MB_OK,
1078     "Key revocation info for '%s':\n"
1079     "Reason for revocation: %s\n"
1080     "Description: %s\n",
1081     k->ctx->uids->name, reasons[reason % 4]+3,
1082     desc);
1083     safe_free (val);
1084     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26