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

Annotation of /trunk/MyGPGME/keylist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (hide annotations)
Wed Jul 27 11:17:44 2005 UTC (19 years, 7 months ago) by twoaday
File MIME type: text/plain
File size: 19810 byte(s)
2005-07-22  Timo Schulz  <twoaday@freakmail.de>
 
        * gpgme.c (_gpgme_add_comment): Forgot to alloc an extra
        byte for the '0'. This fixes a lot of crashes related to
        file operations.
        * keylist.c (gpgme_op_keylist_getkey): Use the param for
        'pub' or 'sec' mode.
        * keycache.c (gpgme_keycache_update_key): If the key is
        not in the cache, add it and if the cache contain secret
        key, sync it with the pub cache.
        * editkey.c (edit_key_colon_handler): Allocate 1 byte for
        the NUL-char.  This also fixes a lot of reported crashes
        related to the showpref feature.
 


1 twoaday 2 /* keylist.c - key listing
2     * Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH
3 twoaday 17 * Copyright (C) 2002-2005 Timo Schulz
4 twoaday 2 *
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     case 3: /* key length */
334     i = atoi( p );
335     if ( i > 1 ) /* ignore invalid values */
336     sk->key_len = i;
337     break;
338     case 4: /* pubkey algo */
339     i = atoi( p );
340     if( i > 0 && i < 128 )
341     sk->key_algo = i;
342     break;
343     case 5: /* long keyid */
344     memset (sk->keyid, 0, sizeof sk->keyid);
345     strncpy (sk->keyid, p, DIM (sk->keyid)-1);
346     break;
347     case 6: /* timestamp (1998-02-28) */
348     sk->timestamp = parse_timestamp( p );
349     break;
350     case 7: /* valid for n days */
351     sk->expires = parse_timestamp( p );
352     break;
353     case 8: /* reserved (LID) */
354     break;
355     case 9: /* ownertrust */
356     break;
357     case 10:/* user ID n/a for a subkey */
358     break;
359     case 11: /* signature class */
360     break;
361     case 12: /* capability */
362     set_subkey_capability ( sk, p );
363     break;
364     case 15:
365     memset (sk->cardno, 0, sizeof sk->cardno);
366     strncpy (sk->cardno, p, DIM (sk->cardno)-1);
367     pend = NULL; /* we can stop here */
368     break;
369     }
370     }
371     else if (rectype == RT_UID)
372     {
373     switch (field)
374     {
375     case 2: /* trust info */
376     trust_info = p; /* save for later use */
377     break;
378     case 6: /* creation date */
379     if (p)
380     val = parse_timestamp (p);
381     break;
382    
383     case 8: /* hash over name */
384     break;
385    
386     case 10: /* user ID */
387     safe_free (ctx->tmp_id);
388     ctx->tmp_id = strdup (p);
389     if (!ctx->tmp_id) {
390     ctx->out_of_core = 1;
391     break;
392     }
393     if (_gpgme_key_append_name (key, p, &u))
394     ctx->out_of_core = 1;
395     else if (trust_info)
396     set_userid_flags (u, trust_info);
397     if (sig) {
398     safe_free (sig->issuer);
399     sig->issuer = calloc (1, strlen (p) + 1);
400     if (!sig->issuer) {
401     ctx->out_of_core = 1;
402     break;
403     }
404     _gpgme_decode_c_string (p, &sig->issuer, strlen (p)+ 1);
405     }
406     u->created = val;
407     pend = NULL; /* we can stop here */
408     break;
409     }
410     }
411     else if( rectype == RT_FPR ) {
412     int nfpr = ctx->tmp_i;
413     switch( field ) {
414     case 10:
415     for( s = &key->keys; s && nfpr; s = s->next, nfpr-- )
416     ;
417     if( s ) {
418     s->fingerprint = strdup( p );
419     if( !s->fingerprint ) {
420     ctx->out_of_core = 1;
421     break;
422     }
423     }
424     pend = NULL; /* that is all we want */
425     ctx->tmp_i++;
426     break;
427     }
428     }
429     else if( rectype == RT_SIG ) {
430     switch( field ) {
431     case 2: /* signature state */
432     switch( *p ) {
433     case '!': sig->stat = GPGME_SIG_STAT_GOOD; break;
434     case '-': sig->stat = GPGME_SIG_STAT_BAD; break;
435     case '?': sig->stat = GPGME_SIG_STAT_NOKEY; break;
436     case '%': sig->stat = GPGME_SIG_STAT_ERROR; break;
437     default : sig->stat = GPGME_SIG_STAT_NONE; break;
438     }
439     break;
440    
441     case 4: /* pk algorithm */
442     sig->algo = atol (p);
443     break;
444    
445     case 5: /* long keyid */
446     memset (sig->keyid, 0, sizeof sig->keyid);
447     strncpy (sig->keyid, p, DIM (sig->keyid)-1);
448     break;
449    
450     case 6: /* created */
451     sig->created = parse_timestamp( p );
452     break;
453    
454     case 7: /* expires */
455     sig->expires = parse_timestamp( p );
456     break;
457    
458     case 10:
459     if( p ) {
460     sig->issuer = calloc( 1, strlen( p ) + 1 );
461     if( !sig->issuer ) {
462     ctx->out_of_core = 1;
463     break;
464     }
465     _gpgme_decode_c_string( p, &sig->issuer, strlen( p ) + 1 );
466     }
467     break;
468    
469     case 11:
470     sig->sigclass = strtoul( p, NULL, 16 );
471     if (strchr (p, 'l'))
472     sig->is_local = 1;
473     /*if (strchr (p, ' '))
474     sig->is_nonrev = 1;*/
475     if (sig->sigclass < 0x10 || sig->sigclass > 0x13) {
476     /* we only want certificates and no key signatures */
477     pend = NULL;
478     break;
479     }
480     if( ctx->tmp_id ) {
481     sig->user_id = calloc( 1, strlen( ctx->tmp_id ) + 1 );
482     if( !sig->user_id ) {
483     ctx->out_of_core = 1;
484     break;
485     }
486     _gpgme_decode_c_string( ctx->tmp_id, &sig->user_id, strlen( ctx->tmp_id ) +1 );
487     }
488     pend = NULL; /* we can stop here */
489     break;
490     }
491     }
492     else if( rectype == RT_PKD ) {
493     switch( field ) {
494     case 1:
495     m = calloc( 1, sizeof * m );
496     if( !m ) {
497     ctx->out_of_core = 1;
498     return;
499     }
500     for( mt=key->pkey; mt->next; mt=mt->next )
501     ;
502     mt->next = m;
503     break;
504    
505     case 2:
506     if( m )
507     m->bits = atol( p );
508     break;
509    
510     case 3:
511     if( m ) {
512     m->hexval = strdup( p );
513     if( !m->hexval )
514     ctx->out_of_core=1;
515     }
516     break;
517     }
518     }
519     }
520    
521     }
522    
523    
524     /*
525     * We have read an entire key into ctx->tmp_key and should now finish
526     * it. It is assumed that this releases ctx->tmp_key.
527     */
528     static void
529     finish_key( gpgme_ctx_t ctx )
530     {
531     gpgme_key_t key = ctx->tmp_key;
532     struct key_queue_item_s * q, * q2;
533    
534     assert( key );
535     ctx->tmp_key = NULL;
536    
537     q = malloc( sizeof *q );
538     if( !q ) {
539     gpgme_key_release( key );
540     ctx->out_of_core = 1;
541     return;
542     }
543     q->key = key;
544     q->next = NULL;
545     /* fixme: lock queue. Use a tail pointer? */
546     q2 = ctx->key_queue;
547     if( !q2 )
548     ctx->key_queue = q;
549     else {
550     for( ; q2->next; q2 = q2->next )
551     ;
552     q2->next = q;
553     }
554     ctx->key_cond = 1;
555     /* fixme: unlock queue */
556     }
557    
558    
559    
560     /**
561     * gpgme_op_keylist_start:
562     * @c: context
563     * @pattern: a GnuPg user ID or NULL for all
564     * @secret_only: List only keys where the secret part is available
565     *
566     * Note that this function also cancels a pending key listing operaton..
567     *
568     * Return value: 0 on success or an errorcode.
569     **/
570     gpgme_error_t
571     gpgme_op_keylist_start( gpgme_ctx_t ctx, const char *pattern, int secret_only )
572     {
573     gpgme_error_t rc = 0;
574    
575     if( !ctx )
576     return mk_error( Invalid_Value );
577     ctx->pending = 1;
578    
579     _gpgme_release_result( ctx );
580     ctx->out_of_core = 0;
581     ctx->cb.progess_tmp = 0;
582    
583     _gpgme_gpg_release( &ctx->gpg );
584     gpgme_key_release( ctx->tmp_key );
585     ctx->tmp_key = NULL;
586     /* Fixme: release key_queue */
587    
588     rc = _gpgme_gpg_new( &ctx->gpg );
589     if( rc )
590     goto leave;
591    
592     _gpgme_gpg_set_status_handler( ctx->gpg, keylist_status_handler, ctx );
593     rc = _gpgme_gpg_set_colon_line_handler( ctx->gpg, keylist_colon_handler, ctx );
594     if ( rc )
595     goto leave;
596    
597     /* build the commandline */
598     if (ctx->use_logging)
599     _gpgme_gpg_set_logging_handler (ctx->gpg, ctx);
600     _gpgme_gpg_set_list_options (ctx->gpg, ctx->list_opts);
601     _gpgme_gpg_add_arg( ctx->gpg, "--with-colons" );
602     _gpgme_gpg_add_arg( ctx->gpg, "--fixed-list-mode" );
603     _gpgme_gpg_add_arg( ctx->gpg, "--with-fingerprint" );
604     _gpgme_gpg_add_arg( ctx->gpg, "--with-fingerprint" ); /* for the subkey */
605     if( ctx->keylist_mode & 1 )
606     _gpgme_gpg_add_arg( ctx->gpg, "--no-expensive-trust-checks" );
607     if( ctx->keylist_mode & 2 )
608     _gpgme_gpg_add_arg( ctx->gpg, "--with-key-data" );
609     if( ctx->keylist_mode & 4 )
610     _gpgme_gpg_add_arg( ctx->gpg, "--fast-list-mode" );
611     if( 1 || !ctx->keylist_mode ) /* XXX: do all combinations make sense? */
612     _gpgme_gpg_add_arg( ctx->gpg, "-vvv" ); /* to list and check sigs */
613     _gpgme_gpg_add_arg ( ctx->gpg, secret_only?
614     "--list-secret-keys": /*"--list-keys"*/ "-k" );
615    
616     /* Tell the gpg object about the data */
617     _gpgme_gpg_add_arg ( ctx->gpg, "--" );
618     if( pattern && *pattern )
619     _gpgme_gpg_add_arg ( ctx->gpg, pattern );
620    
621     /* and kick off the process */
622     rc = _gpgme_gpg_spawn ( ctx->gpg, ctx );
623    
624     leave:
625     if( rc ) {
626     ctx->pending = 0;
627     _gpgme_gpg_release ( &ctx->gpg );
628     }
629     return rc;
630     }
631    
632    
633     gpgme_error_t
634     gpgme_op_keylist_next( gpgme_ctx_t ctx, gpgme_key_t * r_key )
635     {
636     struct key_queue_item_s * q;
637    
638     if( !r_key )
639     return mk_error( Invalid_Value );
640     *r_key = NULL;
641     if( !ctx )
642     return mk_error( Invalid_Value );
643     if( !ctx->pending )
644     return mk_error( No_Request );
645     if( ctx->out_of_core )
646     return mk_error( Out_Of_Core );
647    
648     if( !ctx->key_queue ) {
649     _gpgme_wait_on_condition( ctx, 1, &ctx->key_cond );
650     if ( ctx->out_of_core )
651     return mk_error( Out_Of_Core );
652     if( !ctx->key_cond )
653     return mk_error( EOF );
654     ctx->key_cond = 0;
655     assert ( ctx->key_queue );
656     }
657     q = ctx->key_queue;
658     ctx->key_queue = q->next;
659    
660     *r_key = q->key;
661 twoaday 17 safe_free (q);
662 twoaday 2 return 0;
663     }
664 twoaday 17
665    
666     gpgme_error_t
667 twoaday 21 gpgme_op_keylist_getkey (int is_sec, const char *pattern, gpgme_key_t *r_key)
668 twoaday 17 {
669     gpgme_ctx_t listctx;
670     gpgme_error_t err;
671    
672     err = gpgme_new (&listctx);
673     if (err)
674     return err;
675 twoaday 21 err = gpgme_op_keylist_start (listctx, pattern, is_sec);
676 twoaday 17 if (!err)
677     err = gpgme_op_keylist_next (listctx, r_key);
678     gpgme_release (listctx);
679     return err;
680     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26