Signing with attachments does now work. w/o temp files.
[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 GPGME Dialogs.
5  *
6  * GPGME Dialogs 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  * GPGME Dialogs 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 GPGME Dialogs; 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 "keycache.h"
39 #include "intern.h"
40 #include "passcache.h"
41 #include "engine.h"
42
43 static char *debug_file = NULL;
44 static int init_done = 0;
45
46 /* dummy */
47 struct _gpgme_engine_info  _gpgme_engine_ops_gpgsm;
48
49 static void
50 cleanup (void)
51 {
52   if (debug_file)
53     {
54       xfree (debug_file);
55       debug_file = NULL;
56     }
57 }
58
59
60 /* Enable or disable GPGME debug mode. */
61 void
62 op_set_debug_mode (int val, const char *file)
63 {
64     const char *s= "GPGME_DEBUG";
65
66     cleanup ();
67     if (val > 0) {
68         debug_file = (char *)xcalloc (1, strlen (file) + strlen (s) + 2);
69         sprintf (debug_file, "%s=%d:%s", s, val, file);
70         putenv (debug_file);
71     }
72     else {
73         putenv ("GPGME_DEBUG=");
74     }
75 }
76
77 /* Cleanup static resources. */
78 void
79 op_deinit (void)
80 {
81     cleanup ();
82     cleanup_keycache_objects ();
83 }
84
85
86 /* Initialize the operation system. */
87 int
88 op_init (void)
89 {
90   gpgme_error_t err;
91
92   if (init_done == 1)
93       return 0;
94
95   if (!gpgme_check_version (NEED_GPGME_VERSION)) {
96       log_debug ("gpgme is too old (need %s, have %s)\n",
97                  NEED_GPGME_VERSION, gpgme_check_version (NULL) );
98       return -1;
99   }
100
101   err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
102   if (err) {
103       log_debug ("gpgme can't find a suitable OpenPGP backend: %s\n",
104                  gpgme_strerror (err));
105       return err;
106   }
107
108   /*init_keycache_objects ();*/
109   init_done = 1;
110   return 0;
111 }
112
113
114 /* The read callback used by GPGME to read data from an IStream object. */
115 static ssize_t
116 stream_read_cb (void *handle, void *buffer, size_t size)
117 {
118   LPSTREAM stream = handle;
119   HRESULT hr;
120   ULONG nread;
121
122   /* For EOF detection we assume that Read returns no error and thus
123      nread will be 0.  The specs say that "Depending on the
124      implementation, either S_FALSE or an error code could be returned
125      when reading past the end of the stream"; thus we are not really
126      sure whether our assumption is correct.  OTOH, at another place
127      the docuemntation says that the implementation used by
128      ISequentialStream exhibits the same EOF behaviour has found on
129      the MSDOS FAT file system.  So we seem to have good karma. */
130   hr = IStream_Read (stream, buffer, size, &nread);
131   if (hr != S_OK)
132     {
133       log_debug ("%s:%s: Read failed: hr=%#lx", __FILE__, __func__, hr);
134       errno = EIO;
135       return -1;
136     }
137   return nread;
138 }
139
140 /* The write callback used by GPGME to write data to an IStream object. */
141 static ssize_t
142 stream_write_cb (void *handle, const void *buffer, size_t size)
143 {
144   LPSTREAM stream = handle;
145   HRESULT hr;
146   ULONG nwritten;
147
148   hr = IStream_Write (stream, buffer, size, &nwritten);
149   if (hr != S_OK)
150     {
151       log_debug ("%s:%s: Write failed: hr=%#lx", __FILE__, __func__, hr);
152       errno = EIO;
153       return -1;
154     }
155   return nwritten;
156 }
157
158
159 /* Release a GPGME key array KEYS. */
160 static void
161 free_recipients (gpgme_key_t *keys)
162 {
163   int i;
164   
165   if (!keys)
166     return;
167   for (i=0; keys[i]; i++)
168     gpgme_key_release (keys[i]);
169   xfree (keys);
170 }
171
172
173 /* This routine should be called immediately after an operation to
174    make sure that the passphrase cache gets updated. ERR is expected
175    to be the error code from the gpgme operation and PASS_CB_VALUE the
176    context used by the passphrase callback.  
177
178    On any error we flush a possible passphrase for the used keyID from
179    the cache.  On success we store the passphrase into the cache.  The
180    cache will take care of the supplied TTL and for example actually
181    delete it if the TTL is 0 or an empty value is used. We also wipe
182    the passphrase from the context here. */
183 static void
184 update_passphrase_cache (int err, struct decrypt_key_s *pass_cb_value)
185 {
186   if (*pass_cb_value->keyid)
187     {
188       if (err)
189         passcache_put (pass_cb_value->keyid, NULL, 0);
190       else
191         passcache_put (pass_cb_value->keyid, pass_cb_value->pass,
192                        pass_cb_value->ttl);
193     }
194   if (pass_cb_value->pass)
195     {
196       wipestring (pass_cb_value->pass);
197       xfree (pass_cb_value->pass);
198       pass_cb_value->pass = NULL;
199     }
200 }
201
202
203 int
204 op_encrypt_start (const char *inbuf, char **outbuf)
205 {
206     gpgme_key_t *keys = NULL;
207     int opts = 0;
208     int err;
209
210     recipient_dialog_box (&keys, &opts);
211     if (opts & OPT_FLAG_CANCEL)
212         return 0;
213     err = op_encrypt ((void *)keys, inbuf, outbuf);
214     free_recipients (keys);
215     return err;
216 }
217
218
219 long 
220 ftello (FILE *f)
221 {
222     /* XXX: find out if this is really needed */
223     printf ("fd %d pos %ld\n", fileno(f), (long)ftell(f));
224     return ftell (f);
225 }
226
227
228 /* Copy the data from the GPGME object DAT to a newly created file
229    with name OUTFILE.  Returns 0 on success. */
230 static gpgme_error_t
231 data_to_file (gpgme_data_t *dat, const char *outfile)
232 {
233   FILE *out;
234   char *buf;
235   size_t n=0;
236
237   out = fopen (outfile, "wb");
238   if (!out)
239     return GPG_ERR_UNKNOWN_ERRNO; /* FIXME: We need to check why we
240                                      can't use errno here. */
241   /* FIXME: Why at all are we using an in memory object wqhen we are
242      later going to write to a file anyway. */
243   buf = gpgme_data_release_and_get_mem (*dat, &n);
244   *dat = NULL;
245   if (!n)
246     {
247       fclose (out);
248       return GPG_ERR_EOF; /* FIXME:  wrap this into a gpgme_error() */
249     }
250   fwrite (buf, 1, n, out);
251   fclose (out);
252   /* FIXME: We have no error checking above. */
253   xfree (buf);
254   return 0;
255 }
256
257
258 int
259 op_export_keys (const char *pattern[], const char *outfile)
260 {      
261     /* @untested@ */
262     gpgme_ctx_t ctx=NULL;
263     gpgme_data_t  out=NULL;    
264     gpgme_error_t err;
265
266     err = gpgme_new (&ctx);
267     if (err)
268         return err;
269     err = gpgme_data_new (&out);
270     if (err) {
271         gpgme_release (ctx);
272         return err;
273     }
274
275     gpgme_set_armor (ctx, 1);
276     err = gpgme_op_export_ext (ctx, pattern, 0, out);
277     if (!err)
278         data_to_file (&out, outfile);
279
280     gpgme_data_release (out);  
281     gpgme_release (ctx);  
282     return err;
283 }
284
285
286 /* FIXME: Why is RSET a void* ???*/
287 int
288 op_sign_encrypt_file (void *rset, const char *infile, const char *outfile)
289 {
290   gpgme_data_t in = NULL;
291   gpgme_data_t out = NULL;
292   gpgme_ctx_t ctx = NULL;
293   gpgme_error_t err;
294   gpgme_key_t *keys = (gpgme_key_t*)rset;
295   struct decrypt_key_s *hd;
296   
297   hd = xcalloc (1, sizeof *hd);
298
299   err = gpgme_data_new_from_file (&in, infile, 1);
300   if (err)
301     goto fail;
302     
303   err = gpgme_new (&ctx);
304   if (err)
305     goto fail;
306         
307   err = gpgme_data_new (&out);
308   if (err)
309     goto fail;
310
311   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, hd);
312   hd->ctx = ctx;    
313   err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
314   hd->ctx = NULL;    
315   update_passphrase_cache (err, hd);
316
317   if (!err)
318     err = data_to_file (&out, outfile);
319     
320  fail:
321   if (ctx)
322     gpgme_release (ctx);
323   if (in)
324     gpgme_data_release (in);
325   if (out)
326     gpgme_data_release (out);
327   xfree (hd);
328   return err;
329 }
330
331
332 /* Sign the file with name INFILE and write the output to a new file
333    OUTFILE. PASSCB is the passphrase callback to use and DK the value
334    we will pass to it.  MODE is one of the GPGME signing modes. */
335 static int
336 do_sign_file (gpgme_passphrase_cb_t pass_cb,
337               struct decrypt_key_s *dk,
338               int mode, const char *infile, const char *outfile)
339 {
340   gpgme_data_t in = NULL;
341   gpgme_data_t out = NULL;
342   gpgme_ctx_t ctx = NULL;
343   gpgme_error_t err;
344
345   err = gpgme_data_new_from_file (&in, infile, 1);
346   if (err)
347     goto fail;    
348
349   err = gpgme_new (&ctx);
350   if (err)
351     goto fail;
352   
353   gpgme_set_armor (ctx, 1);
354   
355   err = gpgme_data_new (&out);
356   if (err)
357     goto fail;
358
359   gpgme_set_passphrase_cb (ctx, pass_cb, dk);
360   dk->ctx = ctx;
361   err = gpgme_op_sign (ctx, in, out, mode);
362   dk->ctx = NULL;
363   update_passphrase_cache (err, dk);
364   
365   if (!err)
366     err = data_to_file (&out, outfile);
367
368  fail:
369   if (in)
370     gpgme_data_release (in);
371   if (out)
372     gpgme_data_release (out);
373   if (ctx)
374     gpgme_release (ctx);    
375   return err;
376 }
377
378
379 int
380 op_sign_file (int mode, const char *infile, const char *outfile, int ttl)
381 {
382   struct decrypt_key_s *hd;
383   gpgme_error_t err;
384   
385   hd = xcalloc (1, sizeof *hd);
386   hd->ttl = ttl;
387   hd->flags = 0x01;
388
389   err = do_sign_file (passphrase_callback_box, hd, mode, infile, outfile);
390
391   xfree (hd);
392   return err;
393 }
394
395
396 /* Create a signature from INSTREAM and write it to OUTSTREAM.  Use
397    signature mode MODE and a passphrase caching time of TTL. */
398 int
399 op_sign_stream (LPSTREAM instream, LPSTREAM outstream, int mode, int ttl)
400 {
401   struct gpgme_data_cbs cbs;
402   struct decrypt_key_s dk;
403   gpgme_data_t in = NULL;
404   gpgme_data_t out = NULL;
405   gpgme_ctx_t ctx = NULL;
406   gpgme_error_t err;
407   
408   memset (&cbs, 0, sizeof cbs);
409   cbs.read = stream_read_cb;
410   cbs.write = stream_write_cb;
411
412   memset (&dk, 0, sizeof dk);
413   dk.ttl = ttl;
414   dk.flags = 0x01; /* fixme: Use a more macro for documentation reasons. */
415
416   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
417   if (err)
418     goto fail;
419
420   err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
421   if (err)
422     goto fail;
423
424   err = gpgme_new (&ctx);
425   if (err)
426     goto fail;
427   
428   gpgme_set_armor (ctx, 1);
429
430   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
431   dk.ctx = ctx;
432   err = gpgme_op_sign (ctx, in, out, mode);
433   dk.ctx = NULL;
434   update_passphrase_cache (err, &dk);
435   
436  fail:
437   if (in)
438     gpgme_data_release (in);
439   if (out)
440     gpgme_data_release (out);
441   if (ctx)
442     gpgme_release (ctx);    
443   return err;
444 }
445
446
447 /* Decrypt file INFILE into file OUTFILE. */
448 int
449 op_decrypt_file (const char *infile, const char *outfile)
450 {    
451   gpgme_data_t in = NULL;
452   gpgme_data_t out = NULL;    
453   gpgme_ctx_t ctx = NULL;
454   gpgme_error_t err;
455   struct decrypt_key_s *dk;
456   
457   dk = xcalloc (1, sizeof *dk);
458
459   err = gpgme_data_new_from_file (&in, infile, 1);
460   if (err)
461     goto fail;
462
463   err = gpgme_new (&ctx);
464   if (err)
465     goto fail;
466
467   err = gpgme_data_new (&out);
468   if (err)
469     goto fail;
470
471   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, dk);
472   dk->ctx = ctx;
473   err = gpgme_op_decrypt (ctx, in, out);
474   dk->ctx = NULL;
475   update_passphrase_cache (err, dk);
476
477   if (!err)
478     err = data_to_file (&out, outfile);
479
480  fail:
481   if (in)
482     gpgme_data_release (in);
483   if (out)
484     gpgme_data_release (out);
485   if (ctx)
486     gpgme_release (ctx);
487   xfree (dk);
488   return err;
489 }
490
491
492
493 /* Decrypt the stream INSTREAM directly to the stream OUTSTREAM.
494    Returns 0 on success or an gpgme error code on failure. */
495 int
496 op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream)
497 {    
498   struct decrypt_key_s dk;
499   struct gpgme_data_cbs cbs;
500   gpgme_data_t in = NULL;
501   gpgme_data_t out = NULL;    
502   gpgme_ctx_t ctx = NULL;
503   gpgme_error_t err;
504   
505   memset (&cbs, 0, sizeof cbs);
506   cbs.read = stream_read_cb;
507   cbs.write = stream_write_cb;
508
509   memset (&dk, 0, sizeof dk);
510
511   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
512   if (err)
513     goto fail;
514
515   err = gpgme_new (&ctx);
516   if (err)
517     goto fail;
518
519   err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
520   if (err)
521     goto fail;
522
523   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
524   dk.ctx = ctx;
525   err = gpgme_op_decrypt (ctx, in, out);
526   dk.ctx = NULL;
527   update_passphrase_cache (err, &dk);
528
529  fail:
530   if (in)
531     gpgme_data_release (in);
532   if (out)
533     gpgme_data_release (out);
534   if (ctx)
535     gpgme_release (ctx);
536   return err;
537 }
538
539
540 /* Try to figure out why the encryption failed and provide a suitable
541    error code. */
542 static gpgme_error_t
543 check_encrypt_result (gpgme_ctx_t ctx, gpgme_error_t err)
544 {
545   gpgme_encrypt_result_t res;
546
547   res = gpgme_op_encrypt_result (ctx);
548   if (!res)
549     return err;
550   if (res->invalid_recipients != NULL)
551     return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
552   /* XXX: we need to do more here! */
553   return err;
554 }
555
556
557
558 /* Decrypt the data in file INFILE and write the ciphertext to the new
559    file OUTFILE. */
560 /*FIXME: Why is RSET a void*???.  Why do we have this fucntion when
561   there is already a version yusing streams? */
562 int
563 op_encrypt_file (void *rset, const char *infile, const char *outfile)
564 {
565   gpgme_data_t in = NULL;
566   gpgme_data_t out = NULL;
567   gpgme_error_t err;
568   gpgme_ctx_t ctx = NULL;
569
570   err = gpgme_data_new_from_file (&in, infile, 1);
571   if (err)
572     goto fail;
573
574   err = gpgme_new (&ctx);
575   if (err)
576     goto fail;
577
578   err = gpgme_data_new (&out);
579   if (err)
580     goto fail;
581
582   gpgme_set_armor (ctx, 1);
583   err = gpgme_op_encrypt (ctx, (gpgme_key_t*)rset,
584                           GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
585   if (!err)
586     err = data_to_file (&out, outfile);
587   else
588     err = check_encrypt_result (ctx, err);
589
590  fail:
591   if (ctx)
592     gpgme_release (ctx);
593   if (in)
594     gpgme_data_release (in);
595   if (out)
596     gpgme_data_release (out);
597   return err;
598 }
599
600 /* Encrypt data from INFILE into the newly created file OUTFILE.  This
601    version of the function internally works on streams to avoid
602    copying data into memory buffers. */
603 /*FIXME: Why is RSET a void*??? */
604 int
605 op_encrypt_file_io (void *rset, const char *infile, const char *outfile)
606 {
607   FILE *fin = NULL;
608   FILE *fout = NULL;
609   gpgme_data_t in = NULL;
610   gpgme_data_t out = NULL;
611   gpgme_error_t err;
612   gpgme_ctx_t ctx = NULL;
613
614   fin = fopen (infile, "rb");
615   if (!fin)
616     {
617       err = GPG_ERR_UNKNOWN_ERRNO; /* FIXME: use errno */
618       goto fail;
619     }
620
621   err = gpgme_data_new_from_stream (&in, fin);
622   if (err)
623     goto fail;
624
625   fout = fopen (outfile, "wb");
626   if (!fout)
627     {
628       err = GPG_ERR_UNKNOWN_ERRNO;
629       goto fail;
630     }
631
632   err = gpgme_data_new_from_stream (&out, fout);
633   if (err)
634     goto fail;
635
636   err = gpgme_new (&ctx);
637   if (err)
638     goto fail;
639   
640   gpgme_set_armor (ctx, 1);
641   err = gpgme_op_encrypt (ctx, (gpgme_key_t*)rset,
642                           GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
643
644  fail:
645   if (fin)
646     fclose (fin);
647   /* FIXME: Shouldn't we remove the file on error here? */
648   if (fout)
649     fclose (fout);
650   if (out)
651     gpgme_data_release (out);
652   if (in)
653     gpgme_data_release (in);
654   if (ctx)
655     gpgme_release (ctx);
656   return err;
657 }
658
659 /* Yet another encrypt versions; this time frommone memory buffer to a
660    newly allocated one. */
661 /*FIXME: Why is RSET a void*??? */
662 int
663 op_encrypt (void *rset, const char *inbuf, char **outbuf)
664 {
665   gpgme_key_t *keys = (gpgme_key_t *)rset;
666   gpgme_data_t in = NULL;
667   gpgme_data_t out = NULL;
668   gpgme_error_t err;
669   gpgme_ctx_t ctx = NULL;
670     
671   *outbuf = NULL;
672
673   op_init ();
674   err = gpgme_new (&ctx);
675   if (err)
676     goto leave;
677
678   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
679   if (err)
680     goto leave;
681
682   err = gpgme_data_new (&out);
683   if (err)
684     goto leave;
685
686   gpgme_set_textmode (ctx, 1);
687   gpgme_set_armor (ctx, 1);
688   err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
689   if (!err)
690     {
691       size_t n = 0;     
692       *outbuf = gpgme_data_release_and_get_mem (out, &n);
693       (*outbuf)[n] = 0;
694       out = NULL;
695     }
696   else
697     err = check_encrypt_result (ctx, err);
698
699  leave:
700   if (ctx)
701     gpgme_release (ctx);
702   if (in)
703     gpgme_data_release (in);
704   if (out)
705     gpgme_data_release (out);
706   return err;
707 }
708
709
710 /* Sign and encrypt the data in INBUF into a newly allocated buffer at
711    OUTBUF. */
712 /*FIXME: Why is RSET a void*??? */
713 int
714 op_sign_encrypt (void *rset, void *locusr, const char *inbuf, char **outbuf)
715 {
716   gpgme_key_t *keys = (gpgme_key_t*)rset;
717   gpgme_ctx_t ctx = NULL;
718   gpgme_data_t in = NULL;
719   gpgme_data_t out = NULL;
720   gpgme_error_t err;
721   struct decrypt_key_s *dk = NULL;
722
723   op_init ();
724   
725   *outbuf = NULL;
726
727   err = gpgme_new (&ctx);
728   if (err)
729     goto leave;
730
731   dk = (struct decrypt_key_s *)xcalloc (1, sizeof *dk);
732   dk->flags = 0x01;
733   
734   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
735   if (err)
736     goto leave;
737
738   err = gpgme_data_new (&out);
739   if (err)
740     goto leave;
741   
742   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, dk);
743   gpgme_set_armor (ctx, 1);
744   gpgme_signers_add (ctx, (gpgme_key_t)locusr);
745   err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
746   if (!err) 
747     {
748       size_t n = 0;
749       *outbuf = gpgme_data_release_and_get_mem (out, &n);
750       (*outbuf)[n] = 0;
751       out = NULL;
752     }
753   else
754     err = check_encrypt_result (ctx, err);
755
756  leave:
757   free_decrypt_key (dk);
758   if (ctx)
759     gpgme_release (ctx);
760   if (out)
761     gpgme_data_release (out);
762   if (in)
763     gpgme_data_release (in);
764   return err;
765 }
766
767
768 static int
769 do_sign (gpgme_key_t locusr, const char *inbuf, char **outbuf)
770 {
771   gpgme_error_t err;
772   gpgme_data_t in = NULL;
773   gpgme_data_t out = NULL;
774   gpgme_ctx_t ctx = NULL;
775   struct decrypt_key_s *dk = NULL;
776
777   log_debug ("engine-gpgme.do_sign: enter\n");
778
779   *outbuf = NULL;
780   op_init ();
781   
782   err = gpgme_new (&ctx);
783   if (err) 
784     goto leave;
785
786   dk = (struct decrypt_key_s *)xcalloc (1, sizeof *dk);
787   dk->flags = 0x01;
788
789   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
790   if (err)
791     goto leave;
792
793   err = gpgme_data_new (&out);
794   if (err)
795     goto leave;
796     
797   gpgme_set_passphrase_cb (ctx, passphrase_callback_box, dk);
798   gpgme_signers_add (ctx, locusr);
799   gpgme_set_textmode (ctx, 1);
800   gpgme_set_armor (ctx, 1);
801   err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_CLEAR);
802   if (!err)
803     {
804       size_t n = 0;
805       *outbuf = gpgme_data_release_and_get_mem (out, &n);
806       (*outbuf)[n] = 0;
807       out = NULL;
808     }
809
810  leave:
811   free_decrypt_key (dk);
812   if (ctx)
813     gpgme_release (ctx);
814   if (in)
815     gpgme_data_release (in);
816   if (out)
817     gpgme_data_release (out);
818   log_debug ("%s:%s: leave (rc=%d (%s))\n",
819              __FILE__, __func__, err, gpgme_strerror (err));
820   return err;
821 }
822
823
824
825 int
826 op_sign_start (const char *inbuf, char **outbuf)
827 {
828   gpgme_key_t locusr = NULL;
829   int err;
830
831   log_debug ("engine-gpgme.op_sign_start: enter\n");
832   err = signer_dialog_box (&locusr, NULL);
833   if (err == -1)
834     { /* Cancel */
835       log_debug ("engine-gpgme.op_sign_start: leave (canceled)\n");
836       return 0;
837     }
838   err = do_sign (locusr, inbuf, outbuf);
839   log_debug ("engine-gpgme.op_sign_start: leave (rc=%d (%s))\n",
840              err, gpg_strerror (err));
841   return err;
842 }
843
844
845
846 /* Worker function for the decryption.  PASS_CB is the passphrase
847    callback and PASS_CB_VALUE is passed as opaque argument to the
848    callback.  INBUF is the string with ciphertext.  On success a newly
849    allocated string with the plaintext will be stored at the address
850    of OUTBUF and 0 returned.  On failure, NULL will be stored at
851    OUTBUF and a gpgme error code is returned. */
852 static int
853 do_decrypt (gpgme_passphrase_cb_t pass_cb,
854             struct decrypt_key_s *pass_cb_value,
855             const char *inbuf, char **outbuf)
856 {
857   gpgme_data_t in = NULL;
858   gpgme_data_t out = NULL;
859   gpgme_ctx_t ctx;
860   gpgme_error_t err;
861   
862   *outbuf = NULL;
863   op_init ();
864
865   err = gpgme_new (&ctx);
866   if (err)
867     return err;
868
869   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
870   if (err)
871     goto leave;
872   err = gpgme_data_new (&out);
873   if (err)
874     goto leave;
875
876   /* Set the callback and run the actual decryption routine.  We need
877      to access the gpgme context in the callback, thus store it in the
878      arg for the time of the call. */
879   gpgme_set_passphrase_cb (ctx, pass_cb, pass_cb_value);
880   pass_cb_value->ctx = ctx;    
881   err = gpgme_op_decrypt_verify (ctx, in, out);
882   pass_cb_value->ctx = NULL;    
883   update_passphrase_cache (err, pass_cb_value);
884
885   /* Act upon the result of the decryption operation. */
886   if (!err) 
887     {
888       /* Decryption succeeded.  Store the result at OUTBUF. */
889       size_t n = 0;
890       gpgme_verify_result_t res;
891
892       *outbuf = gpgme_data_release_and_get_mem (out, &n);
893       (*outbuf)[n] = 0; /* Make sure it is really a string. */
894       out = NULL; /* (That GPGME object is no any longer valid.) */
895
896       /* Now check the state of any signature. */
897       res = gpgme_op_verify_result (ctx);
898       if (res && res->signatures)
899         verify_dialog_box (res);
900     }
901   else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED)
902     {
903       /* The decryption failed.  See whether we can determine the real
904          problem. */
905       gpgme_decrypt_result_t res;
906       res = gpgme_op_decrypt_result (ctx);
907       if (res != NULL && res->recipients != NULL &&
908           gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY)
909         err = GPG_ERR_NO_SECKEY;
910       /* XXX: return the keyids */
911     }
912   else
913     {
914       /* Decryption failed for other reasons. */
915
916       /* XXX: automatically spawn verify_start in case the text was signed? */
917     }
918
919
920     /* If the callback indicated a cancel operation, clear the error. */
921   if (pass_cb_value->opts & OPT_FLAG_CANCEL)
922     err = 0;
923   
924
925 leave:    
926   gpgme_release (ctx);
927   gpgme_data_release (in);
928   gpgme_data_release (out);
929   return err;
930 }
931
932
933 /* Run the decryption.  Decrypts INBUF to OUTBUF, caller must xfree
934    the result at OUTBUF.  TTL is the time in seconds to cache a
935    passphrase. */
936 int
937 op_decrypt_start (const char *inbuf, char **outbuf, int ttl)
938 {
939   int err;
940   struct decrypt_key_s *hd;
941     
942   hd = xcalloc (1, sizeof *hd);
943   hd->ttl = ttl;
944   err = do_decrypt (passphrase_callback_box, hd, inbuf, outbuf);
945
946   free_decrypt_key (hd);
947   return err;
948 }
949
950
951 /* Verify a message in INBUF and return the new message (i.e. the one
952    with stripped off dash escaping) in a newly allocated buffer
953    OUTBUF. IF OUTBUF is NULL only the verification result will be
954    displayed (this is suitable for PGP/MIME messages).  A dialog box
955    will show the result of the verification. */
956 int
957 op_verify_start (const char *inbuf, char **outbuf)
958 {
959   gpgme_data_t in = NULL;
960   gpgme_data_t out = NULL;
961   gpgme_ctx_t ctx = NULL;
962   gpgme_error_t err;
963   gpgme_verify_result_t res = NULL;
964
965   *outbuf = NULL;
966
967   op_init ();
968
969   err = gpgme_new (&ctx);
970   if (err)
971     goto leave;
972
973   err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1);
974   if (err)
975     goto leave;
976
977   err = gpgme_data_new (&out);
978   if (err)
979     goto leave;
980
981   err = gpgme_op_verify (ctx, in, NULL, out);
982   if (!err)
983     {
984       size_t n=0;
985       if (outbuf) 
986         {
987           *outbuf = gpgme_data_release_and_get_mem (out, &n);
988           (*outbuf)[n] = 0;
989           out = NULL;
990         }
991       res = gpgme_op_verify_result (ctx);
992     }
993   if (res) 
994     verify_dialog_box (res);
995
996  leave:
997   if (out)
998     gpgme_data_release (out);
999   if (in)
1000     gpgme_data_release (in);
1001   if (ctx)
1002     gpgme_release (ctx);
1003   return err;
1004 }
1005
1006
1007 /* Try to find a key for each item in array NAMES. If one ore more
1008    items were not found, they are stored as malloced strings to the
1009    newly allocated array UNKNOWN at the corresponding position.  Found
1010    keys are stored in the newly allocated array KEYS. If N is not NULL
1011    the total number of items will be stored at that address.  Note,
1012    that both UNKNOWN may have NULL entries inbetween. The fucntion
1013    returns the nuber of keys not found. Caller needs to releade KEYS
1014    and UNKNOWN. 
1015
1016    FIXME: The calling convetion is far to complicated.  Needs to be revised.
1017
1018 */
1019 int 
1020 op_lookup_keys (char **names, gpgme_key_t **keys, char ***unknown, size_t *n)
1021 {
1022     int i, pos=0;
1023     gpgme_key_t k;
1024
1025     for (i=0; names[i]; i++)
1026         ;
1027     if (n)
1028         *n = i;
1029     *unknown = (char **)xcalloc (i+1, sizeof (char*));
1030     *keys = (gpgme_key_t *)xcalloc (i+1, sizeof (gpgme_key_t));
1031     for (i=0; names[i]; i++) {
1032         /*k = find_gpg_email(id[i]);*/
1033         k = get_gpg_key (names[i]);
1034         if (!k)
1035             (*unknown)[pos++] = xstrdup (names[i]);
1036         else
1037             (*keys)[i] = k;
1038     }
1039     return (i-pos);
1040 }
1041
1042
1043 const char*
1044 op_strerror (int err)
1045 {
1046     return gpgme_strerror (err);
1047 }