/[winpt]/trunk/MyGPGME/keylist.c
ViewVC logotype

Contents of /trunk/MyGPGME/keylist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Wed Aug 10 11:33:35 2005 UTC (19 years, 6 months ago) by twoaday
File MIME type: text/plain
File size: 19720 byte(s)
2005-08-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptGPGME.cpp (keycache_update): Reload OpenPGP parts
        of the secret key.
        (keycache_init): cache name of secret keyring.
        * wptKeyList.cpp (keylist_upd_key): Do not add long keyid.
        (get_key_type): Do not assume 'ultimate' means key pair.
        * wptKeyEditDlgs.cpp (diff_time): New.
        (keyedit_addsubkey_dlg_proc): Changed design and use
        diff_time. Drop checks for invalid keylength (< 1024, > 4096)
        because the combo box automatically handles this.
        * wptKeyManager.cpp (km_set_implicit_trust): Return error code.
        * wptGPG.cpp (get_backup_name): New.
        (gnupg_backup_keyrings): Rotate backup names, from 0..3.
        * wptClipImportDialog.cpp (clip_import_dlg_proc): Free memory.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Use 0x short keyid and
        not the long keyid.


1 /* keylist.c - key listing
2 * Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH
3 * Copyright (C) 2002-2005 Timo Schulz
4 *
5 * This file is part of MyGPGME.
6 *
7 * MyGPGME is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * MyGPGME 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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <windows.h>
29
30 #include "util.h"
31 #include "context.h"
32 #include "ops.h"
33 #include "key.h"
34
35 static void finish_key ( gpgme_ctx_t ctx );
36
37
38 static void
39 keylist_status_handler( gpgme_ctx_t ctx, gpg_status_code_t code, char *args )
40 {
41 if( ctx->out_of_core )
42 return;
43
44 switch( code ) {
45 case STATUS_EOF:
46 if( ctx->tmp_key )
47 finish_key( ctx );
48 break;
49
50 default: /* ignore all other codes */
51 break;
52 }
53 }
54
55
56
57 static time_t
58 parse_timestamp (char * p)
59 {
60 return *p ? (time_t)strtoul (p, NULL, 10) : 0;
61 }
62
63
64 static void
65 set_mainkey_trust_info( gpgme_key_t key, const char * s )
66 {
67 /* look at letters and stop at the first digit */
68 for( ; *s && !isdigit( *s ); s++ ) {
69 switch( *s ) {
70 case 'u': key->gloflags.ultimate = 1;
71 key->validity = GPGME_VALIDITY_ULTIMATE; break;
72 case '-':
73 case 'q': key->validity = GPGME_VALIDITY_UNDEFINED; break;
74 case 'm': key->validity = GPGME_VALIDITY_MARGINAL; break;
75 case 'f': key->validity = GPGME_VALIDITY_FULL; break;
76 case 'e': key->keys.flags.expired = 1; break;
77 case 'r': key->keys.flags.revoked = 1;
78 key->validity = GPGME_VALIDITY_REVOKED; break;
79 case 'd': key->keys.flags.disabled = 1; break;
80 case 'i': key->keys.flags.invalid = 1; break;
81 }
82 }
83 }
84
85
86 static void
87 set_userid_flags (struct user_id_s * u, const char * s)
88 {
89 /* look at letters and stop at the first digit */
90 for (; *s && !isdigit (*s); s++) {
91 switch( *s ) {
92 case 'r': u->flags.revoked = 1;
93 u->validity = GPGME_VALIDITY_REVOKED; break;
94 case 'i': u->flags.invalid = 1;
95 u->validity = GPGME_VALIDITY_UNDEFINED; break;
96 case 'n': u->validity = GPGME_VALIDITY_NEVER; break;
97 case 'm': u->validity = GPGME_VALIDITY_MARGINAL; break;
98 case 'f': u->validity = GPGME_VALIDITY_FULL; break;
99 case 'u': u->validity = GPGME_VALIDITY_ULTIMATE; break;
100 }
101 }
102 }
103
104 static void
105 set_subkey_trust_info( struct subkey_s * k, const char * s )
106 {
107 /* look at letters and stop at the first digit */
108 for( ; *s && !isdigit (*s); s++ ) {
109 switch( *s ) {
110 case 'e': k->flags.expired = 1; break;
111 case 'r': k->flags.revoked = 1; break;
112 case 'd': k->flags.disabled = 1; break;
113 case 'i': k->flags.invalid = 1; break;
114 }
115 }
116 }
117
118 static void
119 set_mainkey_capability( gpgme_key_t key, const char * s )
120 {
121 for( ; *s ; s++ ) {
122 switch( *s ) {
123 case 'a': key->keys.flags.can_auth = 1; break;
124 case 'e': key->keys.flags.can_encrypt = 1; break;
125 case 's': key->keys.flags.can_sign = 1; break;
126 case 'c': key->keys.flags.can_certify = 1; break;
127 case 'E': key->gloflags.can_encrypt = 1; break;
128 case 'S': key->gloflags.can_sign = 1; break;
129 case 'C': key->gloflags.can_certify = 1; break;
130 case 'D': key->gloflags.disabled = 1; break;
131 }
132 }
133 }
134
135 static void
136 set_subkey_capability (struct subkey_s * k, const char * s)
137 {
138 for (; *s; s++) {
139 switch (*s) {
140 case 'a': k->flags.can_auth = 1; break;
141 case 'e': k->flags.can_encrypt = 1; break;
142 case 's': k->flags.can_sign = 1; break;
143 case 'c': k->flags.can_certify = 1; break;
144 }
145 }
146 }
147
148 static void
149 set_mainkey_ownertrust( gpgme_key_t key, const char * s )
150 {
151 switch( *s ) {
152 case '-': key->otrust = GPGME_TRUST_UNKNOWN; break;
153 case 'e': key->otrust = GPGME_TRUST_EXPIRED; break;
154 case 'q': key->otrust = GPGME_TRUST_UNDEFINED; break;
155 case 'n': key->otrust = GPGME_TRUST_NEVER; break;
156 case 'm': key->otrust = GPGME_TRUST_MARGINAL; break;
157 case 'f': key->otrust = GPGME_TRUST_FULLY; break;
158 case 'u': key->otrust = GPGME_TRUST_ULTIMATE; break;
159 default: key->otrust = GPGME_TRUST_UNKNOWN; break;
160 }
161 }
162
163
164 /* Note: we are allowed to modify line */
165 static void
166 keylist_colon_handler (gpgme_ctx_t ctx, char *line)
167 {
168 enum {
169 RT_NONE,
170 RT_SIG,
171 RT_UID,
172 RT_SUB,
173 RT_PUB,
174 RT_FPR,
175 RT_SSB,
176 RT_SEC,
177 RT_PKD,
178 } rectype = RT_NONE;
179 gpgme_key_t key = ctx->tmp_key;
180 struct subkey_s *sk = NULL;
181 struct signature_s *sig = NULL;
182 struct subkey_s *s = NULL;
183 struct user_id_s *u = NULL;
184 struct mpi_s *m = NULL, * mt = NULL;
185 const char *trust_info = NULL;
186 char *p, *pend;
187 int field = 0;
188 unsigned long val=0;
189 int i;
190
191 if (ctx->out_of_core)
192 return;
193 if( !line ) { /* EOF */
194 if( ctx->tmp_key )
195 finish_key( ctx );
196 return;
197 }
198
199 for( p = line; p; p = pend ) {
200 field++;
201 pend = strchr( p, ':' );
202 if( pend )
203 *pend++ = 0;
204
205 if( field == 1 ) {
206 if( !strcmp( p, "sig" ) && key ) {
207 rectype = RT_SIG;
208 sig = _gpgme_key_add_signature( key );
209 if( !sig ) {
210 ctx->out_of_core = 1;
211 break;
212 }
213 }
214 else if( !strcmp( p, "uid" ) && key ) {
215 rectype = RT_UID;
216 key = ctx->tmp_key;
217 sig = _gpgme_key_add_signature( key );
218 if( !sig ) {
219 ctx->out_of_core = 1;
220 break;
221 }
222 }
223 else if( !strcmp( p, "sub" ) && key ) {
224 /* start a new subkey */
225 rectype = RT_SUB;
226 sk = _gpgme_key_add_subkey( key );
227 if( !sk ) {
228 ctx->out_of_core = 1;
229 return;
230 }
231 }
232 else if( !strcmp( p, "ssb" ) && key ) {
233 /* start a new secret subkey */
234 rectype = RT_SSB;
235 sk = _gpgme_key_add_secret_subkey( key );
236 if( !sk ) {
237 ctx->out_of_core = 1;
238 return;
239 }
240 }
241 else if( !strcmp( p, "pub" ) ) {
242 /* start a new keyblock */
243 if( _gpgme_key_new ( &key ) ) {
244 ctx->out_of_core = 1; /* the only kind of error we can get*/
245 return;
246 }
247 rectype = RT_PUB;
248 if ( ctx->tmp_key )
249 finish_key ( ctx );
250 assert ( !ctx->tmp_key );
251 ctx->tmp_key = key;
252 ctx->tmp_i = 0;
253 if (ctx->cb.progress)
254 ctx->cb.progress (ctx->cb.progress_value, "keylist", 0,
255 ctx->cb.progess_tmp,
256 ctx->cb.progress_value_int);
257 ctx->cb.progess_tmp++;
258 }
259 else if( !strcmp ( p, "sec" ) ) {
260 /* start a new keyblock */
261 if ( _gpgme_key_new_secret( &key ) ) {
262 ctx->out_of_core = 1; /* the only kind of error we can get */
263 return;
264 }
265 rectype = RT_SEC;
266 if( ctx->tmp_key )
267 finish_key ( ctx );
268 assert ( !ctx->tmp_key );
269 ctx->tmp_key = key;
270 }
271 else if( !strcmp( p, "fpr" ) && key )
272 rectype = RT_FPR;
273 else if( !strcmp( p, "pkd" ) && key )
274 rectype = RT_PKD;
275 else
276 rectype = RT_NONE;
277 }
278 else if( rectype == RT_PUB || rectype == RT_SEC )
279 {
280 switch( field ) {
281 case 2: /* trust info */
282 trust_info = p;
283 set_mainkey_trust_info( key, trust_info );
284 break;
285 case 3: /* key length */
286 i = atoi (p);
287 if( i > 1 ) /* ignore invalid values */
288 key->keys.key_len = i;
289 break;
290 case 4: /* pubkey algo */
291 i = atoi (p);
292 if (i > 0 && i < 128)
293 key->keys.key_algo = i;
294 break;
295 case 5: /* long keyid */
296 memset (key->keys.keyid, 0, sizeof key->keys.keyid);
297 strncpy (key->keys.keyid, p, DIM (key->keys.keyid)-1);
298 break;
299 case 6: /* timestamp (1998-02-28) */
300 key->keys.timestamp = parse_timestamp( p );
301 break;
302 case 7: /* valid for n days */
303 key->keys.expires = parse_timestamp( p );
304 break;
305 case 8: /* reserved (LID) */
306 break;
307 case 9: /* ownertrust */
308 set_mainkey_ownertrust( key, p );
309 break;
310 case 10: /* not used due to --fixed-list-mode option */
311 break;
312 case 11: /* signature class */
313 break;
314 case 12: /* capabilities */
315 set_mainkey_capability( key, p );
316 break;
317 case 15:
318 if (p && * p)
319 {
320 key->gloflags.divert_to_card = 1;
321 memset (key->keys.cardno, 0, sizeof key->keys.cardno);
322 strncpy (key->keys.cardno, p, DIM (key->keys.cardno));
323 }
324 pend = NULL; /* we can stop here */
325 break;
326 }
327 }
328 else if ((rectype == RT_SUB || rectype== RT_SSB) && sk) {
329 switch (field) {
330 case 2: /* trust info */
331 set_subkey_trust_info (sk, p);
332 break;
333
334 case 3: /* key length */
335 i = atoi( p );
336 if ( i > 1 ) /* ignore invalid values */
337 sk->key_len = i;
338 break;
339
340 case 4: /* pubkey algo */
341 i = atoi (p);
342 if (i > 0 && i < 128)
343 sk->key_algo = i;
344 break;
345
346 case 5: /* long keyid */
347 memset (sk->keyid, 0, sizeof sk->keyid);
348 strncpy (sk->keyid, p, DIM (sk->keyid)-1);
349 break;
350 case 6: /* timestamp (1998-02-28) */
351 sk->timestamp = parse_timestamp( p );
352 break;
353 case 7: /* valid for n days */
354 sk->expires = parse_timestamp( p );
355 break;
356 case 8: /* reserved (LID) */
357 break;
358 case 9: /* ownertrust */
359 break;
360 case 10:/* user ID n/a for a subkey */
361 break;
362 case 11: /* signature class */
363 break;
364 case 12: /* capability */
365 set_subkey_capability ( sk, p );
366 break;
367 case 15:
368 memset (sk->cardno, 0, sizeof sk->cardno);
369 strncpy (sk->cardno, p, DIM (sk->cardno)-1);
370 pend = NULL; /* we can stop here */
371 break;
372 }
373 }
374 else if (rectype == RT_UID)
375 {
376 switch (field)
377 {
378 case 2: /* trust info */
379 trust_info = p; /* save for later use */
380 break;
381 case 6: /* creation date */
382 if (p)
383 val = parse_timestamp (p);
384 break;
385
386 case 8: /* hash over name */
387 break;
388
389 case 10: /* user ID */
390 safe_free (ctx->tmp_id);
391 ctx->tmp_id = strdup (p);
392 if (!ctx->tmp_id) {
393 ctx->out_of_core = 1;
394 break;
395 }
396 if (_gpgme_key_append_name (key, p, &u))
397 ctx->out_of_core = 1;
398 else if (trust_info)
399 set_userid_flags (u, trust_info);
400 if (sig) {
401 safe_free (sig->issuer);
402 sig->issuer = calloc (1, strlen (p) + 1);
403 if (!sig->issuer) {
404 ctx->out_of_core = 1;
405 break;
406 }
407 _gpgme_decode_c_string (p, &sig->issuer, strlen (p)+ 1);
408 }
409 u->created = val;
410 pend = NULL; /* we can stop here */
411 break;
412 }
413 }
414 else if( rectype == RT_FPR ) {
415 int nfpr = ctx->tmp_i;
416 switch( field ) {
417 case 10:
418 for( s = &key->keys; s && nfpr; s = s->next, nfpr-- )
419 ;
420 if( s ) {
421 s->fingerprint = strdup( p );
422 if( !s->fingerprint ) {
423 ctx->out_of_core = 1;
424 break;
425 }
426 }
427 pend = NULL; /* that is all we want */
428 ctx->tmp_i++;
429 break;
430 }
431 }
432 else if( rectype == RT_SIG ) {
433 switch( field ) {
434 case 2: /* signature state */
435 switch( *p ) {
436 case '!': sig->stat = GPGME_SIG_STAT_GOOD; break;
437 case '-': sig->stat = GPGME_SIG_STAT_BAD; break;
438 case '?': sig->stat = GPGME_SIG_STAT_NOKEY; break;
439 case '%': sig->stat = GPGME_SIG_STAT_ERROR; break;
440 default : sig->stat = GPGME_SIG_STAT_NONE; break;
441 }
442 break;
443
444 case 4: /* pk algorithm */
445 sig->algo = atol (p);
446 break;
447
448 case 5: /* long keyid */
449 memset (sig->keyid, 0, sizeof sig->keyid);
450 strncpy (sig->keyid, p, DIM (sig->keyid)-1);
451 break;
452
453 case 6: /* created */
454 sig->created = parse_timestamp( p );
455 break;
456
457 case 7: /* expires */
458 sig->expires = parse_timestamp( p );
459 break;
460
461 case 10:
462 if( p ) {
463 sig->issuer = calloc( 1, strlen( p ) + 1 );
464 if( !sig->issuer ) {
465 ctx->out_of_core = 1;
466 break;
467 }
468 _gpgme_decode_c_string( p, &sig->issuer, strlen( p ) + 1 );
469 }
470 break;
471
472 case 11:
473 sig->sigclass = strtoul( p, NULL, 16 );
474 if (strchr (p, 'l'))
475 sig->is_local = 1;
476 /*if (strchr (p, ' '))
477 sig->is_nonrev = 1;*/
478 if (sig->sigclass < 0x10 || sig->sigclass > 0x13) {
479 /* we only want certificates and no key signatures */
480 pend = NULL;
481 break;
482 }
483 if( ctx->tmp_id ) {
484 sig->user_id = calloc( 1, strlen( ctx->tmp_id ) + 1 );
485 if( !sig->user_id ) {
486 ctx->out_of_core = 1;
487 break;
488 }
489 _gpgme_decode_c_string( ctx->tmp_id, &sig->user_id, strlen( ctx->tmp_id ) +1 );
490 }
491 pend = NULL; /* we can stop here */
492 break;
493 }
494 }
495 else if( rectype == RT_PKD ) {
496 switch( field ) {
497 case 1:
498 m = calloc( 1, sizeof * m );
499 if( !m ) {
500 ctx->out_of_core = 1;
501 return;
502 }
503 for( mt=key->pkey; mt->next; mt=mt->next )
504 ;
505 mt->next = m;
506 break;
507
508 case 2:
509 if( m )
510 m->bits = atol( p );
511 break;
512
513 case 3:
514 if( m ) {
515 m->hexval = strdup( p );
516 if( !m->hexval )
517 ctx->out_of_core=1;
518 }
519 break;
520 }
521 }
522 }
523
524 }
525
526
527 /*
528 * We have read an entire key into ctx->tmp_key and should now finish
529 * it. It is assumed that this releases ctx->tmp_key.
530 */
531 static void
532 finish_key( gpgme_ctx_t ctx )
533 {
534 gpgme_key_t key = ctx->tmp_key;
535 struct key_queue_item_s * q, * q2;
536
537 assert( key );
538 ctx->tmp_key = NULL;
539
540 q = malloc( sizeof *q );
541 if( !q ) {
542 gpgme_key_release( key );
543 ctx->out_of_core = 1;
544 return;
545 }
546 q->key = key;
547 q->next = NULL;
548 /* fixme: lock queue. Use a tail pointer? */
549 q2 = ctx->key_queue;
550 if( !q2 )
551 ctx->key_queue = q;
552 else {
553 for( ; q2->next; q2 = q2->next )
554 ;
555 q2->next = q;
556 }
557 ctx->key_cond = 1;
558 /* fixme: unlock queue */
559 }
560
561
562
563 /**
564 * gpgme_op_keylist_start:
565 * @c: context
566 * @pattern: a GnuPg user ID or NULL for all
567 * @secret_only: List only keys where the secret part is available
568 *
569 * Note that this function also cancels a pending key listing operaton..
570 *
571 * Return value: 0 on success or an errorcode.
572 **/
573 gpgme_error_t
574 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
575 {
576 gpgme_error_t rc = 0;
577
578 if (!ctx)
579 return mk_error (Invalid_Value);
580 ctx->pending = 1;
581
582 _gpgme_release_result (ctx);
583 ctx->out_of_core = 0;
584 ctx->cb.progess_tmp = 0;
585
586 _gpgme_gpg_release (&ctx->gpg);
587 gpgme_key_release (ctx->tmp_key);
588 ctx->tmp_key = NULL;
589 /* Fixme: release key_queue */
590
591 rc = _gpgme_gpg_new (&ctx->gpg);
592 if (rc)
593 goto leave;
594
595 _gpgme_gpg_set_status_handler (ctx->gpg, keylist_status_handler, ctx);
596 rc = _gpgme_gpg_set_colon_line_handler (ctx->gpg, keylist_colon_handler, ctx);
597 if (rc)
598 goto leave;
599
600 /* build the commandline */
601 if (ctx->use_logging)
602 _gpgme_gpg_set_logging_handler (ctx->gpg, ctx);
603 _gpgme_gpg_set_list_options (ctx->gpg, ctx->list_opts);
604 _gpgme_gpg_add_arg (ctx->gpg, "--with-colons");
605 _gpgme_gpg_add_arg (ctx->gpg, "--fixed-list-mode");
606 _gpgme_gpg_add_arg (ctx->gpg, "--with-fingerprint");
607 _gpgme_gpg_add_arg (ctx->gpg, "--with-fingerprint"); /* for the subkey */
608 if (ctx->keylist_mode & 1)
609 _gpgme_gpg_add_arg (ctx->gpg, "--no-expensive-trust-checks");
610 if (ctx->keylist_mode & 2)
611 _gpgme_gpg_add_arg (ctx->gpg, "--with-key-data");
612 if (ctx->keylist_mode & 4)
613 _gpgme_gpg_add_arg (ctx->gpg, "--fast-list-mode");
614 if (secret_only)
615 _gpgme_gpg_add_arg (ctx->gpg, "--list-secret-keys");
616 else {
617 if (ctx->keylist_mode & 8)
618 _gpgme_gpg_add_arg (ctx->gpg, "--check-sigs");
619 else
620 _gpgme_gpg_add_arg (ctx->gpg, "--list-keys");
621 }
622
623 /* Tell the gpg object about the data */
624 _gpgme_gpg_add_arg ( ctx->gpg, "--" );
625 if( pattern && *pattern )
626 _gpgme_gpg_add_arg ( ctx->gpg, pattern );
627
628 /* and kick off the process */
629 rc = _gpgme_gpg_spawn ( ctx->gpg, ctx );
630
631 leave:
632 if( rc ) {
633 ctx->pending = 0;
634 _gpgme_gpg_release ( &ctx->gpg );
635 }
636 return rc;
637 }
638
639
640 gpgme_error_t
641 gpgme_op_keylist_next( gpgme_ctx_t ctx, gpgme_key_t * r_key )
642 {
643 struct key_queue_item_s * q;
644
645 if( !r_key )
646 return mk_error( Invalid_Value );
647 *r_key = NULL;
648 if( !ctx )
649 return mk_error( Invalid_Value );
650 if( !ctx->pending )
651 return mk_error( No_Request );
652 if( ctx->out_of_core )
653 return mk_error( Out_Of_Core );
654
655 if( !ctx->key_queue ) {
656 _gpgme_wait_on_condition( ctx, 1, &ctx->key_cond );
657 if ( ctx->out_of_core )
658 return mk_error( Out_Of_Core );
659 if( !ctx->key_cond )
660 return mk_error( EOF );
661 ctx->key_cond = 0;
662 assert ( ctx->key_queue );
663 }
664 q = ctx->key_queue;
665 ctx->key_queue = q->next;
666
667 *r_key = q->key;
668 safe_free (q);
669 return 0;
670 }
671
672
673 gpgme_error_t
674 gpgme_op_keylist_getkey (int is_sec, const char *pattern, gpgme_key_t *r_key)
675 {
676 gpgme_ctx_t listctx;
677 gpgme_error_t err;
678
679 err = gpgme_new (&listctx);
680 if (err)
681 return err;
682 err = gpgme_op_keylist_start (listctx, pattern, is_sec);
683 if (!err)
684 err = gpgme_op_keylist_next (listctx, r_key);
685 gpgme_release (listctx);
686 return err;
687 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26