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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26