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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 304 - (hide annotations)
Wed Mar 21 10:59:31 2007 UTC (17 years, 11 months ago) by twoaday
File size: 26964 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26