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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations)
Fri Oct 28 08:25:30 2005 UTC (19 years, 4 months ago) by werner
File size: 25771 byte(s)
Readded lost changes from revision 40

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26