Add verify function
[gpgme.git] / gpgme / verify.c
1 /* verify.c -  signature verification
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GPGME is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "util.h"
28 #include "context.h"
29 #include "ops.h"
30
31 typedef enum {
32     VERIFY_STATUS_NONE = 0,
33     VERIFY_STATUS_NOSIG,
34     VERIFY_STATUS_NOKEY,
35     VERIFY_STATUS_ERROR,
36     VERIFY_STATUS_BAD,
37     VERIFY_STATUS_GOOD
38 } VerifyStatus;
39
40 struct verify_result_s {
41     VerifyStatus status;
42
43 };
44
45
46 void
47 _gpgme_release_verify_result ( VerifyResult res )
48 {
49     xfree (res);
50 }
51
52
53 static void
54 verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
55 {
56     if ( ctx->out_of_core )
57         return;
58     if ( ctx->result_type == RESULT_TYPE_NONE ) {
59         assert ( !ctx->result.verify );
60         ctx->result.verify = xtrycalloc ( 1, sizeof *ctx->result.verify );
61         if ( !ctx->result.verify ) {
62             ctx->out_of_core = 1;
63             return;
64         }
65         ctx->result_type = RESULT_TYPE_VERIFY;
66     }
67     assert ( ctx->result_type == RESULT_TYPE_VERIFY );
68
69     /* FIXME: For now we handle only one signature */
70     /* FIXME: Collect useful information */
71     switch (code) {
72       case STATUS_GOODSIG:
73         ctx->result.verify->status = VERIFY_STATUS_GOOD;
74         break;
75       case STATUS_BADSIG:
76         ctx->result.verify->status = VERIFY_STATUS_BAD;
77         break;
78       case STATUS_ERRSIG:
79         ctx->result.verify->status = VERIFY_STATUS_ERROR;
80         /* FIXME: distinguish between a regular error and a missing key.
81          * this is encoded in the args. */
82         break;
83       default:
84         /* ignore all other codes */
85         fprintf (stderr, "verify_status: code=%d not handled\n", code );
86         break;
87     }
88 }
89
90
91
92 GpgmeError
93 gpgme_start_verify ( GpgmeCtx c,  GpgmeData sig, GpgmeData text )
94 {
95     int rc = 0;
96     int i;
97
98     fail_on_pending_request( c );
99     c->pending = 1;
100
101     _gpgme_release_result (c);
102     c->out_of_core = 0;
103
104     /* create a process object.
105      * To optimize this, we should reuse an existing one and
106      * run gpg in the new --pipemode (I started with this but it is
107      * not yet finished) */
108     if ( c->gpg ) {
109         _gpgme_gpg_release_object ( c->gpg ); 
110         c->gpg = NULL;
111     }
112     rc = _gpgme_gpg_new_object ( &c->gpg );
113     if (rc)
114         goto leave;
115
116     _gpgme_gpg_set_status_handler ( c->gpg, verify_status_handler, c );
117
118     /* build the commandline */
119     _gpgme_gpg_add_arg ( c->gpg, "--verify" );
120     for ( i=0; i < c->verbosity; i++ )
121         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
122     
123
124     /* Check the supplied data */
125     if ( gpgme_query_data_type (sig) == GPGME_DATA_TYPE_NONE ) {
126         rc = mk_error (No_Data);
127         goto leave;
128     }
129     if ( text && gpgme_query_data_type (text) == GPGME_DATA_TYPE_NONE ) {
130         rc = mk_error (No_Data);
131         goto leave;
132     }
133     _gpgme_set_data_mode (sig, GPGME_DATA_MODE_OUT );
134     if (text) /* detached signature */
135         _gpgme_set_data_mode (text, GPGME_DATA_MODE_OUT );
136     /* Tell the gpg object about the data */
137     _gpgme_gpg_add_arg ( c->gpg, "--" );
138     _gpgme_gpg_add_data ( c->gpg, sig, -1 );
139     if (text)
140         _gpgme_gpg_add_data ( c->gpg, text, 0 );
141
142     /* and kick off the process */
143     rc = _gpgme_gpg_spawn ( c->gpg, c );
144
145  leave:
146     if (rc) {
147         c->pending = 0; 
148         _gpgme_gpg_release_object ( c->gpg ); c->gpg = NULL;
149     }
150     return rc;
151 }
152
153
154
155 GpgmeError
156 gpgme_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text )
157 {
158     int rc = gpgme_start_verify ( c, sig, text );
159     if ( !rc ) {
160         gpgme_wait (c, 1);
161         if ( c->result_type != RESULT_TYPE_VERIFY )
162             rc = mk_error (General_Error);
163         else if ( c->out_of_core )
164             rc = mk_error (Out_Of_Core);
165         else {
166             assert ( c->result.verify );
167             switch ( c->result.verify->status ) {
168               case VERIFY_STATUS_NONE:
169                 fputs ("Verification Status: None\n", stdout);
170                 break;
171               case VERIFY_STATUS_NOSIG:
172                 fputs ("Verification Status: No Signature\n", stdout);
173                 break;
174               case VERIFY_STATUS_GOOD:
175                 fputs ("Verification Status: Good\n", stdout);
176                 break;
177               case VERIFY_STATUS_BAD:
178                 fputs ("Verification Status: Bad\n", stdout);
179                 break;
180               case VERIFY_STATUS_NOKEY:
181                 fputs ("Verification Status: No Key\n", stdout);
182                 break;
183               case VERIFY_STATUS_ERROR:
184                 fputs ("Verification Status: Error\n", stdout);
185                 break;
186             }
187         }
188         c->pending = 0;
189     }
190     return rc;
191 }
192
193
194
195
196
197
198