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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (hide annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 27305 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26