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

Annotation of /trunk/MyGPGME/verify.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Mon Apr 4 07:01:43 2005 UTC (19 years, 10 months ago) by twoaday
File MIME type: text/plain
File size: 22173 byte(s)
2005-03-22  Timo Schulz  <twoaday@freakmail.de>
                                                                                
        * editcard.c: Support new status-fd entries SC_OP_SUCCESS
        and SC_OP_FAILURE.
        * editkey.c (cmd_addrev_handler): Check if context != NULL.
        * import.c (import_command_handler): Wrong function signature.
        Noted by Kurt Fitzner.
        * types.h: Fixed encrypt_result_s. Noted by Kurt.
        * gpgme.h (gpgme_editkey_addrev_set): Changed return type.
        Kudos to Kurt.
        * key.c: Removed some unreachable code. By Kurt.
                                                                                


1 twoaday 2 /* verify.c - signature verification
2     * Copyright (C) 2000 Werner Koch (dd9jn)
3     * Copyright (C) 2001-2004 Timo Schulz
4     *
5     * This file is part of MyGPGME.
6     *
7     * MyGPGME is safe_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 <ctype.h>
26     #include <assert.h>
27    
28     #include "util.h"
29     #include "context.h"
30     #include "ops.h"
31     #include "gpgme.h"
32    
33     struct verify_result_s {
34     struct verify_result_s * next;
35     gpgme_sigstat_t status;
36     gpgme_data_t notation; /* we store an XML fragment here */
37     int collecting; /* private to finish_sig() */
38     int notation_in_data; /* private to add_notation() */
39     char fpr[41]; /* fingerprint of a good signature or keyid of a bad one*/
40     ulong timestamp; /* signature creation time */
41     ulong exptime; /* signature expiration time */
42     unsigned expired:1;
43     int trust;
44     int key_algo;
45     int md_algo;
46     int sig_class;
47     char * user_id;
48     char * policy_url;
49     char * key_server;
50     char * file_name;
51     };
52    
53    
54     void
55     _gpgme_release_verify_result(_verify_result_t res)
56     {
57     while (res) {
58     _verify_result_t r2 = res->next;
59     gpgme_data_release (res->notation);
60     safe_free (res->user_id);
61     safe_free (res->policy_url );
62     safe_free (res->file_name);
63     safe_free (res->key_server);
64     safe_free (res);
65     res = r2;
66     }
67     } /* _gpgme_release_verify_result */
68    
69    
70     /*
71     * finish a pending signature info collection and prepare for a new
72     * signature info collection
73     */
74     static void
75     finish_sig( gpgme_ctx_t ctx, int stop )
76     {
77     if( stop )
78     return; /* nothing to do */
79    
80     if( ctx->result.verify->collecting ) {
81     _verify_result_t res2;
82    
83     ctx->result.verify->collecting = 0;
84     /* create a new result structure */
85     res2 = calloc ( 1, sizeof *res2 );
86     if( !res2 ) {
87     ctx->out_of_core = 1;
88     return;
89     }
90     res2->next = ctx->result.verify;
91     ctx->result.verify = res2;
92     }
93    
94     ctx->result.verify->collecting = 1;
95     } /* finish_sig */
96    
97    
98     static char *
99     read_val( const char * args, int *ret_i )
100     {
101     static char buf[32];
102     int i = *ret_i, pos = 0;
103    
104     for( ; args[i] && args[i] != ' '; i++ )
105     buf[pos++] = args[i];
106     buf[pos] = '\0';
107     *ret_i = ++i;
108     return buf;
109     } /* read_val */
110    
111    
112     static int
113     read_int_val( const char * args, int *ret_i )
114     {
115     char * p = read_val( args, ret_i );
116     return atol( p );
117     } /* read_int_val */
118    
119    
120     static unsigned
121     read_unsigned_val( const char * args, int *ret_i )
122     {
123     char * p = read_val( args, ret_i );
124     return strtoul( p, NULL, 10 );
125     } /* read_unsigned_val */
126    
127    
128     static void
129     verify_status_handler( gpgme_ctx_t ctx, gpg_status_code_t code, char * args )
130     {
131     gpgme_data_t in;
132     char * p;
133     int i, j, rc = 0;
134    
135     if( ctx->out_of_core )
136     return;
137     if( ctx->result_type == RESULT_TYPE_NONE ) {
138     assert ( !ctx->result.verify );
139     ctx->result.verify = calloc( 1, sizeof *ctx->result.verify );
140     if( !ctx->result.verify ) {
141     ctx->out_of_core = 1;
142     return;
143     }
144     ctx->result_type = RESULT_TYPE_VERIFY;
145     }
146     assert( ctx->result_type == RESULT_TYPE_VERIFY );
147    
148     if( code == STATUS_GOODSIG
149     || code == STATUS_REVKEYSIG
150     || code == STATUS_EXPKEYSIG
151     || code == STATUS_BADSIG
152     || code == STATUS_ERRSIG ) {
153     finish_sig( ctx, 0 );
154     if( ctx->out_of_core )
155     return;
156     }
157    
158     _gpgme_sigtrust_status_handler (code, args, &ctx->result.verify->trust);
159    
160     switch( code ) {
161     case STATUS_FILE_START:
162     if( *args++ == '1' ) {
163     args++;
164     p = ctx->result.verify->file_name = strdup( args );
165     if( !p ) {
166     ctx->out_of_core = 1;
167     return;
168     }
169     }
170     break;
171    
172     case STATUS_FILE_DONE:
173     break;
174    
175     case STATUS_GOODSIG: /* use it to get the user-id */
176     ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
177     i = 0;
178     while( args[i] && args[i] == ' ' ) /* skip keyid */
179     i++;
180     while( args[i] && args[i] != ' ' )
181     i++;
182     ctx->result.verify->user_id = p = calloc( 1, strlen( args+i ) + 2 );
183     if( !p ) {
184     ctx->out_of_core = 1;
185     return;
186     }
187     j = 0;
188     while( args[i] )
189     p[j++] = args[i++];
190     p[j++] = '\0';
191     break;
192    
193     case STATUS_BADSIG:
194     ctx->result.verify->status = GPGME_SIG_STAT_BAD;
195     p = ctx->result.verify->fpr; /* store the keyID in the fpr field */
196     for( i = 0; i < DIM(ctx->result.verify->fpr)
197     && args[i] && args[i] != ' ' ; i++ )
198     *p++ = args[i];
199     *p = '\0';
200     p = ctx->result.verify->user_id = calloc( 1, strlen( args+i ) + 2 );
201     if( !p ) {
202     ctx->out_of_core = 1;
203     return;
204     }
205     j = 0;
206     while( args[i] )
207     p[j++] = args[i++];
208     p[j++] = '\0';
209     break;
210    
211     case STATUS_EXPKEYSIG:
212     case STATUS_REVKEYSIG:
213     if( code == STATUS_EXPKEYSIG )
214     ctx->result.verify->status = GPGME_SIG_STAT_E_GOOD;
215     else if( code == STATUS_REVKEYSIG )
216     ctx->result.verify->status = GPGME_SIG_STAT_R_GOOD;
217     for( i=0, p=ctx->result.verify->fpr;
218     args[i] && args[i] != ' '; i++ )
219     *p++ = args[i];
220     *p = '\0';
221     p = ctx->result.verify->user_id = calloc( 1, strlen( args+i ) + 2 );
222     if( !p ) {
223     ctx->out_of_core = 1;
224     return;
225     }
226     j=0;
227     while( args[i] )
228     p[j++] = args[i++];
229     p[j++] = '\0';
230     break;
231    
232     case STATUS_VALIDSIG:
233     p = ctx->result.verify->fpr;
234     for( i = 0; i < DIM(ctx->result.verify->fpr)
235     && args[i] && args[i] != ' ' ; i++ )
236     *p++ = args[i];
237     *p = 0;
238     /* skip the formatted date */
239     while( args[i] && args[i] == ' ')
240     i++;
241     while( args[i] && args[i] != ' ')
242     i++;
243     /* and get the timestamp */
244     ctx->result.verify->timestamp = strtoul( args+i, NULL, 10 );
245     /* and the expire timestamp */
246     while( args[i] && args[i] == ' ' )
247     i++;
248     while( args[i] && args[i] != ' ' )
249     i++;
250     ctx->result.verify->exptime = strtoul( args+i, NULL, 10 );
251     break;
252    
253     case STATUS_ERRSIG:
254     ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
255     p = ctx->result.verify->fpr;
256     for( i = 0; i < DIM(ctx->result.verify->fpr )
257     && args[i] && args[i] != ' ' ; i++ )
258     *p++ = args[i];
259     *p = 0;
260     i++;
261     ctx->result.verify->key_algo = read_int_val( args, &i );
262     ctx->result.verify->md_algo = read_int_val( args, &i );
263     ctx->result.verify->sig_class = read_int_val( args, &i );
264     ctx->result.verify->timestamp = read_unsigned_val( args, &i );
265     rc = read_int_val( args, &i );
266     if( rc == 9 )
267     ctx->result.verify->status = GPGME_SIG_STAT_NOKEY;
268     break;
269    
270     case STATUS_EXPSIG:
271     ctx->result.verify->expired = 1;
272     break;
273    
274     case STATUS_NO_PUBKEY:
275     ctx->result.verify->status = GPGME_SIG_STAT_NOKEY;
276     break;
277    
278     case STATUS_NOTATION_NAME:
279     if( !ctx->result.verify->notation )
280     gpgme_data_new( &ctx->result.verify->notation );
281     in = ctx->result.verify->notation;
282     gpgme_data_write( in, args, strlen( args ) );
283     gpgme_data_write( in, "=", 1 );
284     break;
285    
286     case STATUS_NOTATION_DATA:
287     in = ctx->result.verify->notation;
288     for( i = 0; args[i] && in; i++ ) {
289     if( args[i] == '%' ) {
290     gpgme_data_putc( in, ' ' );
291     i += 2;
292     }
293     else
294     gpgme_data_putc( in, args[i] );
295     }
296     break;
297    
298     case STATUS_SIG_SUBPACKET:
299     i=0;
300     read_int_val (args, &i);
301     read_int_val (args, &i);
302     j = read_int_val (args, &i);
303     p = ctx->result.verify->key_server = calloc (1, j+1);
304     if (!p) {
305     ctx->out_of_core = 1;
306     break;
307     }
308     memcpy (p, args+i, j);
309     break;
310    
311     case STATUS_POLICY_URL:
312     p = ctx->result.verify->policy_url = strdup (args);
313     if (!p)
314     ctx->out_of_core = 1;
315     break;
316    
317     case STATUS_EOF:
318     finish_sig( ctx, 1 );
319     break;
320     }
321     } /* verify_status_handler */
322    
323    
324     static const char *
325     verify_command_handler( void *opaque, gpg_status_code_t code, const char *key )
326     {
327     gpgme_ctx_t ctx = opaque;
328    
329     if( !code || !key )
330     return NULL;
331    
332     if( code == STATUS_GET_LINE && !strcmp( key, "detached_signature.filename" ) )
333     return ctx->tmp_id;
334    
335     return NULL;
336     } /* verify_command_handler */
337    
338    
339     static long
340     verify_get_sig_date( gpgme_data_t sig )
341     {
342     gpgme_ctx_t ctx;
343     gpgme_data_t out;
344     gpgme_error_t rc;
345     const char * s;
346     char buf[128], tbuf[32];
347     size_t nread = 0, i = 0;
348     long timestamp = 0;
349    
350     rc = gpgme_new( &ctx );
351     if( rc )
352     return 0;
353     gpgme_data_rewind( sig );
354     gpgme_data_read( sig, buf, 40, &nread );
355    
356     _gpgme_gpg_new( &ctx->gpg );
357     _gpgme_gpg_add_arg( ctx->gpg, "--list-packets" );
358     gpgme_data_new( &out );
359     _gpgme_data_set_mode( out, GPGME_DATA_MODE_IN );
360    
361     _gpgme_gpg_add_arg( ctx->gpg, "--output" );
362     _gpgme_gpg_add_arg( ctx->gpg, "-" );
363     _gpgme_gpg_add_data( ctx->gpg, out, 1 );
364     _gpgme_gpg_add_arg( ctx->gpg, "--" );
365     _gpgme_gpg_add_data( ctx->gpg, sig, 0 );
366    
367     rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
368     if( !rc ) {
369     gpgme_wait( ctx, 1 );
370     nread = gpgme_data_readline( out, buf, sizeof buf-1 );
371     if( !nread )
372     goto end;
373     nread = gpgme_data_readline( out, buf, sizeof buf -1 );
374     if( !nread )
375     goto end;
376     s = buf;
377     while( s && (*s == ' ' || * s == '\t') )
378     s++;
379     if( strstr( s, "version" ) && strlen( s ) > 20 ) {
380     s += 19;
381     while( isdigit( *s ) ) {
382     tbuf[i++] = *s;
383     s++;
384     }
385     tbuf[i++] = '\0';
386     timestamp = atol( tbuf );
387     }
388     }
389    
390     end:
391     gpgme_data_release( out );
392     gpgme_release( ctx );
393     return timestamp;
394     }
395    
396    
397     static gpgme_error_t
398     verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t text)
399     {
400     gpgme_error_t rc = 0;
401    
402     fail_on_pending_request( ctx );
403     ctx->pending = 1;
404    
405     _gpgme_release_result( ctx );
406     ctx->out_of_core = 0;
407    
408     _gpgme_gpg_release( &ctx->gpg );
409     rc = _gpgme_gpg_new ( &ctx->gpg );
410     if( rc )
411     goto leave;
412    
413     if( ctx->use_logging )
414     _gpgme_gpg_set_logging_handler( ctx->gpg, ctx );
415     _gpgme_gpg_set_status_handler( ctx->gpg, verify_status_handler, ctx );
416    
417     /* build the commandline */
418     _gpgme_gpg_add_arg ( ctx->gpg, "--verify" );
419     /* Check the supplied data */
420     if( gpgme_data_get_type( sig ) == GPGME_DATA_TYPE_NONE ) {
421     rc = mk_error( No_Data );
422     goto leave;
423     }
424     if( text && gpgme_data_get_type( text ) == GPGME_DATA_TYPE_NONE ) {
425     rc = mk_error( No_Data );
426     goto leave;
427     }
428     _gpgme_data_set_mode( sig, GPGME_DATA_MODE_OUT );
429     if (text) /* detached signature */
430     _gpgme_data_set_mode (text, GPGME_DATA_MODE_OUT);
431     /* Tell the gpg object about the data */
432     _gpgme_gpg_add_arg (ctx->gpg, "--");
433     _gpgme_gpg_add_data (ctx->gpg, sig, -1);
434     if (text) {
435     _gpgme_gpg_add_arg (ctx->gpg, "-");
436     _gpgme_gpg_add_data (ctx->gpg, text, 0);
437     }
438    
439     /* and kick off the process */
440     rc = _gpgme_gpg_spawn (ctx->gpg, ctx);
441    
442     leave:
443     if( rc ) {
444     ctx->pending = 0;
445     _gpgme_gpg_release( &ctx->gpg );
446     }
447    
448     return rc;
449     } /* verify_start */
450    
451    
452     static gpgme_error_t
453     file_verify_start( gpgme_ctx_t ctx, gpgme_sigmode_t sigmode ,
454     const char ** sigfile, size_t nfiles, const char * datfile )
455     {
456     gpgme_error_t rc = 0;
457    
458     fail_on_pending_request( ctx );
459     ctx->pending = 1;
460    
461     _gpgme_gpg_release( &ctx->gpg );
462     rc = _gpgme_gpg_new( &ctx->gpg );
463     if( rc ) {
464     _gpgme_gpg_release( &ctx->gpg );
465     return rc;
466     }
467    
468     _gpgme_gpg_set_status_handler( ctx->gpg, verify_status_handler, ctx );
469     _gpgme_gpg_set_command_handler( ctx->gpg, verify_command_handler, ctx );
470    
471     _gpgme_gpg_add_arg( ctx->gpg, "--yes" );
472     if( ctx->pipemode || nfiles > 1 )
473     _gpgme_gpg_add_arg( ctx->gpg, "--verify-files" );
474     else if( sigmode != GPGME_SIG_MODE_DETACH )
475     _gpgme_gpg_add_arg( ctx->gpg, "--verify" );
476     else {
477     ctx->tmp_id = strdup( datfile );
478     if( !ctx->tmp_id ) {
479     ctx->out_of_core = 1;
480     return mk_error( Out_Of_Core );
481     }
482     }
483    
484     while( nfiles-- )
485     _gpgme_gpg_add_arg( ctx->gpg, *sigfile++ );
486    
487     rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
488     if( rc ) {
489     ctx->pending = 0;
490     _gpgme_gpg_release( &ctx->gpg );
491     }
492    
493     return rc;
494     } /* gpgme_file_verify_start */
495    
496    
497     /*
498     * Figure out a common status value for all signatures
499     */
500     static gpgme_sigstat_t
501     intersect_stati( _verify_result_t res )
502     {
503     gpgme_sigstat_t status = res->status;
504    
505     for( res = res->next; res; res = res->next ) {
506     if( status != res->status )
507     return GPGME_SIG_STAT_DIFF;
508     }
509    
510     return status;
511     } /* intersect_stati */
512    
513    
514     static char*
515     get_sig_userid( gpgme_ctx_t ctx, int idx )
516     {
517     _verify_result_t res;
518    
519     if( !ctx )
520     return NULL;
521     for( res = ctx->result.verify; res && idx>0; res = res->next, idx-- )
522     ;
523     if( !res )
524     return NULL;
525     return res->user_id? strdup( res->user_id ) : NULL;
526     } /* get_sig_userid */
527    
528    
529     static gpgme_error_t
530     read_sig_results( gpgme_ctx_t ctx, gpgme_sig_t * r_sigctx )
531     {
532     gpgme_sig_t root = NULL, node;
533     gpgme_error_t err;
534     size_t i, n;
535    
536     gpgme_get_sig_ctx( ctx, -1, &n, NULL );
537     for( i = 0; i < n; i++ ) {
538     err = gpgme_get_sig_ctx( ctx, i, NULL, &node );
539     if( !err ) {
540     if( node->sigstat != GPGME_SIG_STAT_NOKEY )
541     err = gpgme_get_sig_key( ctx, i, &node->key );
542     }
543     if( !root )
544     root = node;
545     else {
546     gpgme_sig_t s;
547     for( s = root; s->next; s = s->next )
548     ;
549     s->next = node;
550     }
551     }
552     *r_sigctx = root;
553     return err;
554     } /* read_sig_results */
555    
556    
557     /**
558     * gpgme_op_verify:
559     * @c: the context
560     * @sig: the signature data
561     * @text: the signed text
562     *
563     * Perform a signature check on the signature given in @sig. Currently it is
564     * assumed that this is a detached signature for the material given in @text.
565     * The result of this operation is returned via gpgme_get_sig_ctx ().
566     *
567     * Return value: 0 on success or an errorcode if something not related to
568     * the signature itself did go wrong.
569     **/
570     gpgme_error_t
571     gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t text)
572     {
573     gpgme_error_t rc;
574    
575     gpgme_data_release (ctx->notation);
576     ctx->notation = NULL;
577    
578     rc = verify_start( ctx, sig, text );
579     if( !rc ) {
580     gpgme_wait( ctx, 1 );
581     if( ctx->result_type != RESULT_TYPE_VERIFY )
582     rc = mk_error( General_Error );
583     else if ( ctx->out_of_core )
584     rc = mk_error( Out_Of_Core );
585     else {
586     assert ( ctx->result.verify );
587     if( ctx->result.verify->notation ) {
588     gpgme_data_t dh = ctx->result.verify->notation;
589     ctx->notation = dh;
590     ctx->result.verify->notation = NULL;
591     }
592     if( intersect_stati( ctx->result.verify ) == GPGME_SIG_STAT_BAD )
593     ctx->result.verify->timestamp = verify_get_sig_date( sig );
594     }
595     ctx->pending = 0;
596     }
597    
598     return rc;
599     } /* gpgme_op_verify */
600    
601    
602     gpgme_error_t
603     gpgme_op_file_verify( gpgme_ctx_t ctx, gpgme_sigmode_t sigmode,
604     gpgme_sig_t * r_sigctx,
605     const char * sigfile, const char * datfile )
606    
607     {
608     const char * s[1];
609     gpgme_error_t rc = 0;
610    
611     s[0] = sigfile;
612     rc = file_verify_start( ctx, sigmode, s, 1, datfile );
613     if( !rc ) {
614     gpgme_wait( ctx, 1 );
615     ctx->pending = 0;
616     if( ctx->result_type != RESULT_TYPE_VERIFY )
617     rc = mk_error( General_Error );
618     else if( ctx->out_of_core )
619     rc = mk_error( Out_Of_Core );
620     else {
621     assert( ctx->result.verify );
622     if( ctx->result.verify->notation ) {
623     gpgme_data_t dh = ctx->result.verify->notation;
624     ctx->notation = dh;
625     ctx->result.verify->notation = NULL;
626     }
627     if( intersect_stati( ctx->result.verify ) == GPGME_SIG_STAT_BAD ) {
628     gpgme_data_t sig;
629     rc = gpgme_data_new_from_file (&sig, sigfile);
630     if( !rc ) {
631     ctx->result.verify->timestamp = verify_get_sig_date( sig );
632     gpgme_data_release( sig );
633     }
634     }
635     rc = read_sig_results( ctx, r_sigctx );
636     }
637     }
638    
639     return rc;
640     } /* gpgme_op_file_verify */
641    
642    
643     gpgme_error_t
644     gpgme_op_files_verify( gpgme_ctx_t ctx, const char ** files, size_t nfiles,
645     gpgme_sig_t * ret_sig )
646     {
647     gpgme_error_t rc;
648    
649     rc = file_verify_start( ctx, 0, files, nfiles, NULL );
650     if( !rc ) {
651     gpgme_wait( ctx, 1 );
652     ctx->pending = 0;
653     if( ctx->result_type != RESULT_TYPE_VERIFY )
654     rc = mk_error( General_Error );
655     else if( ctx->out_of_core )
656     rc = mk_error( Out_Of_Core );
657     else
658     read_sig_results( ctx, ret_sig );
659     }
660     return rc;
661     }
662    
663    
664     /**
665     * gpgme_get_sig_ctx:
666     * @ctx: Context
667     * @idx: Index of the signature starting at 0
668     * @r_stat: Returns the status
669     * @r_created: Returns the creation timestamp
670     *
671     * Return information about an already verified signatures.
672     *
673     * Return value: The fingerprint or NULL in case of an problem or
674     * when there are no more signatures.
675     **/
676     gpgme_error_t
677     gpgme_get_sig_ctx (gpgme_ctx_t ctx, int idx, size_t * r_ncount,
678     gpgme_sig_t * r_sig )
679     {
680     _verify_result_t res;
681     gpgme_sig_t sig;
682     gpgme_error_t err;
683     int idx_old = idx;
684    
685     if( idx == -1 && !r_sig && r_ncount ) {
686     size_t n = 0;
687     for( res = ctx->result.verify; res; res = res->next )
688     n++;
689     *r_ncount = n;
690     }
691    
692     if (!r_sig)
693     return mk_error (Invalid_Value);
694     if (!ctx || ctx->pending || ctx->result_type != RESULT_TYPE_VERIFY)
695     return mk_error (General_Error); /* No results yet or verification error */
696    
697     for (res = ctx->result.verify; res && idx > 0 ; res = res->next, idx--)
698     ;
699     if (!res)
700     return mk_error (Invalid_Value); /* No more signatures */
701    
702     *r_sig = NULL;
703     err = gpgme_sig_new (&sig);
704     if (err)
705     return err;
706    
707     sig->flags.expired = res->expired;
708     sig->sigstat = res->status;
709     sig->created = res->timestamp;
710     sig->expired = res->exptime;
711     strcpy( sig->id, res->fpr );
712     sig->notation = gpgme_get_notation( ctx );
713     sig->trust = res->trust;
714     sig->key_algo = res->key_algo;
715     sig->md_algo = res->md_algo;
716 twoaday 7 sig->sigclass = res->sig_class;
717 twoaday 2 sig->user_id = get_sig_userid( ctx, idx_old );
718     sig->policy_url = res->policy_url? strdup (res->policy_url) : NULL;
719     sig->file_name = res->file_name? strdup (res->file_name) : NULL;
720     sig->key_server = res->key_server? strdup (res->key_server) : NULL;
721     *r_sig = sig;
722     return 0;
723     } /* gpgme_get_sig_ctx */
724    
725    
726     /**
727     * gpgme_get_sig_key:
728     * @c: context
729     * @idx: Index of the signature starting at 0
730     * @r_key: Returns the key object
731     *
732     * Return a key object which was used to check the signature.
733     *
734     * Return value: An Errorcode or 0 for success. GPGME_EOF is returned to
735     * indicate that there are no more signatures.
736     **/
737     gpgme_error_t
738     gpgme_get_sig_key( gpgme_ctx_t ctx, int idx, gpgme_key_t * r_key )
739     {
740     _verify_result_t res;
741     gpgme_ctx_t listctx = NULL;
742     gpgme_error_t err;
743    
744     if( !ctx || !r_key )
745     return mk_error( Invalid_Value );
746     if( ctx->pending || ctx->result_type != RESULT_TYPE_VERIFY )
747     return mk_error( Busy );
748    
749     for( res = ctx->result.verify; res && idx>0 ; res = res->next, idx-- )
750     ;
751     if( !res )
752     return mk_error( EOF );
753    
754     if( strlen( res->fpr ) < 16 ) /* we have at least an key ID */
755     return mk_error( Invalid_Key );
756    
757     if( ctx->key_lookup )
758     err = gpgme_keycache_find_key( ctx->key_lookup, res->fpr, 0, r_key );
759     else {
760     err = gpgme_new( &listctx );
761     if( !err ) {
762     gpgme_control( listctx, GPGME_CTRL_LISTMODE, listctx->keylist_mode );
763     err = gpgme_op_keylist_start( listctx, res->fpr, 0 );
764     }
765     if( !err )
766     err = gpgme_op_keylist_next( listctx, r_key );
767     gpgme_release( listctx );
768     }
769    
770     return err;
771     } /* gpgme_get_sig_key */
772    
773    
774     gpgme_error_t
775     gpgme_op_clip_verify (gpgme_keycache_t cache, gpgme_sig_t * r_sigctx)
776     {
777     gpgme_error_t err;
778     gpgme_data_t sig = NULL;
779     gpgme_ctx_t ctx = NULL;
780    
781    
782     err = gpgme_new (&ctx);
783     if (!err) {
784     if (cache)
785     gpgme_set_cache_ctx (ctx, cache);
786     }
787     if (!err)
788     err = gpgme_data_new_from_clipboard (&sig);
789     if (!err)
790     err = gpgme_op_verify (ctx, sig, NULL);
791     if (!err)
792     err = read_sig_results (ctx, r_sigctx);
793     gpgme_data_release (sig);
794     gpgme_release (ctx);
795    
796     return err;
797     } /* gpgme_op_clip_verify */
798    
799    
800     gpgme_error_t
801     gpgme_op_clip_verify_detached( gpgme_keycache_t cache, gpgme_sig_t * r_sigctx,
802     const char * data, size_t len )
803     {
804     gpgme_error_t err;
805     gpgme_data_t sig = NULL;
806     gpgme_data_t text = NULL;
807     gpgme_ctx_t ctx = NULL;
808    
809     err = gpgme_new( &ctx );
810     if( !err )
811     err = gpgme_data_new_from_mem( &text, data, len, 1 );
812     if( !err )
813     if( !err && cache )
814     gpgme_set_cache_ctx( ctx, cache );
815     if( !err )
816     err = gpgme_data_new_from_clipboard (&sig);
817     if( !err )
818     err = gpgme_op_verify( ctx, sig, text );
819     if( !err )
820     err = read_sig_results( ctx, r_sigctx );
821    
822     gpgme_data_release( sig );
823     gpgme_data_release( text );
824     gpgme_release( ctx );
825    
826     return err;
827     } /* gpgme_op_clip_verify_detached */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26