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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26