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

Annotation of /trunk/MyGPGME/verify.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (hide annotations)
Wed Apr 13 11:10:53 2005 UTC (19 years, 10 months ago) by twoaday
File MIME type: text/plain
File size: 22244 byte(s)
Fix signature ownertrust code.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26