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

Contents of /trunk/MyGPGME/verify.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File MIME type: text/plain
File size: 21943 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


1 /* verify.c - signature verification
2 * Copyright (C) 2000 Werner Koch (dd9jn)
3 * Copyright (C) 2001-2005 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 if (code >= STATUS_TRUST_UNDEFINED && code <= STATUS_TRUST_ULTIMATE)
159 _gpgme_sigtrust_status_handler (code, args, &ctx->result.verify->trust);
160
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->use_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 sig->sigclass = res->sig_class;
718 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_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_op_keylist_getkey (0, res->fpr, r_key);
761
762 return err;
763 } /* gpgme_get_sig_key */
764
765
766 gpgme_error_t
767 gpgme_op_clip_verify (gpgme_keycache_t cache, gpgme_sig_t * r_sigctx)
768 {
769 gpgme_error_t err;
770 gpgme_data_t sig = NULL;
771 gpgme_ctx_t ctx = NULL;
772
773
774 err = gpgme_new (&ctx);
775 if (!err) {
776 if (cache)
777 gpgme_set_cache_ctx (ctx, cache);
778 }
779 if (!err)
780 err = gpgme_data_new_from_clipboard (&sig);
781 if (!err)
782 err = gpgme_op_verify (ctx, sig, NULL);
783 if (!err)
784 err = read_sig_results (ctx, r_sigctx);
785 gpgme_data_release (sig);
786 gpgme_release (ctx);
787
788 return err;
789 } /* gpgme_op_clip_verify */
790
791
792 gpgme_error_t
793 gpgme_op_clip_verify_detached( gpgme_keycache_t cache, gpgme_sig_t * r_sigctx,
794 const char * data, size_t len )
795 {
796 gpgme_error_t err;
797 gpgme_data_t sig = NULL;
798 gpgme_data_t text = NULL;
799 gpgme_ctx_t ctx = NULL;
800
801 err = gpgme_new( &ctx );
802 if( !err )
803 err = gpgme_data_new_from_mem( &text, data, len, 1 );
804 if( !err )
805 if( !err && cache )
806 gpgme_set_cache_ctx( ctx, cache );
807 if( !err )
808 err = gpgme_data_new_from_clipboard (&sig);
809 if( !err )
810 err = gpgme_op_verify( ctx, sig, text );
811 if( !err )
812 err = read_sig_results( ctx, r_sigctx );
813
814 gpgme_data_release( sig );
815 gpgme_data_release( text );
816 gpgme_release( ctx );
817
818 return err;
819 } /* gpgme_op_clip_verify_detached */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26