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