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

Annotation of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations)
Mon Oct 24 08:03:48 2005 UTC (19 years, 4 months ago) by twoaday
File size: 26695 byte(s)
2005-10-23  Timo Schulz  <twoaday@g10code.com>
 
        * wptFileManager.cpp (fm_get_file_type): Detect detached sigs.
        * wptKeyList.cpp (keylist_cmp_cb): Take care of expired/revoked keys.
        (get_ext_validity): New.
        * wptFileVerifyDlg.cpp (file_verify_dlg_proc): Several cleanups.
        * wptClipEditDlg.cpp (load_clipboard): Factored out some code into
        this function.
        (load_clipboard_from_file): Likewise.
        (save_clipboard_to_file): New.
        * wptKeyManagerDlg.cpp (keyprops_dlg_proc): Fix stack overflow.

For complete details, see the ChangeLog files.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26