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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 181 - (show annotations)
Tue Mar 14 11:01:22 2006 UTC (18 years, 11 months ago) by twoaday
File size: 26663 byte(s)
2006-03-12  Timo Schulz  <ts@g10code.de>
 
        * wptGPG.cpp (gnupg_load_config): Search for 'ask-cert-expire'.
        * wptKeyPropsDlg.cpp (display_key_info): Automatically update
        sym algorithm preferences if needed.
        * wptKeysignDlg.cpp (date_is_today): New.
        (keysign_dlg_proc): Only allow to set cert expire date if
        the option was found.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Allow to set
        'ask-cert-expire'.
         


1 /* wptKeylist.cpp - Keylist element
2 * Copyright (C) 2001-2006 Timo Schulz
3 * Copyright (C) 2004 Andreas Jobs
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 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <commctrl.h>
28 #include <time.h>
29
30 #include "wptCommonCtl.h"
31 #include "wptTypes.h"
32 #include "wptGPG.h"
33 #include "wptKeylist.h"
34 #include "wptKeyManager.h"
35 #include "wptW32API.h"
36 #include "wptNLS.h"
37 #include "wptErrors.h"
38 #include "wptUTF8.h"
39 #include "wptRegistry.h"
40 #include "wptContext.h"
41 #include "wptVersion.h"
42 #include "resource.h"
43
44 #define key_is_useable(key) (!(key)->revoked && !(key)->expired && !(key)->disabled)
45
46 struct key_array_s {
47 char keyid[32];
48 int checked;
49 };
50
51 static int find_secret_key (gpgme_key_t key);
52
53
54 static key_array_s*
55 key_array_new (int items)
56 {
57 key_array_s *ka;
58 int j;
59
60 if (items == 0)
61 return NULL;
62 ka = new key_array_s[items + 1];
63 if (!ka)
64 BUG (NULL);
65 for (j = 0; j < items; j++)
66 ka[j].checked = 0;
67 return ka;
68 }
69
70
71 static void
72 key_array_release (key_array_s *ka)
73 {
74 free_if_alloc (ka);
75 }
76
77
78 /* Check if the keyid @keyid is in the key array @ka.
79 Return value: 1 if it exists, 0 otherwise. */
80 static int
81 key_array_search (key_array_s *ka, int items, const char *keyid)
82 {
83 int j;
84
85 for (j = 0; j < items; j++) {
86 if (!strcmp (keyid, ka[j].keyid ))
87 return 1;
88 }
89 return 0;
90 }
91
92
93 gpgme_user_id_t
94 get_nth_userid (gpgme_key_t key, int idx)
95 {
96 gpgme_user_id_t t;
97
98 if (!key->uids)
99 return NULL;
100 t = key->uids;
101 while (idx-- && t->next)
102 t = t->next;
103 return t;
104 }
105
106
107 int
108 count_userids (gpgme_key_t key)
109 {
110 gpgme_user_id_t u;
111 int n = 1;
112
113 u = key->uids;
114 if (!u)
115 return 0;
116 while (u->next) {
117 u = u->next;
118 n++;
119 }
120 return n;
121 }
122
123
124 gpgme_subkey_t
125 get_nth_key (gpgme_key_t key, int idx)
126 {
127 gpgme_subkey_t t;
128
129 if (!key->subkeys)
130 return NULL;
131 t = key->subkeys;
132 while (idx-- && t->next)
133 t = t->next;
134 return t;
135 }
136
137
138 int
139 count_subkeys (gpgme_key_t key)
140 {
141 gpgme_subkey_t k;
142 int n = 1;
143
144 k = key->subkeys;
145 if (!k)
146 return 0;
147 while (k->next) {
148 k = k->next;
149 n++;
150 }
151 return n;
152 }
153
154
155 /* Return the self signature of the key @keyid.
156 If first is set, the first self sig will be returned. */
157 gpgme_key_sig_t
158 get_selfsig (gpgme_user_id_t uid, const char *keyid, int first)
159 {
160 gpgme_key_sig_t s, self_sig=NULL;
161 long timestamp=0;
162 int off = 0;
163
164 if (strlen (keyid) == 8)
165 off = 8;
166
167 for (s = uid->signatures; s; s = s->next) {
168 if (!strcmp (s->keyid+off, keyid) && s->timestamp > timestamp) {
169 self_sig = s;
170 timestamp = s->timestamp;
171 if (first)
172 break;
173 }
174 }
175 return self_sig;
176 }
177
178
179
180 const char*
181 get_key_algo (gpgme_key_t key, int keyidx)
182 {
183 static char algo_id[128];
184 gpgme_subkey_t k;
185 char alg[32];
186 const char *subalg;
187 int n=0;
188
189 if (keyidx > 0) {
190 k = get_nth_key (key, keyidx-1);
191 subalg = get_key_pubalgo (k->pubkey_algo);
192 _snprintf (algo_id, DIM (algo_id)-1, "%s", subalg);
193 return algo_id;
194 }
195 strcpy (alg, get_key_pubalgo (key->subkeys->pubkey_algo));
196 n = count_subkeys (key);
197 if (n > 1) {
198 k = get_nth_key (key, n-1);
199 subalg = get_key_pubalgo (k->pubkey_algo);
200 _snprintf (algo_id, DIM (algo_id)-1, "%s/%s", alg, subalg);
201 return algo_id;
202 }
203 return get_key_pubalgo (key->subkeys->pubkey_algo);
204 }
205
206
207 const char*
208 get_key_created (long timestamp)
209 {
210 static char timebuf[128];
211 struct tm *warp;
212 const char *dat;
213
214 if (timestamp < 1)
215 return "????" "-??" "-??";
216 dat = get_locale_date (timestamp, timebuf, sizeof (timebuf)-1);
217 if (dat)
218 return dat;
219 warp = localtime (&timestamp);
220 _snprintf (timebuf, sizeof timebuf - 1, "%04d-%02d-%02d",
221 warp->tm_year + 1900, warp->tm_mon + 1, warp->tm_mday);
222 return timebuf;
223 }
224
225
226 /* Return a string presentation of the time @timestamp. */
227 const char*
228 get_key_expire_date (long timestamp)
229 {
230 static char timebuf[64];
231 struct tm *warp;
232 const char *dat;
233
234 if (timestamp == 0)
235 return _("Never");
236 dat = get_locale_date (timestamp, timebuf, sizeof (timebuf)-1);
237 if (dat)
238 return dat;
239 warp = localtime (&timestamp);
240 _snprintf (timebuf, sizeof timebuf -1, "%04d-%02d-%02d",
241 warp->tm_year + 1900, warp->tm_mon + 1, warp->tm_mday);
242 return timebuf;
243 }
244
245
246 const char*
247 get_key_type (gpgme_key_t key)
248 {
249 int type = find_secret_key (key);
250
251 if (type == 1)
252 return _("Key Pair");
253 else if (type == 2)
254 return _("Key Pair (Card)");
255 return _("Public Key");
256 }
257
258
259 const char*
260 get_key_size (gpgme_key_t key, int keyidx)
261 {
262 static char size_id[64];
263 gpgme_subkey_t k;
264 int n, size_main, size_sub;
265
266 if (keyidx > 0) {
267 k = get_nth_key (key, keyidx-1);
268 size_main = k->length;
269 _snprintf (size_id, DIM (size_id)-1, "%d", size_main);
270 return size_id;
271 }
272 size_main = key->subkeys->length;
273 n = count_subkeys (key);
274 if (n > 1) {
275 k = get_nth_key (key, n-1);
276 size_sub = k->length;
277 _snprintf (size_id, sizeof (size_id) - 1, "%d/%d",
278 size_main, size_sub);
279 return size_id;
280 }
281 _snprintf( size_id, sizeof (size_id) - 1, "%d", size_main );
282 return size_id;
283 }
284
285
286 const char*
287 get_key_pubalgo2 (gpgme_pubkey_algo_t alg)
288 {
289 switch (alg) {
290 case GPGME_PK_DSA: return "D";
291 case GPGME_PK_RSA: return "R";
292 case GPGME_PK_ELG: return "G";
293 default: return "?";
294 }
295 return "?";
296 }
297
298
299 const char*
300 get_key_pubalgo (gpgme_pubkey_algo_t alg)
301 {
302 switch (alg) {
303 case GPGME_PK_DSA: return "DSA";
304 case GPGME_PK_ELG:
305 case GPGME_PK_ELG_E: return "ELG";
306 case GPGME_PK_RSA: return "RSA";
307 default: return "???";
308 }
309 return "???";
310 }
311
312 const char*
313 get_key_fpr (gpgme_key_t key)
314 {
315 static char fpr_md[64];
316 const char *fpr;
317 char t[16], tmp[40];
318 size_t i=0;
319
320 memset (fpr_md, 0, sizeof (fpr_md));
321 fpr = key->subkeys->fpr;
322 if (!fpr || !*fpr) {
323 memset (tmp, '0', 40);
324 fpr = tmp;
325 }
326 if (strlen (fpr) == 32) {
327 strcat (fpr_md, " ");
328 for (i=0; i < strlen (fpr)/2; i++) {
329 sprintf (t, "%c%c ", fpr[2*i], fpr[2*i+1]);
330 strcat (fpr_md, t);
331 }
332 }
333 else {
334 strcat (fpr_md, " ");
335 for (i = 0; i < strlen (fpr) / 4; i++) {
336 sprintf (t, "%c%c%c%c ", fpr[4*i], fpr[4*i+1], fpr[4*i+2], fpr[4*i+3]);
337 strcat (fpr_md, t);
338 }
339 }
340 return fpr_md;
341 }
342
343
344 const char*
345 get_key_trust2 (gpgme_key_t key, int val, int uididx, int listmode)
346 {
347 if (key)
348 val = key->owner_trust; /* uididx?? */
349 switch (val) {
350 case GPGME_VALIDITY_UNKNOWN:
351 case GPGME_VALIDITY_UNDEFINED:
352 return _("None");
353 case GPGME_VALIDITY_NEVER:
354 return _("Never");
355 case GPGME_VALIDITY_MARGINAL:
356 return _("Marginal");
357 case GPGME_VALIDITY_FULL:
358 case GPGME_VALIDITY_ULTIMATE:
359 return _("Full");
360 }
361 return "";
362 }
363
364
365 const char*
366 get_key_trust (gpgme_key_t key, int uididx, int listmode)
367 {
368 return get_key_trust2 (key, 0, uididx, listmode);
369 }
370
371
372 const char*
373 get_key_trust_str (int val)
374 {
375 return get_key_trust2 (NULL, val, 0, 0);
376 }
377
378
379 /* Return the status of the key @key. */
380 char*
381 get_key_status (gpgme_key_t key, int uididx, int listmode)
382 {
383 gpgme_user_id_t u;
384 const char *attr;
385 u32 key_attr =0;
386
387 if (uididx < 0 || count_userids (key) > uididx)
388 uididx = 0;
389 if (listmode) {
390 const char *s;
391 if (key->revoked)
392 s = _("Revoked");
393 else if (key->expired)
394 s = _("Expired");
395 else if (key->disabled)
396 s = _("Disabled");
397 else
398 s = "";
399 /* if the key has a special status, we don't continue to figure out
400 the user-id validities. */
401 if (*s)
402 return m_strdup (s);
403 }
404 u = get_nth_userid (key, uididx);
405 key_attr = u->validity;
406 attr = get_key_trust2 (NULL, key_attr, 0, 0);
407 return m_strdup (attr);
408 }
409
410
411 /* Return human readable description of the key @key. */
412 char*
413 get_key_desc (gpgme_key_t key)
414 {
415 gpgme_key_t sk;
416 const char *state, *alg, *type;
417 char *p;
418
419 /* XXX: problems with the German translation. */
420 state = "";
421 if (key->disabled)
422 state = _("Disabled");
423 if (key->expired)
424 state = _("Expired");
425 if (key->revoked)
426 state = _("Revoked");
427 alg = "OpenPGP";
428 if (strlen (key->subkeys->fpr) == 32)
429 alg = "RSA Legacy";
430 type = _("public key");
431 if (!get_seckey (key->subkeys->keyid+8, &sk))
432 type = _("key pair");
433 p = new char[strlen (state) + strlen (alg) + strlen (type) + 4 + 1];
434 if (!p)
435 BUG (0);
436 sprintf (p, "%s %s %s", state, alg, type);
437 return p;
438 }
439
440
441 /* Integer comparsion of @a and @b.
442 Return values: same as in strcmp. */
443 static inline int
444 int_cmp (int a, int b)
445 {
446 if (a == b) return 0;
447 else if (a > b) return 1;
448 else return -1;
449 return 0;
450 }
451
452
453 /* To allow to sort the keys, we need to take care of
454 the expired/revoke status also. */
455 static int
456 get_ext_validity (gpgme_key_t k)
457 {
458 if (k->revoked)
459 return GPGME_VALIDITY_ULTIMATE+1;
460 else if (k->expired)
461 return GPGME_VALIDITY_ULTIMATE+2;
462 else if (k->disabled)
463 return GPGME_VALIDITY_ULTIMATE+3;
464 return k->uids->validity;
465 }
466
467
468 /* List view sorting callback. */
469 static int CALLBACK
470 keylist_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
471 {
472 gpgme_key_t a, b;
473 int cmpresult = 0;
474
475 a = (gpgme_key_t)first;
476 b = (gpgme_key_t)second;
477 if (!a || !b)
478 BUG (NULL);
479
480 switch (sortby & ~KEYLIST_SORT_DESC) {
481 case KEY_SORT_USERID:
482 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
483 break;
484
485 case KEY_SORT_KEYID:
486 cmpresult = strcmpi (a->subkeys->keyid+8,
487 b->subkeys->keyid+8);
488 break;
489
490 case KEY_SORT_VALIDITY:
491 cmpresult = int_cmp (get_ext_validity (a),
492 get_ext_validity (b));
493 break;
494
495 case KEY_SORT_OTRUST:
496 cmpresult = int_cmp (a->owner_trust, b->owner_trust);
497 break;
498
499 case KEY_SORT_IS_SECRET:
500 get_seckey (a->subkeys->keyid, &a);
501 get_seckey (b->subkeys->keyid, &b);
502 cmpresult = int_cmp (a? a->secret : 0, b? b->secret : 0);
503 break;
504
505 case KEY_SORT_LEN:
506 cmpresult = int_cmp (a->subkeys->length,
507 b->subkeys->length);
508 break;
509
510 case KEY_SORT_CREATED:
511 cmpresult = int_cmp (a->subkeys->timestamp,
512 b->subkeys->timestamp);
513 break;
514
515 case KEY_SORT_ALGO:
516 cmpresult = int_cmp (a->subkeys->pubkey_algo,
517 b->subkeys->pubkey_algo);
518 break;
519
520 default:
521 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
522 break;
523 }
524 if (sortby & KEYLIST_SORT_DESC)
525 return (~cmpresult + 1);
526 else
527 return cmpresult;
528 }
529
530
531 int
532 keylist_add_groups (listview_ctrl_t lv)
533 {
534 return 0;
535 }
536
537
538 /* Create a listview for listing keys. Use the mode given in @mode
539 and the control is given in @ctrl. */
540 static int
541 keylist_build (listview_ctrl_t *r_lv, HWND ctrl, int mode)
542 {
543 struct listview_column_s klist_enc[] = {
544 {0, 242, (char *)_("User ID")},
545 {1, 80, (char *)_("Key ID")},
546 {3, 46, (char *)_("Size")},
547 {4, 50, (char *)_("Cipher")},
548 {5, 70, (char *)_("Validity")},
549 {0, 0, NULL}
550 };
551 struct listview_column_s klist[] = {
552 {0, 240, (char *)_("User ID")},
553 {1, 78, (char *)_("Key ID")},
554 {2, 52, (char *)_("Type")},
555 {3, 66, (char *)_("Size")},
556 {4, 60, (char *)_("Cipher")},
557 {5, 66, (char *)_("Validity")},
558 {6, 58, (char *)_("Trust")},
559 {7, 72, (char *)_("Creation")},
560 {0, 0, NULL}
561 };
562 HICON ico[2];
563 listview_ctrl_t lv;
564 listview_column_t col;
565 int j, n = 0, ext_chk = 0;
566 int rc = 0;
567
568 rc = listview_new (&lv);
569 if (rc)
570 return rc;
571
572 lv->ctrl = ctrl;
573 if (mode & KEYLIST_ENCRYPT_MIN) {
574 col = klist_enc;
575 n = (DIM(klist_enc) -1);
576 ext_chk = 1;
577 }
578 else if ((mode & KEYLIST_SIGN)) {
579 col = klist_enc;
580 n = (DIM(klist_enc) - 1) - 1;
581 ext_chk = 1;
582 }
583 else {
584 col = klist;
585 n = (DIM(klist) - 1);
586 }
587
588 for (j = 0; j < n; j++)
589 listview_add_column (lv, &col[j]);
590 listview_set_ext_style (lv);
591 if (ext_chk)
592 listview_set_chkbox_style (lv);
593 ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
594 ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
595 listview_set_image_list (lv, 22, 14, ico, 2);
596 listview_del_all_items (lv);
597
598 *r_lv = lv;
599 return 0;
600 }
601
602
603 static void
604 keylist_load_keycache (listview_ctrl_t lv, int mode,
605 gpg_keycache_t pubkc, gpg_keycache_t seckc)
606 {
607 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
608 gpgme_key_t key, skey;
609 const char * keyid;
610
611 if (pubkc && seckc) {
612 gpg_keycache_rewind (pubkc);
613 while (!gpg_keycache_next_key (pubkc, 0, &key)) {
614 keyid = key->subkeys->keyid;
615 if (keyid && !gpg_keycache_find_key (seckc, keyid, 0, &skey))
616 keylist_add_key (lv, mode, key);
617 }
618 }
619 else if (pubkc) {
620 gpg_keycache_rewind (pubkc);
621 while (!err) {
622 err = gpg_keycache_next_key (pubkc, 0, &key);
623 if (!err)
624 keylist_add_key (lv, mode, key);
625 }
626 }
627 }
628
629
630 /* Load the list view @ctrl with the keys from the cache.
631 Return value: list view context on success. */
632 listview_ctrl_t
633 keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc,
634 int mode, int sortby)
635 {
636 listview_ctrl_t lv;
637 int rc = 0;
638
639 rc = keylist_build (&lv, ctrl, mode);
640 if (rc)
641 return NULL;
642 keylist_load_keycache (lv, mode, pubkc, seckc);
643 keylist_sort (lv, sortby);
644 if (mode & KEYLIST_ENCRYPT_MIN)
645 keylist_add_groups (lv);
646 return lv;
647 }
648
649
650 /* Reload the given key list control @lv. */
651 int
652 keylist_reload (listview_ctrl_t lv, gpg_keycache_t pubkc, int mode, int sortby)
653 {
654 listview_del_all_items (lv);
655 keylist_load_keycache (lv, mode, pubkc, NULL);
656 keylist_sort (lv, sortby);
657 return 0;
658 }
659
660
661 void
662 keylist_delete (listview_ctrl_t lv)
663 {
664 if (lv) {
665 listview_release (lv);
666 }
667 }
668
669
670 /* Return if there is a secret for @key.
671 0 means success. */
672 static int
673 find_secret_key (gpgme_key_t key)
674 {
675 const char *keyid;
676 winpt_key_s skey;
677
678 memset (&skey, 0, sizeof (skey));
679 keyid = key->subkeys->keyid;
680 if (!keyid)
681 return 0;
682 winpt_get_seckey (keyid, &skey);
683 if (skey.ext && skey.ext->gloflags.divert_to_card)
684 return 2;
685 return skey.ctx? 1 : 0;
686 }
687
688
689 static int
690 do_addkey (listview_ctrl_t lv, gpgme_key_t key, int uididx, int keyidx, int list)
691 {
692 LV_ITEM lvi;
693 gpgme_user_id_t u;
694 gpgme_subkey_t k;
695 char fmt[128], *p;
696 const char *attr;
697 u32 key_attr;
698 int idx = 0;
699
700 /* we check the pubkey algorithm here to make sure that no ElGamal
701 sign+encrypt key is used in _any_ mode */
702 if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {
703 log_debug ("ElGamal (E+S) key found: %s (%s)\n",
704 key->uids->name, key->subkeys->keyid);
705 return 0;
706 }
707
708 if (listview_add_item2 (lv, " ", (void *)key))
709 return WPTERR_GENERAL;
710
711 attr = key->uids->uid;
712 memset (&lvi, 0, sizeof lvi);
713 lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
714 lvi.pszText = (char *)attr;
715 lvi.iImage = find_secret_key (key)? 1 : 0;
716 lvi.lParam = (LPARAM )key;
717 if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
718 return WPTERR_GENERAL;
719
720 if (uididx == -1) { /* request the primary user-id of the key. */
721 attr = key->uids->uid;
722 uididx = 0;
723 }
724 else {
725 u = get_nth_userid (key, uididx);
726 if (!u || u->revoked || uididx < 0)
727 uididx = 0;
728 u = get_nth_userid (key, uididx);
729 attr = u->uid;
730 }
731 if (attr == NULL || strlen (attr) < 5) { /* normal userids are > 5 chars */
732 attr = _("Invalid User ID");
733 listview_add_sub_item (lv, 0, idx++, attr);
734 }
735 else {
736 char *uid = utf8_to_wincp (attr, strlen (attr));
737 if (uid) {
738 listview_add_sub_item (lv, 0, idx++, uid);
739 free (uid);
740 }
741 }
742 k = get_nth_key (key, keyidx);
743 if (k && k->keyid) {
744 _snprintf (fmt, sizeof fmt -1, "0x%s", k->keyid + 8);
745 listview_add_sub_item( lv, 0, idx++, fmt );
746 }
747 if (list > 0) {
748 key_attr = find_secret_key (key);
749 if (!key_attr)
750 attr = "pub";
751 else
752 attr = key_attr == 1? "pub/sec" : "pub/crd";
753 listview_add_sub_item (lv, 0, idx++, attr);
754 }
755 if (lv->cols >= 2) {
756 attr = get_key_size (key, list == -1? keyidx+1 : 0);
757 if (attr)
758 listview_add_sub_item (lv, 0, idx++, attr);
759 }
760 if (lv->cols >= 3) {
761 attr = get_key_algo (key, list == -1? keyidx+1 : 0);
762 if (attr)
763 listview_add_sub_item( lv, 0, idx++, attr);
764 }
765 if (lv->cols >= 4) {
766 p = get_key_status( key, uididx, list > 0? 1 : 0 );
767 if (!p)
768 return WPTERR_GENERAL;
769 listview_add_sub_item (lv, 0, idx++, p);
770 free_if_alloc (p);
771 }
772 if (lv->cols >= 5) {
773 attr = get_key_trust (key, uididx, list > 0? 1 : 0);
774 listview_add_sub_item (lv, 0, idx++, attr);
775 }
776 if( lv->cols >= 6 ) {
777 k = get_nth_key (key, keyidx);
778 key_attr = k->timestamp;
779 if( key_attr ) {
780 attr = get_key_created (key_attr);
781 listview_add_sub_item( lv, 0, idx++, attr );
782 }
783 }
784
785 return 0;
786 }
787
788
789 /* Update a single column @col but for each element in the
790 listview @lv. */
791 void
792 keylist_upd_col (listview_ctrl_t lv, int col)
793 {
794 gpgme_key_t key;
795 const char *s;
796 char buf[32], *p;
797 int i;
798
799 for (i=0; i < listview_count_items (lv, 0); i++) {
800 key = (gpgme_key_t)listview_get_item2 (lv, i);
801 if (!key)
802 continue;
803 switch (col) {
804 case KM_COL_KEYID:
805 _snprintf (buf, sizeof (buf)-1, "0x%s", key->subkeys->keyid+8);
806 listview_add_sub_item (lv, i, col, buf);
807 break;
808
809 case KM_COL_CIPHER:
810 s = get_key_algo (key, 0);
811 listview_add_sub_item (lv, i, col, s);
812 break;
813
814 case KM_COL_TYPE:
815 s = find_secret_key (key)? "pub/sec" : "pub";
816 listview_add_sub_item (lv, i, col, s);
817 break;
818
819 case KM_COL_CREAT:
820 s = get_key_created (key->subkeys->timestamp);
821 listview_add_sub_item (lv, i, col, s);
822 break;
823
824 case KM_COL_DESC:
825 p = get_key_desc (key);
826 listview_add_sub_item (lv, i, col, p);
827 free_if_alloc (p);
828 break;
829 }
830 }
831 }
832
833
834 /* Update the listview item at position @pos with the data from
835 the key @key. */
836 void
837 keylist_upd_key (listview_ctrl_t lv, int pos, gpgme_key_t key)
838 {
839 const char *s;
840 char *uid, *p;
841 char tmp[32];
842
843 listview_set_item2 (lv, pos, (void *)key);
844 /* the only mode we support is KYLIST_LIST in the Key Manager */
845
846 s = key->uids->uid;
847 if (s) {
848 uid = utf8_to_wincp2 (s);
849 listview_add_sub_item (lv, pos, KM_COL_UID, uid);
850 free (uid);
851 }
852
853 s = key->subkeys->keyid;
854 if (s) {
855 sprintf (tmp, "0x%s", s+8);
856 listview_add_sub_item (lv, pos, KM_COL_KEYID, tmp);
857 }
858
859 s = find_secret_key (key)? "pub/sec" : "pub";
860 listview_add_sub_item (lv, pos, KM_COL_TYPE, s);
861
862 s = get_key_size (key, 0);
863 if (s)
864 listview_add_sub_item (lv, pos, KM_COL_SIZE, s);
865
866 s = get_key_algo (key, 0);
867 if (s)
868 listview_add_sub_item (lv, pos, KM_COL_CIPHER, s);
869
870 p = get_key_status (key, 0, 1);
871 if (p) {
872 listview_add_sub_item (lv, pos, KM_COL_VALID, p);
873 free_if_alloc (p);
874 }
875
876 s = get_key_trust (key, 0, 1);
877 if (s)
878 listview_add_sub_item (lv, pos, KM_COL_TRUST, s);
879
880 long t = key->subkeys->timestamp;
881 s = get_key_created (t);
882 if (s)
883 listview_add_sub_item (lv, pos, KM_COL_CREAT, s);
884 }
885
886
887 int
888 keylist_add_key (listview_ctrl_t lv, int mode, gpgme_key_t key)
889 {
890 int uids, rc = 0, i;
891 gpgme_subkey_t k;
892
893 /* if the entire key is disabled, just return. */
894 if (key->disabled && !(mode & KEYLIST_LIST))
895 return 0;
896
897 for (k=key->subkeys, i = 0; i < count_subkeys (key); i++, k=k->next) {
898 if (k->invalid) {
899 log_debug ("keylist_add_key: invalid key \"%s\"\n", key->uids->name);
900 continue; /* Don't use invalid keys */
901 }
902
903 if (mode & KEYLIST_ALL) {
904 uids = count_userids (key);
905 rc = do_addkey (lv, key, uids, i, 0);
906 if (rc)
907 return rc;
908 }
909 else if (mode & KEYLIST_LIST)
910 return do_addkey (lv, key, -1, i, 1);
911 else if (mode & KEYLIST_ENCRYPT) {
912 if (k->can_encrypt && key_is_useable (k)) {
913 if (mode & KEYLIST_FLAG_FILE) {
914 rc = do_addkey (lv, key, -1, i, -1);
915 if (rc)
916 return rc;
917 }
918 else {
919 for (uids = 0; uids < count_userids (key); uids++) {
920 rc = do_addkey (lv, key, uids, i, -1);
921 if (rc)
922 return rc;
923 }
924 }
925 }
926 }
927 else if (mode & KEYLIST_ENCRYPT_MIN) {
928 if( k->can_encrypt && key_is_useable (k))
929 {
930 rc = do_addkey (lv, key, -1, i, -1);
931 return rc;
932 }
933 }
934 else if (mode & KEYLIST_SIGN) {
935 if (k->can_sign
936 && find_secret_key (key)
937 && key_is_useable (k)) {
938 rc = do_addkey (lv, key, -1, i, -1);
939 if (rc)
940 return rc;
941 }
942 }
943 }
944
945 return rc;
946 }
947
948
949 int
950 keylist_sort (listview_ctrl_t lv, int sortby)
951 {
952 return listview_sort_items (lv, sortby, keylist_cmp_cb);
953 }
954
955
956 /* Check that the validity @validity is at least >= marginal. */
957 static int
958 key_check_validity (gpgme_key_t key)
959 {
960 gpgme_user_id_t u;
961
962 for (u=key->uids; u; u =u->next) {
963 if (u->validity >= GPGME_VALIDITY_MARGINAL)
964 return -1;
965 }
966
967 return 0;
968 }
969
970
971 /* Extract all selected recipients from the list @lv and return them
972 as a vector. @r_force_trust is >= 1 if one of the recipients is not
973 fully trusted. @r_count returns the number of selected keys.
974 Return value: the key list on success, NULL otherwise. */
975 gpgme_key_t*
976 keylist_get_recipients (listview_ctrl_t lv, int *r_force_trust, int *r_count)
977 {
978 key_array_s *ka = NULL;
979 gpgme_key_t *keybuf, key;
980 int count = 0, force_trust = 0;
981 int n, j, ka_pos = 0, rc = 0;
982 int k_pos=0;
983
984 n = listview_count_items (lv, 0);
985
986 ka = key_array_new (n);
987 if (!ka)
988 BUG (NULL);
989
990 keybuf = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));
991 if (!keybuf)
992 BUG (NULL);
993
994 for (j = 0; j < n; j++) {
995 if (listview_get_item_state (lv, j) || n == 1) {
996 key = (gpgme_key_t)listview_get_item2 (lv, j);
997 if (!key)
998 BUG (0);
999 if (!key_check_validity (key) &&
1000 !key_array_search (ka, ka_pos, key->subkeys->keyid)) {
1001 char *warn = new char[512+strlen (key->uids->uid) + 1];
1002 if (!warn)
1003 BUG (0);
1004 sprintf (warn,
1005 _("It is NOT certain that the key belongs to the person\n"
1006 "named in the user ID. If you *really* know what you are\n"
1007 "doing, you may answer the next question with yes\n"
1008 "\n"
1009 "Use \"%s\" anyway?"), key->uids->uid);
1010 if (reg_prefs.always_trust)
1011 rc = IDYES;
1012 else
1013 rc = msg_box (NULL, warn, _("Recipients"), MB_ERR_ASK);
1014 if (rc == IDYES) {
1015 keybuf[k_pos++] = key;
1016 force_trust++;
1017 ka[ka_pos].checked = 1;
1018 strcpy (ka[ka_pos++].keyid, key->subkeys->keyid);
1019 count++;
1020 }
1021 free_if_alloc (warn);
1022 }
1023 else {
1024 keybuf[k_pos++] = key;
1025 count++;
1026 }
1027 }
1028 }
1029 key_array_release (ka);
1030 if (r_force_trust)
1031 *r_force_trust = force_trust;
1032 if (r_count)
1033 *r_count = count;
1034 return keybuf;
1035 }
1036
1037
1038 static int
1039 keylist_get_keyflags (gpgme_key_t key)
1040 {
1041 int flags = KEYFLAG_NONE;
1042
1043 if (key->revoked)
1044 flags |= KEYFLAG_REVOKED;
1045 if (key->expired)
1046 flags |= KEYFLAG_EXPIRED;
1047 if (key->disabled)
1048 flags |= KEYFLAG_DISABLED;
1049
1050 return flags;
1051 }
1052
1053
1054 gpgme_key_t*
1055 keylist_enum_recipients (listview_ctrl_t lv, int listype, int *r_count)
1056 {
1057 gpgme_key_t *rset;
1058 gpgme_key_t key;
1059 int i, n, id, k_pos=0;
1060
1061 n = listview_count_items (lv, 0);
1062 if (!n)
1063 return 0;
1064 rset = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));
1065 if (!rset)
1066 BUG (NULL);
1067 for (i = 0; i < n; i++) {
1068 if (!listview_get_item_state (lv, i))
1069 continue;
1070 key = (gpgme_key_t)listview_get_item2 (lv, i);
1071 if (!key)
1072 BUG (0);
1073 switch (listype) {
1074 case KEYLIST_LIST:
1075 if (keylist_get_keyflags (key) & KEYFLAG_REVOKED) {
1076 id = printf_box (_("Recipients"), MB_INFO|MB_YESNO,
1077 _("KeyID %s.\nDo you really want to export a revoked key?"),
1078 key->uids->uid);
1079 if (id == IDNO)
1080 continue;
1081 }
1082 break;
1083 }
1084 rset[k_pos++] = key;
1085 }
1086 if (r_count)
1087 *r_count = k_pos;
1088 return rset;
1089 }
1090
1091
1092 void
1093 seclist_destroy (keylist_t *list)
1094 {
1095 keylist_t l2;
1096 while (*list) {
1097 l2 = (*list)->next;
1098 safe_free (*list);
1099 *list = l2;
1100 }
1101 list = NULL;
1102 }
1103
1104
1105 void
1106 seclist_init (HWND dlg, int ctlid, int flags, keylist_t * ret_list)
1107 {
1108 gpg_keycache_t kc = NULL;
1109 gpgme_key_t key = NULL;
1110 HWND kb;
1111 keylist_t list=NULL, l, l2;
1112 long pos = 0;
1113
1114 SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);
1115 kb = GetDlgItem (dlg, ctlid);
1116 kc = keycache_get_ctx (0);
1117 if (!kc)
1118 BUG (0);
1119 gpg_keycache_rewind (kc);
1120
1121 while (!gpg_keycache_next_key (kc, 1, &key)) {
1122 char *inf = NULL, *uid = NULL;
1123 const char *id;
1124 const char *keyid;
1125 int algo;
1126 size_t size = 0;
1127
1128 if (flags & KEYLIST_FLAG_SHORT)
1129 id = key->uids->name;
1130 else
1131 id = key->uids->uid;
1132 keyid = key->subkeys->keyid;
1133 algo = key->subkeys->pubkey_algo;
1134 if (!id || !keyid)
1135 continue;
1136 if (key->disabled || !key_is_useable (key->subkeys))
1137 continue;
1138
1139 uid = utf8_to_wincp (id, strlen (id));
1140 size = strlen (uid) + strlen (keyid) + 32;
1141 inf = new char[size+1];
1142 if (!inf)
1143 BUG (NULL);
1144 _snprintf (inf, size, "%s (%s/0x%s)", uid,
1145 get_key_pubalgo (key->subkeys->pubkey_algo), keyid + 8);
1146 combox_add_string (kb, inf);
1147 free_if_alloc (inf);
1148 free (uid);
1149 l = (struct keylist_s *)calloc (1, sizeof * l);
1150 if (!l)
1151 BUG (0);
1152 l->key = key;
1153 if (!list)
1154 list = l;
1155 else {
1156 for( l2 = list; l2->next; l2 = l2->next )
1157 ;
1158 l2->next = l;
1159 }
1160 }
1161 for (pos = 0, l2=list; pos < SendMessage (kb, CB_GETCOUNT, 0, 0);
1162 pos++, l2=l2->next)
1163 SendMessage (kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key);
1164 SendMessage (kb, CB_SETCURSEL, 0, 0);
1165 *ret_list = list;
1166 }
1167
1168
1169 /* Select a secret key from the combo box with the ID @ctlid.
1170 Return the code on success in @ret_key. */
1171 int
1172 seclist_select_key (HWND dlg, int ctlid, gpgme_key_t *ret_key)
1173 {
1174 int pos;
1175 DWORD k = 0;
1176
1177 pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
1178 if (pos == CB_ERR) {
1179 msg_box (dlg, _("No key was selected."), _("Secret Key List"), MB_ERR);
1180 *ret_key = NULL;
1181 }
1182 else {
1183 k = SendDlgItemMessage (dlg, ctlid, CB_GETITEMDATA, pos, 0);
1184 *ret_key = (gpgme_key_t)k;
1185 }
1186 return k? 0 : -1;
1187 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26