6cbfa4926aee74cc17be6b2723036c648806c4f9
[gpgol.git] / src / engine-gpgme.c
1 /* engine-gpgme.c - Crypto engine with GPGME
2  *      Copyright (C) 2005 g10 Code GmbH
3  *
4  * This file is part of GPGol.
5  *
6  * GPGol is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 
9  * of the License, or (at your option) any later version.
10  *  
11  * GPGol 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 GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with GPGol; if not, write to the Free Software Foundation, 
18  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
19  */
20
21 /* Please note that we assume UTF-8 strings everywhere except when
22    noted. */
23    
24
25 #include <config.h>
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <errno.h>
32
33 #define COBJMACROS
34 #include <windows.h>
35 #include <objidl.h> /* For IStream. */
36
37 #include "gpgme.h"
38 #include "intern.h"
39 #include "passcache.h"
40 #include "engine.h"
41
42 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
43                                        __FILE__, __func__, __LINE__); \
44                         } while (0)
45
46
47 static char *debug_file = NULL;
48 static int init_done = 0;
49
50
51 static void add_verify_attestation (gpgme_data_t at, 
52                                     gpgme_ctx_t ctx, 
53                                     gpgme_verify_result_t res,
54                                     const char *filename);
55
56
57
58 static void
59 cleanup (void)
60 {
61   if (debug_file)
62     {
63       xfree (debug_file);
64       debug_file = NULL;
65     }
66 }
67
68
69 /* Enable or disable GPGME debug mode. */
70 void
71 op_set_debug_mode (int val, const char *file)
72 {
73   const char *s= "GPGME_DEBUG";
74
75   cleanup ();
76   if (val > 0) 
77     {
78       debug_file = (char *)xcalloc (1, strlen (file) + strlen (s) + 2);
79       sprintf (debug_file, "%s=%d;%s", s, val, file);
80       putenv (debug_file);
81     }
82   else
83     putenv ("GPGME_DEBUG=");
84 }
85
86
87 /* Cleanup static resources. */
88 void
89 op_deinit (void)
90 {
91   cleanup ();
92 }
93
94
95 /* Initialize the operation system. */
96 int
97 op_init (void)
98 {
99   gpgme_error_t err;
100
101   if (init_done == 1)
102     return 0;
103
104   if (!gpgme_check_version (NEED_GPGME_VERSION)) 
105     {
106       log_debug ("gpgme is too old (need %s, have %s)\n",
107                  NEED_GPGME_VERSION, gpgme_check_version (NULL) );
108       return -1;
109     }
110
111   err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
112   if (err)
113     {
114       log_debug ("gpgme can't find a suitable OpenPGP backend: %s\n",
115                  gpgme_strerror (err));
116       return err;
117     }
118   
119   /*init_keycache_objects ();*/
120   init_done = 1;
121   return 0;
122 }
123
124
125 /* The read callback used by GPGME to read data from an IStream object. */
126 static ssize_t
127 stream_read_cb (void *handle, void *buffer, size_t size)
128 {
129   LPSTREAM stream = handle;
130   HRESULT hr;
131   ULONG nread;
132
133   /* For EOF detection we assume that Read returns no error and thus
134      nread will be 0.  The specs say that "Depending on the
135      implementation, either S_FALSE or an error code could be returned
136      when reading past the end of the stream"; thus we are not really
137      sure whether our assumption is correct.  OTOH, at another place
138      the docuemntation says that the implementation used by
139      ISequentialStream exhibits the same EOF behaviour has found on
140      the MSDOS FAT file system.  So we seem to have good karma. */
141   hr = IStream_Read (stream, buffer, size, &nread);
142   if (hr != S_OK)
143     {
144       log_debug ("%s:%s: Read failed: hr=%#lx", __FILE__, __func__, hr);
145       errno = EIO;
146       return -1;
147     }
148   return nread;
149 }
150
151 /* The write callback used by GPGME to write data to an IStream object. */
152 static ssize_t
153 stream_write_cb (void *handle, const void *buffer, size_t size)
154 {
155   LPSTREAM stream = handle;
156   HRESULT hr;
157   ULONG nwritten;
158
159   hr = IStream_Write (stream, buffer, size, &nwritten);
160   if (hr != S_OK)
161     {
162       log_debug ("%s:%s: Write failed: hr=%#lx", __FILE__, __func__, hr);
163       errno = EIO;
164       return -1;
165     }
166   return nwritten;
167 }
168
169
170 /* This routine should be called immediately after an operation to
171    make sure that the passphrase cache gets updated. ERR is expected
172    to be the error code from the gpgme operation and PASS_CB_VALUE the
173    context used by the passphrase callback.  
174
175    On any error we flush a possible passphrase for the used keyID from
176    the cache.  On success we store the passphrase into the cache.  The
177    cache will take care of the supplied TTL and for example actually
178    delete it if the TTL is 0 or an empty value is used. We also wipe
179    the passphrase from the context here. */
180 static void
181 update_passphrase_cache (int err, struct decrypt_key_s *pass_cb_value)
182 {
183   if (*pass_cb_value->keyid)
184     {
185       if (err)
186         passcache_put (pass_cb_value->keyid, NULL, 0);
187       else
188         passcache_put (pass_cb_value->keyid, pass_cb_value->pass,
189                        pass_cb_value->ttl);
190     }
191   if (pass_cb_value->pass)
192     {
193       wipestring (pass_cb_value->pass);
194       xfree (pass_cb_value->pass);
195       pass_cb_value->pass = NULL;
196     }
197 }
198
199
200
201 \f
202 /* Try to figure out why the encryption failed and provide a more
203    suitable error code than the one returned by the encryption
204    routine. */
205 static gpgme_error_t
206 check_encrypt_result (gpgme_ctx_t ctx, gpgme_error_t err)
207 {
208   gpgme_encrypt_result_t res;
209
210   res = gpgme_op_encrypt_result (ctx);
211   if (!res)
212     return err;
213   if (res->invalid_recipients != NULL)
214     return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
215   /* XXX: we need to do more here! */
216   return err;
217 }
218
219
220 /* Encrypt the data in INBUF into a newly malloced buffer stored on
221    success at OUTBUF. The recipients are expected in the NULL
222    terminated array KEYS. If SIGN_KEY is not NULl, the data will also
223    be signed using this key.  TTL is the time the passphrase should be
224    cached. */
225 int
226 op_encrypt (const char *inbuf, char **outbuf, gpgme_key_t *keys,
227             gpgme_key_t sign_key, int ttl)
228 {
229   struct decrypt_key_s dk;
230   gpgme_data_t in = NULL;
231   gpgme_data_t out = NULL;
232   gpgme_error_t err;
233   gpgme_ctx_t ctx = NULL;
234     
235   memset (&dk, 0, sizeof dk);
236   dk.ttl = ttl;
237   dk.flags = 0x01; /* FIXME: what is that? */
238
239   *outbuf = NULL;
240
241   op_init ();
242   err = gpgme_new (&ctx);
243   if (err)
244     goto leave;
245
246   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
247   if (err)
248     goto leave;
249
250   err = gpgme_data_new (&out);
251   if (err)
252     goto leave;
253
254   gpgme_set_textmode (ctx, 1);
255   gpgme_set_armor (ctx, 1);
256   if (sign_key)
257     {
258       gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
259       dk.ctx = ctx;
260       err = gpgme_signers_add (ctx, sign_key);
261       if (!err)
262         err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST,
263                                      in, out);
264       dk.ctx = NULL;
265       update_passphrase_cache (err, &dk);
266     }
267   else
268     err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
269   if (err)
270     err = check_encrypt_result (ctx, err);
271   else
272     {
273       /* Return the buffer but first make sure it is a string. */
274       if (gpgme_data_write (out, "", 1) == 1)
275         {
276           *outbuf = gpgme_data_release_and_get_mem (out, NULL);
277           out = NULL; 
278         }
279     }
280
281
282  leave:
283   if (ctx)
284     gpgme_release (ctx);
285   if (in)
286     gpgme_data_release (in);
287   if (out)
288     gpgme_data_release (out);
289   return err;
290 }
291
292
293
294 /* Encrypt the stream INSTREAM to the OUTSTREAM for all recpients
295    given in the NULL terminated array KEYS.  If SIGN_KEY is not NULL
296    the message will also be signed. */
297 int
298 op_encrypt_stream (LPSTREAM instream, LPSTREAM outstream, gpgme_key_t *keys,
299                    gpgme_key_t sign_key, int ttl)
300 {
301   struct decrypt_key_s dk;
302   struct gpgme_data_cbs cbs;
303   gpgme_data_t in = NULL;
304   gpgme_data_t out = NULL;
305   gpgme_ctx_t ctx = NULL;
306   gpgme_error_t err;
307
308   memset (&cbs, 0, sizeof cbs);
309   cbs.read = stream_read_cb;
310   cbs.write = stream_write_cb;
311
312   memset (&dk, 0, sizeof dk);
313   dk.ttl = ttl;
314   dk.flags = 1;
315
316   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
317   if (err)
318     goto fail;
319
320   err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
321   if (err)
322     goto fail;
323
324   err = gpgme_new (&ctx);
325   if (err)
326     goto fail;
327
328   gpgme_set_armor (ctx, 1);
329   /* FIXME:  We should not hardcode always trust. */
330   if (sign_key)
331     {
332       gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
333       dk.ctx = ctx;
334       err = gpgme_signers_add (ctx, sign_key);
335       if (!err)
336         err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST,
337                                      in, out);
338       dk.ctx = NULL;
339       update_passphrase_cache (err, &dk);
340     }
341   else
342     err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
343   if (err)
344     err = check_encrypt_result (ctx, err);
345
346  fail:
347   if (ctx)
348     gpgme_release (ctx);
349   if (in)
350     gpgme_data_release (in);
351   if (out)
352     gpgme_data_release (out);
353   return err;
354 }
355
356 \f
357 /* Sign and encrypt the data in INBUF into a newly allocated buffer at
358    OUTBUF. */
359 int
360 op_sign (const char *inbuf, char **outbuf, int mode,
361          gpgme_key_t sign_key, int ttl)
362 {
363   struct decrypt_key_s dk;
364   gpgme_error_t err;
365   gpgme_data_t in = NULL;
366   gpgme_data_t out = NULL;
367   gpgme_ctx_t ctx = NULL;
368
369   memset (&dk, 0, sizeof dk);
370   dk.ttl = ttl;
371   dk.flags = 1;
372
373   *outbuf = NULL;
374   op_init ();
375   
376   err = gpgme_new (&ctx);
377   if (err) 
378     goto leave;
379
380   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
381   if (err)
382     goto leave;
383
384   err = gpgme_data_new (&out);
385   if (err)
386     goto leave;
387
388   if (sign_key)
389     gpgme_signers_add (ctx, sign_key);
390
391   if (mode == GPGME_SIG_MODE_CLEAR)
392     gpgme_set_textmode (ctx, 1);
393   gpgme_set_armor (ctx, 1);
394
395   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
396   dk.ctx = ctx;
397   err = gpgme_op_sign (ctx, in, out, mode);
398   dk.ctx = NULL;
399   update_passphrase_cache (err, &dk);
400
401   if (!err)
402     {
403       /* Return the buffer but first make sure it is a string. */
404       if (gpgme_data_write (out, "", 1) == 1)
405         {
406           *outbuf = gpgme_data_release_and_get_mem (out, NULL);
407           out = NULL; 
408         }
409     }
410
411  leave:
412   if (ctx)
413     gpgme_release (ctx);
414   if (in)
415     gpgme_data_release (in);
416   if (out)
417     gpgme_data_release (out);
418   return err;
419 }
420
421
422 /* Create a signature from INSTREAM and write it to OUTSTREAM.  Use
423    signature mode MODE and a passphrase caching time of TTL. */
424 int
425 op_sign_stream (LPSTREAM instream, LPSTREAM outstream, int mode,
426                 gpgme_key_t sign_key, int ttl)
427 {
428   struct gpgme_data_cbs cbs;
429   struct decrypt_key_s dk;
430   gpgme_data_t in = NULL;
431   gpgme_data_t out = NULL;
432   gpgme_ctx_t ctx = NULL;
433   gpgme_error_t err;
434   
435   memset (&cbs, 0, sizeof cbs);
436   cbs.read = stream_read_cb;
437   cbs.write = stream_write_cb;
438
439   memset (&dk, 0, sizeof dk);
440   dk.ttl = ttl;
441   dk.flags = 0x01; /* fixme: Use a macro for documentation reasons. */
442
443   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
444   if (err)
445     goto fail;
446
447   err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
448   if (err)
449     goto fail;
450
451   err = gpgme_new (&ctx);
452   if (err)
453     goto fail;
454   
455   if (sign_key)
456     gpgme_signers_add (ctx, sign_key);
457
458   if (mode == GPGME_SIG_MODE_CLEAR)
459     gpgme_set_textmode (ctx, 1);
460   gpgme_set_armor (ctx, 1);
461
462   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
463   dk.ctx = ctx;
464   err = gpgme_op_sign (ctx, in, out, mode);
465   dk.ctx = NULL;
466   update_passphrase_cache (err, &dk);
467   
468  fail:
469   if (in)
470     gpgme_data_release (in);
471   if (out)
472     gpgme_data_release (out);
473   if (ctx)
474     gpgme_release (ctx);    
475   return err;
476 }
477
478
479 \f
480 /* Run the decryption.  Decrypts INBUF to OUTBUF, caller must xfree
481    the result at OUTBUF.  TTL is the time in seconds to cache a
482    passphrase.  If FILENAME is not NULL it will be displayed along
483    with status outputs. If ATTESTATION is not NULL a text with the
484    result of the signature verification will get printed to it. */
485 int 
486 op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename,
487             gpgme_data_t attestation)
488 {
489   struct decrypt_key_s dk;
490   gpgme_data_t in = NULL;
491   gpgme_data_t out = NULL;
492   gpgme_ctx_t ctx;
493   gpgme_error_t err;
494   
495   *outbuf = NULL;
496   op_init ();
497
498   memset (&dk, 0, sizeof dk);
499   dk.ttl = ttl;
500
501   err = gpgme_new (&ctx);
502   if (err)
503     return err;
504
505   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
506   if (err)
507     goto leave;
508   err = gpgme_data_new (&out);
509   if (err)
510     goto leave;
511
512   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
513   dk.ctx = ctx;
514   err = gpgme_op_decrypt_verify (ctx, in, out);
515   dk.ctx = NULL;
516   update_passphrase_cache (err, &dk);
517
518   /* Act upon the result of the decryption operation. */
519   if (!err) 
520     {
521       /* Decryption succeeded.  Store the result at OUTBUF. */
522       gpgme_verify_result_t res;
523
524       /* Return the buffer but first make sure it is a string. */
525       if (gpgme_data_write (out, "", 1) == 1)
526         {
527           *outbuf = gpgme_data_release_and_get_mem (out, NULL);
528           out = NULL; 
529         }
530
531       /* Now check the state of any signature. */
532       res = gpgme_op_verify_result (ctx);
533       if (res && res->signatures)
534         verify_dialog_box (res, filename);
535       if (res && res->signatures && attestation)
536         add_verify_attestation (attestation, ctx, res, filename);
537     }
538   else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED)
539     {
540       /* The decryption failed.  See whether we can determine the real
541          problem. */
542       gpgme_decrypt_result_t res;
543       res = gpgme_op_decrypt_result (ctx);
544       if (res != NULL && res->recipients != NULL &&
545           gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY)
546         err = GPG_ERR_NO_SECKEY;
547       /* XXX: return the keyids */
548     }
549   else
550     {
551       /* Decryption failed for other reasons. */
552     }
553
554
555   /* If the callback indicated a cancel operation, set the error
556      accordingly. */
557   if (err && (dk.opts & OPT_FLAG_CANCEL))
558     err = gpg_error (GPG_ERR_CANCELED);
559   
560 leave:    
561   if (ctx)
562     gpgme_release (ctx);
563   if (in)
564     gpgme_data_release (in);
565   if (out)
566     gpgme_data_release (out);
567   return err;
568 }
569
570
571 /* Decrypt the GPGME data object IN into the data object OUT.  Returns
572    0 on success or an gpgme error code on failure.  If FILENAME is not
573    NULL it will be displayed along with status outputs. If ATTESTATION
574    is not NULL a text with the result of the signature verification
575    will get printed to it. */
576 static int
577 decrypt_stream (gpgme_data_t in, gpgme_data_t out, int ttl,
578                 const char *filename, gpgme_data_t attestation)
579 {    
580   struct decrypt_key_s dk;
581   gpgme_ctx_t ctx = NULL;
582   gpgme_error_t err;
583   
584   memset (&dk, 0, sizeof dk);
585   dk.ttl = ttl;
586
587   err = gpgme_new (&ctx);
588   if (err)
589     goto fail;
590
591   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
592   dk.ctx = ctx;
593   err = gpgme_op_decrypt_verify (ctx, in, out);
594   dk.ctx = NULL;
595   update_passphrase_cache (err, &dk);
596   /* Act upon the result of the decryption operation. */
597   if (!err) 
598     {
599       gpgme_verify_result_t res;
600
601       /* Decryption succeeded.  Now check the state of the signatures. */
602       res = gpgme_op_verify_result (ctx);
603       if (res && res->signatures)
604         verify_dialog_box (res, filename);
605       if (res && res->signatures && attestation)
606         add_verify_attestation (attestation, ctx, res, filename);
607     }
608   else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED)
609     {
610       /* The decryption failed.  See whether we can determine the real
611          problem. */
612       gpgme_decrypt_result_t res;
613       res = gpgme_op_decrypt_result (ctx);
614       if (res != NULL && res->recipients != NULL &&
615           gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY)
616         err = GPG_ERR_NO_SECKEY;
617       /* XXX: return the keyids */
618     }
619   else
620     {
621       /* Decryption failed for other reasons. */
622     }
623
624
625   /* If the callback indicated a cancel operation, set the error
626      accordingly. */
627   if (err && (dk.opts & OPT_FLAG_CANCEL))
628     err = gpg_error (GPG_ERR_CANCELED);
629
630  fail:
631   if (ctx)
632     gpgme_release (ctx);
633   return err;
634 }
635
636 /* Decrypt the stream INSTREAM directly to the stream OUTSTREAM.
637    Returns 0 on success or an gpgme error code on failure.  If
638    FILENAME is not NULL it will be displayed along with status
639    outputs. */
640 int
641 op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl,
642                    const char *filename, gpgme_data_t attestation)
643 {
644   struct gpgme_data_cbs cbs;
645   gpgme_data_t in = NULL;
646   gpgme_data_t out = NULL;    
647   gpgme_error_t err;
648   
649   memset (&cbs, 0, sizeof cbs);
650   cbs.read = stream_read_cb;
651   cbs.write = stream_write_cb;
652
653   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
654   if (!err)
655     err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
656   if (!err)
657     err = decrypt_stream (in, out, ttl, filename, attestation);
658
659   if (in)
660     gpgme_data_release (in);
661   if (out)
662     gpgme_data_release (out);
663   return err;
664 }
665
666
667 /* Decrypt the stream INSTREAM directly to the newly allocated buffer OUTBUF.
668    Returns 0 on success or an gpgme error code on failure.  If
669    FILENAME is not NULL it will be displayed along with status
670    outputs. */
671 int
672 op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
673                              const char *filename, gpgme_data_t attestation)
674 {    
675   struct gpgme_data_cbs cbs;
676   gpgme_data_t in = NULL;
677   gpgme_data_t out = NULL;    
678   gpgme_error_t err;
679   
680   *outbuf = NULL;
681
682   memset (&cbs, 0, sizeof cbs);
683   cbs.read = stream_read_cb;
684
685   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
686   if (!err)
687     err = gpgme_data_new (&out);
688   if (!err)
689     err = decrypt_stream (in, out, ttl, filename, attestation);
690   if (!err)
691     {
692       /* Return the buffer but first make sure it is a string. */
693       if (gpgme_data_write (out, "", 1) == 1)
694         {
695           *outbuf = gpgme_data_release_and_get_mem (out, NULL);
696           out = NULL; 
697         }
698     }
699
700   if (in)
701     gpgme_data_release (in);
702   if (out)
703     gpgme_data_release (out);
704   return err;
705 }
706
707
708 /* Decrypt the stream INSTREAM directly to the GPGME data object OUT.
709    Returns 0 on success or an gpgme error code on failure.  If
710    FILENAME is not NULL it will be displayed along with status
711    outputs. */
712 int
713 op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
714                             const char *filename, gpgme_data_t attestation)
715 {
716   struct gpgme_data_cbs cbs;
717   gpgme_data_t in = NULL;
718   gpgme_error_t err;
719   
720   memset (&cbs, 0, sizeof cbs);
721   cbs.read = stream_read_cb;
722
723   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
724   if (!err)
725     err = decrypt_stream (in, out, ttl, filename, attestation);
726
727   if (in)
728     gpgme_data_release (in);
729   return err;
730 }
731
732
733 \f
734 /* Verify a message in INBUF and return the new message (i.e. the one
735    with stripped off dash escaping) in a newly allocated buffer
736    OUTBUF. If OUTBUF is NULL only the verification result will be
737    displayed (this is suitable for PGP/MIME messages).  A dialog box
738    will show the result of the verification.  If FILENAME is not NULL
739    it will be displayed along with status outputs.  If ATTESTATION is
740    not NULL a text with the result of the signature verification will
741    get printed to it. */
742 int
743 op_verify (const char *inbuf, char **outbuf, const char *filename,
744            gpgme_data_t attestation)
745 {
746   gpgme_data_t in = NULL;
747   gpgme_data_t out = NULL;
748   gpgme_ctx_t ctx = NULL;
749   gpgme_error_t err;
750   gpgme_verify_result_t res = NULL;
751
752   if (outbuf)
753     *outbuf = NULL;
754
755   op_init ();
756
757   err = gpgme_new (&ctx);
758   if (err)
759     goto leave;
760
761   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
762   if (err)
763     goto leave;
764
765   err = gpgme_data_new (&out);
766   if (err)
767     goto leave;
768
769   err = gpgme_op_verify (ctx, in, NULL, out);
770   if (!err)
771     {
772       if (outbuf) 
773         {
774           /* Return the buffer but first make sure it is a string. */
775           if (gpgme_data_write (out, "", 1) == 1)
776             {
777               *outbuf = gpgme_data_release_and_get_mem (out, NULL);
778               out = NULL; 
779             }
780         }
781       res = gpgme_op_verify_result (ctx);
782     }
783   if (res) 
784     verify_dialog_box (res, filename);
785   if (res && attestation)
786     add_verify_attestation (attestation, ctx, res, filename);
787
788  leave:
789   if (out)
790     gpgme_data_release (out);
791   if (in)
792     gpgme_data_release (in);
793   if (ctx)
794     gpgme_release (ctx);
795   return err;
796 }
797
798 /* Verify a detached message where the data is to be read from the
799    DATA_STREAM and the signature itself is expected to be the string
800    SIG_STRING.  FILENAME will be shown by the verification status
801    dialog box.  If ATTESTATION is not NULL a text with the result of
802    the signature verification will get printed to it.  */ 
803 int
804 op_verify_detached_sig (LPSTREAM data_stream,
805                         const char *sig_string, const char *filename,
806                         gpgme_data_t attestation)
807 {
808   struct gpgme_data_cbs cbs;
809   gpgme_data_t data = NULL;
810   gpgme_data_t sig = NULL;
811   gpgme_ctx_t ctx = NULL;
812   gpgme_error_t err;
813   gpgme_verify_result_t res = NULL;
814
815   memset (&cbs, 0, sizeof cbs);
816   cbs.read = stream_read_cb;
817   cbs.write = stream_write_cb;
818
819   op_init ();
820
821   err = gpgme_new (&ctx);
822   if (err)
823     goto leave;
824
825   err = gpgme_data_new_from_cbs (&data, &cbs, data_stream);
826   if (err)
827     goto leave;
828
829   err = gpgme_data_new_from_mem (&sig, sig_string, strlen (sig_string), 0);
830   if (err)
831     goto leave;
832
833   err = gpgme_op_verify (ctx, sig, data, NULL);
834   if (!err)
835     {
836       res = gpgme_op_verify_result (ctx);
837       if (res) 
838         verify_dialog_box (res, filename);
839       if (res && attestation)
840         add_verify_attestation (attestation, ctx, res, filename);
841     }
842
843  leave:
844   if (data)
845     gpgme_data_release (data);
846   if (sig)
847     gpgme_data_release (sig);
848   if (ctx)
849     gpgme_release (ctx);
850   return err;
851 }
852
853
854 \f
855 static void
856 at_puts (gpgme_data_t a, const char *s)
857 {
858   gpgme_data_write (a, s, strlen (s));
859 }
860
861 static void 
862 at_print_time (gpgme_data_t a, time_t t)
863 {
864   char buf[200];
865
866   strftime (buf, sizeof (buf)-1, "%c", localtime (&t));
867   at_puts (a, buf);
868 }
869
870 static void 
871 at_fingerprint (gpgme_data_t a, gpgme_key_t key)
872 {
873   const char *s;
874   int i, is_pgp;
875   char *buf, *p;
876   const char *prefix = _("Fingerprint: ");
877
878   if (!key)
879     return;
880   s = key->subkeys ? key->subkeys->fpr : NULL;
881   if (!s)
882     return;
883   is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
884
885   buf = xmalloc ( strlen (prefix) + strlen(s) * 4 + 2 );
886   p = stpcpy (buf, prefix);
887   if (is_pgp && strlen (s) == 40)
888     { 
889       /* v4 style formatted. */
890       for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
891         {
892           *p++ = s[0];
893           *p++ = s[1];
894           *p++ = s[2];
895           *p++ = s[3];
896           *p++ = ' ';
897           if (i == 4)
898             *p++ = ' ';
899         }
900     }
901   else
902     { 
903       /* v3 style or X.509 formatted. */
904       for (i=0; *s && s[1] && s[2]; s += 2, i++)
905         {
906           *p++ = s[0];
907           *p++ = s[1];
908           *p++ = is_pgp? ' ':':';
909           if (is_pgp && i == 7)
910             *p++ = ' ';
911         }
912     }
913
914   /* Just in case print remaining odd digits */
915   for (; *s; s++)
916     *p++ = *s;
917   *p++ = '\n';
918   *p = 0;
919   at_puts (a, buf);
920   xfree (buf);
921 }
922
923
924 /* Print common attributes of the signature summary SUM.  Returns
925    trues if a severe warning has been encountered. */
926 static int 
927 at_sig_summary (gpgme_data_t a,  
928                 unsigned long sum, gpgme_signature_t sig, gpgme_key_t key)
929 {
930   int severe = 0;
931
932   if ((sum & GPGME_SIGSUM_VALID))
933     at_puts (a, _("This signature is valid\n"));
934   if ((sum & GPGME_SIGSUM_GREEN))
935     at_puts (a, _("signature state is \"green\"\n"));
936   if ((sum & GPGME_SIGSUM_RED))
937     at_puts (a, _("signature state is \"red\"\n"));
938
939   if ((sum & GPGME_SIGSUM_KEY_REVOKED))
940     {
941       at_puts (a, _("Warning: One of the keys has been revoked\n"));
942       severe = 1;
943     }
944   
945   if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
946     {
947       time_t t = key->subkeys->expires ? key->subkeys->expires : 0;
948
949       if (t)
950         {
951           at_puts (a, _("Warning: The key used to create the "
952                         "signature expired at: "));
953           at_print_time (a, t);
954           at_puts (a, "\n");
955         }
956       else
957         at_puts (a, _("Warning: At least one certification key "
958                       "has expired\n"));
959     }
960
961   if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
962     {
963       at_puts (a, _("Warning: The signature expired at: "));
964       at_print_time (a, sig ? sig->exp_timestamp : 0);
965       at_puts (a, "\n");
966     }
967
968   if ((sum & GPGME_SIGSUM_KEY_MISSING))
969     at_puts (a, _("Can't verify due to a missing key or certificate\n"));
970
971   if ((sum & GPGME_SIGSUM_CRL_MISSING))
972     {
973       at_puts (a, _("The CRL is not available\n"));
974       severe = 1;
975     }
976
977   if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
978     {
979       at_puts (a, _("Available CRL is too old\n"));
980       severe = 1;
981     }
982
983   if ((sum & GPGME_SIGSUM_BAD_POLICY))
984     at_puts (a, _("A policy requirement was not met\n"));
985
986   if ((sum & GPGME_SIGSUM_SYS_ERROR))
987     {
988       const char *t0 = NULL, *t1 = NULL;
989
990       at_puts (a, _("A system error occured"));
991
992       /* Try to figure out some more detailed system error information. */
993       if (sig)
994         {
995           t0 = "";
996           t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
997         }
998
999       if (t0 || t1)
1000         {
1001           at_puts (a, ": ");
1002           if (t0)
1003             at_puts (a, t0);
1004           if (t1 && !(t0 && !strcmp (t0, t1)))
1005             {
1006               if (t0)
1007                 at_puts (a, ",");
1008               at_puts (a, t1);
1009             }
1010         }
1011       at_puts (a, "\n");
1012     }
1013
1014   return severe;
1015 }
1016
1017
1018 /* Print the validity of a key used for one signature. */
1019 static void 
1020 at_sig_validity (gpgme_data_t a, gpgme_signature_t sig)
1021 {
1022   const char *txt = NULL;
1023
1024   switch (sig ? sig->validity : 0)
1025     {
1026     case GPGME_VALIDITY_UNKNOWN:
1027       txt = _("WARNING: We have NO indication whether "
1028               "the key belongs to the person named "
1029               "as shown above\n");
1030       break;
1031     case GPGME_VALIDITY_UNDEFINED:
1032       break;
1033     case GPGME_VALIDITY_NEVER:
1034       txt = _("WARNING: The key does NOT BELONG to "
1035               "the person named as shown above\n");
1036       break;
1037     case GPGME_VALIDITY_MARGINAL:
1038       txt = _("WARNING: It is NOT certain that the key "
1039               "belongs to the person named as shown above\n");
1040       break;
1041     case GPGME_VALIDITY_FULL:
1042     case GPGME_VALIDITY_ULTIMATE:
1043       txt = NULL;
1044       break;
1045     }
1046
1047   if (txt)
1048     at_puts (a, txt);
1049 }
1050
1051
1052 /* Print a text with the attestation of the signature verification
1053    (which is in RES) to A.  FILENAME may also be used in the
1054    attestation. */
1055 static void
1056 add_verify_attestation (gpgme_data_t a, gpgme_ctx_t ctx,
1057                         gpgme_verify_result_t res, const char *filename)
1058 {
1059   time_t created;
1060   const char *fpr, *uid;
1061   gpgme_key_t key = NULL;
1062   int i, anybad = 0, anywarn = 0;
1063   unsigned int sum;
1064   gpgme_user_id_t uids = NULL;
1065   gpgme_signature_t sig;
1066   gpgme_error_t err;
1067
1068   if (!gpgme_data_seek (a, 0, SEEK_CUR))
1069     {
1070       /* Nothing yet written to the stream.  Insert the curretn time. */
1071       at_puts (a, _("Verification started at: "));
1072       at_print_time (a, time (NULL));
1073       at_puts (a, "\n\n");
1074     }
1075
1076   at_puts (a, _("Verification result for: "));
1077   at_puts (a, filename ? filename : _("[unnamed part]"));
1078   at_puts (a, "\n");
1079   if (res)
1080     {
1081       for (sig = res->signatures; sig; sig = sig->next)
1082         {
1083           created = sig->timestamp;
1084           fpr = sig->fpr;
1085           sum = sig->summary;
1086
1087           if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1088             anybad = 1;
1089
1090           err = gpgme_get_key (ctx, fpr, &key, 0);
1091           uid = !err && key->uids && key->uids->uid ? key->uids->uid : "[?]";
1092
1093           if ((sum & GPGME_SIGSUM_GREEN))
1094             {
1095               at_puts (a, _("Good signature from: "));
1096               at_puts (a, uid);
1097               at_puts (a, "\n");
1098               for (i = 1, uids = key->uids; uids; i++, uids = uids->next)
1099                 {
1100                   if (uids->revoked)
1101                     continue;
1102                   at_puts (a, _("                aka: "));
1103                   at_puts (a, uids->uid);
1104                   at_puts (a, "\n");
1105                 }
1106               at_puts (a, _("            created: "));
1107               at_print_time (a, created);
1108               at_puts (a, "\n");
1109               if (at_sig_summary (a, sum, sig, key))
1110                 anywarn = 1;
1111               at_sig_validity (a, sig);
1112             }
1113           else if ((sum & GPGME_SIGSUM_RED))
1114             {
1115               at_puts (a, _("*BAD* signature claimed to be from: "));
1116               at_puts (a, uid);
1117               at_puts (a, "\n");
1118               at_sig_summary (a, sum, sig, key);
1119             }
1120           else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
1121             { /* We can't decide (yellow) but this is a PGP key with a
1122                  good signature, so we display what a PGP user
1123                  expects: The name, fingerprint and the key validity
1124                  (which is neither fully or ultimate). */
1125               at_puts (a, _("Good signature from: "));
1126               at_puts (a, uid);
1127               at_puts (a, "\n");
1128               at_puts (a, _("            created: "));
1129               at_print_time (a, created);
1130               at_puts (a, "\n");
1131               at_sig_validity (a, sig);
1132               at_fingerprint (a, key);
1133               if (at_sig_summary (a, sum, sig, key))
1134                 anywarn = 1;
1135             }
1136           else /* can't decide (yellow) */
1137             {
1138               at_puts (a, _("Error checking signature"));
1139               at_puts (a, "\n");
1140               at_sig_summary (a, sum, sig, key);
1141             }
1142           
1143           gpgme_key_release (key);
1144         }
1145
1146       if (!anybad )
1147         {
1148           gpgme_sig_notation_t notation;
1149           
1150           for (sig = res->signatures; sig; sig = sig->next)
1151             {
1152               if (!sig->notations)
1153                 continue;
1154               at_puts (a, _("*** Begin Notation (signature by: "));
1155               at_puts (a, sig->fpr);
1156               at_puts (a, ") ***\n");
1157               for (notation = sig->notations; notation;
1158                    notation = notation->next)
1159                 {
1160                   if (notation->name)
1161                     {
1162                       at_puts (a, notation->name);
1163                       at_puts (a, "=");
1164                     }
1165                   if (notation->value)
1166                     {
1167                       at_puts (a, notation->value);
1168                       if (!(*notation->value
1169                             && (notation->value[strlen (notation->value)-1]
1170                                 =='\n')))
1171                         at_puts (a, "\n");
1172                     }
1173                 }
1174               at_puts (a, _("*** End Notation ***\n"));
1175             }
1176         }
1177     }
1178   at_puts (a, "\n");
1179 }
1180
1181
1182
1183 \f
1184 /* Try to find a key for each item in array NAMES. Items not found are
1185    stored as malloced strings in the newly allocated array UNKNOWN.
1186    Found keys are stored in the newly allocated array KEYS.  Both
1187    arrays are terminated by a NULL entry.  Caller needs to releade
1188    KEYS and UNKNOWN.
1189
1190    Returns: 0 on success. However success may also be that one or all
1191    keys are unknown.
1192 */
1193 int 
1194 op_lookup_keys (char **names, gpgme_key_t **keys, char ***unknown)
1195 {
1196   gpgme_error_t err;
1197   gpgme_ctx_t ctx;
1198   size_t n;
1199   int i, kpos, upos;
1200   gpgme_key_t k, k2;
1201
1202   *keys = NULL;
1203   *unknown = NULL;
1204
1205   err = gpgme_new (&ctx);
1206   if (err)
1207     return -1; /* Error. */
1208
1209   for (n=0; names[n]; n++)
1210     ;
1211
1212   *keys =  xcalloc (n+1, sizeof *keys);
1213   *unknown = xcalloc (n+1, sizeof *unknown);
1214
1215   for (i=kpos=upos=0; names[i]; i++)
1216     {
1217       k = NULL;
1218       err = gpgme_op_keylist_start (ctx, names[i], 0);
1219       if (!err)
1220         {
1221           err = gpgme_op_keylist_next (ctx, &k);
1222           if (!err && !gpgme_op_keylist_next (ctx, &k2))
1223             {
1224               /* More than one matching key available.  Take this one
1225                  as unknown. */
1226               gpgme_key_release (k);
1227               gpgme_key_release (k2);
1228               k = k2 = NULL;
1229             }
1230         }
1231       gpgme_op_keylist_end (ctx);
1232
1233       if (k)
1234         (*keys)[kpos++] = k;
1235       else
1236         (*unknown)[upos++] = xstrdup (names[i]);
1237     }
1238
1239   gpgme_release (ctx);
1240   return 0;
1241 }
1242
1243
1244
1245 /* Copy the data from the GPGME object DAT to a newly created file
1246    with name OUTFILE.  Returns 0 on success. */
1247 static gpgme_error_t
1248 data_to_file (gpgme_data_t *dat, const char *outfile)
1249 {
1250   FILE *out;
1251   char *buf;
1252   size_t n=0;
1253
1254   out = fopen (outfile, "wb");
1255   if (!out)
1256     return GPG_ERR_UNKNOWN_ERRNO; /* FIXME: We need to check why we
1257                                      can't use errno here. */
1258   /* FIXME: Why at all are we using an in memory object wqhen we are
1259      later going to write to a file anyway. */
1260   buf = gpgme_data_release_and_get_mem (*dat, &n);
1261   *dat = NULL;
1262   if (!n)
1263     {
1264       fclose (out);
1265       return GPG_ERR_EOF; /* FIXME:  wrap this into a gpgme_error() */
1266     }
1267   fwrite (buf, 1, n, out);
1268   fclose (out);
1269   /* FIXME: We have no error checking above. */
1270   xfree (buf);
1271   return 0;
1272 }
1273
1274
1275 int
1276 op_export_keys (const char *pattern[], const char *outfile)
1277 {      
1278     /* @untested@ */
1279     gpgme_ctx_t ctx=NULL;
1280     gpgme_data_t  out=NULL;    
1281     gpgme_error_t err;
1282
1283     err = gpgme_new (&ctx);
1284     if (err)
1285         return err;
1286     err = gpgme_data_new (&out);
1287     if (err) {
1288         gpgme_release (ctx);
1289         return err;
1290     }
1291
1292     gpgme_set_armor (ctx, 1);
1293     err = gpgme_op_export_ext (ctx, pattern, 0, out);
1294     if (!err)
1295         data_to_file (&out, outfile);
1296
1297     gpgme_data_release (out);  
1298     gpgme_release (ctx);  
1299     return err;
1300 }
1301
1302
1303 const char *
1304 userid_from_key (gpgme_key_t k)
1305 {
1306   if (k && k->uids && k->uids->uid)
1307     return k->uids->uid;
1308   else
1309     return "?";
1310 }
1311
1312 const char *
1313 keyid_from_key (gpgme_key_t k)
1314 {
1315   
1316   if (k && k->subkeys && k->subkeys->keyid)
1317     return k->subkeys->keyid;
1318   else
1319     return "????????";
1320 }
1321
1322
1323 const char*
1324 op_strerror (int err)
1325 {
1326     return gpgme_strerror (err);
1327 }
1328
1329