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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 278 - (hide annotations)
Mon Jan 15 22:02:04 2007 UTC (18 years, 1 month ago) by twoaday
File size: 27237 byte(s)
See ChangeLog.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26