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

Annotation of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 301 - (hide annotations)
Wed Mar 21 10:25:48 2007 UTC (17 years, 11 months ago) by twoaday
File size: 27024 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26