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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 303 - (hide annotations)
Wed Mar 21 10:48:02 2007 UTC (17 years, 11 months ago) by twoaday
File size: 27064 byte(s)
bug fix for the export problem


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26