New API gpgme_op_getauditlog.
[gpgme.git] / gpgme / engine.c
1 /* engine.c - GPGME engine support.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2006 g10 Code GmbH
4  
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11    
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16    
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
29
30 #include "gpgme.h"
31 #include "util.h"
32 #include "sema.h"
33 #include "ops.h"
34
35 #include "engine.h"
36 #include "engine-backend.h"
37
38
39 struct engine
40 {
41   struct engine_ops *ops;
42   void *engine;
43 };
44
45
46 static struct engine_ops *engine_ops[] =
47   {
48     &_gpgme_engine_ops_gpg,             /* OpenPGP.  */
49 #ifdef ENABLE_GPGSM
50     &_gpgme_engine_ops_gpgsm            /* CMS.  */
51 #else
52     NULL
53 #endif
54   };
55
56
57 /* The engine info.  */
58 static gpgme_engine_info_t engine_info;
59 DEFINE_STATIC_LOCK (engine_info_lock);
60
61 \f
62 /* Get the file name of the engine for PROTOCOL.  */
63 static const char *
64 engine_get_file_name (gpgme_protocol_t proto)
65 {
66   if (proto > DIM (engine_ops))
67     return NULL;
68
69   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
70     return (*engine_ops[proto]->get_file_name) ();
71   else
72     return NULL;
73 }
74
75
76 /* Get a malloced string containing the version number of the engine
77    for PROTOCOL.  */
78 static char *
79 engine_get_version (gpgme_protocol_t proto, const char *file_name)
80 {
81   if (proto > DIM (engine_ops))
82     return NULL;
83
84   if (engine_ops[proto] && engine_ops[proto]->get_version)
85     return (*engine_ops[proto]->get_version) (file_name);
86   else
87     return NULL;
88 }
89
90
91 /* Get the required version number of the engine for PROTOCOL.  */
92 static const char *
93 engine_get_req_version (gpgme_protocol_t proto)
94 {
95   if (proto > DIM (engine_ops))
96     return NULL;
97
98   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
99     return (*engine_ops[proto]->get_req_version) ();
100   else
101     return NULL;
102 }
103
104
105 /* Verify the version requirement for the engine for PROTOCOL.  */
106 gpgme_error_t
107 gpgme_engine_check_version (gpgme_protocol_t proto)
108 {
109   gpgme_error_t err;
110   gpgme_engine_info_t info;
111   int result;
112
113   LOCK (engine_info_lock);
114   info = engine_info;
115   if (!info)
116     {
117       /* Make sure it is initialized.  */
118       UNLOCK (engine_info_lock);
119       err = gpgme_get_engine_info (&info);
120       if (err)
121         return err;
122
123       LOCK (engine_info_lock);
124     }
125
126   while (info && info->protocol != proto)
127     info = info->next;
128
129   if (!info)
130     result = 0;
131   else
132     result = _gpgme_compare_versions (info->version,
133                                       info->req_version);
134
135   UNLOCK (engine_info_lock);
136   return result ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
137 }
138
139
140 /* Release the engine info INFO.  */
141 void
142 _gpgme_engine_info_release (gpgme_engine_info_t info)
143 {
144   while (info)
145     {
146       gpgme_engine_info_t next_info = info->next;
147
148       assert (info->file_name);
149       free (info->file_name);
150       if (info->home_dir)
151         free (info->home_dir);
152       if (info->version)
153         free (info->version);
154       free (info);
155       info = next_info;
156     }
157 }
158
159
160 /* Get the information about the configured and installed engines.  A
161    pointer to the first engine in the statically allocated linked list
162    is returned in *INFO.  If an error occurs, it is returned.  The
163    returned data is valid until the next gpgme_set_engine_info.  */
164 gpgme_error_t
165 gpgme_get_engine_info (gpgme_engine_info_t *info)
166 {
167   LOCK (engine_info_lock);
168   if (!engine_info)
169     {
170       gpgme_engine_info_t *lastp = &engine_info;
171       gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
172                                         GPGME_PROTOCOL_CMS };
173       unsigned int proto;
174
175       for (proto = 0; proto < DIM (proto_list); proto++)
176         {
177           const char *ofile_name = engine_get_file_name (proto_list[proto]);
178           char *file_name;
179
180           if (!ofile_name)
181             continue;
182
183           file_name = strdup (ofile_name);
184
185           *lastp = malloc (sizeof (*engine_info));
186           if (!*lastp || !file_name)
187             {
188               int saved_errno = errno;
189
190               _gpgme_engine_info_release (engine_info);
191               engine_info = NULL;
192
193               if (file_name)
194                 free (file_name);
195
196               UNLOCK (engine_info_lock);
197               return gpg_error_from_errno (saved_errno);
198             }
199
200           (*lastp)->protocol = proto_list[proto];
201           (*lastp)->file_name = file_name;
202           (*lastp)->home_dir = NULL;
203           (*lastp)->version = engine_get_version (proto_list[proto], NULL);
204           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
205           (*lastp)->next = NULL;
206           lastp = &(*lastp)->next;
207         }
208     }
209
210   *info = engine_info;
211   UNLOCK (engine_info_lock);
212   return 0;
213 }
214
215
216 /* Get a deep copy of the engine info and return it in INFO.  */
217 gpgme_error_t
218 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
219 {
220   gpgme_error_t err = 0;
221   gpgme_engine_info_t info;
222   gpgme_engine_info_t new_info;
223   gpgme_engine_info_t *lastp;
224
225   LOCK (engine_info_lock);
226   info = engine_info;
227   if (!info)
228     {
229       /* Make sure it is initialized.  */
230       UNLOCK (engine_info_lock);
231       err = gpgme_get_engine_info (&info);
232       if (err)
233         return err;
234
235       LOCK (engine_info_lock);
236     }
237
238   new_info = NULL;
239   lastp = &new_info;
240
241   while (info)
242     {
243       char *file_name;
244       char *home_dir;
245       char *version;
246
247       assert (info->file_name);
248       file_name = strdup (info->file_name);
249
250       if (info->home_dir)
251         {
252           home_dir = strdup (info->home_dir);
253           if (!home_dir)
254             err = gpg_error_from_errno (errno);
255         }
256       else
257         home_dir = NULL;
258
259       if (info->version)
260         {
261           version = strdup (info->version);
262           if (!version)
263             err = gpg_error_from_errno (errno);
264         }
265       else
266         version = NULL;
267
268       *lastp = malloc (sizeof (*engine_info));
269       if (!*lastp || !file_name || err)
270         {
271           int saved_errno = errno;
272
273           _gpgme_engine_info_release (new_info);
274
275           if (file_name)
276             free (file_name);
277           if (home_dir)
278             free (home_dir);
279           if (version)
280             free (version);
281
282           UNLOCK (engine_info_lock);
283           return gpg_error_from_errno (saved_errno);
284         }
285
286       (*lastp)->protocol = info->protocol;
287       (*lastp)->file_name = file_name;
288       (*lastp)->home_dir = home_dir;
289       (*lastp)->version = version;
290       (*lastp)->req_version = info->req_version;
291       (*lastp)->next = NULL;
292       lastp = &(*lastp)->next;
293
294       info = info->next;
295     }
296
297   *r_info = new_info;
298   UNLOCK (engine_info_lock);
299   return 0;
300 }
301
302
303 /* Set the engine info for the info list INFO, protocol PROTO, to the
304    file name FILE_NAME and the home directory HOME_DIR.  */
305 gpgme_error_t
306 _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
307                         const char *file_name, const char *home_dir)
308 {
309   char *new_file_name;
310   char *new_home_dir;
311
312   /* FIXME: Use some PROTO_MAX definition.  */
313   if (proto > DIM (engine_ops))
314     return gpg_error (GPG_ERR_INV_VALUE);
315
316   while (info && info->protocol != proto)
317     info = info->next;
318
319   if (!info)
320     return gpg_error (GPG_ERR_INV_ENGINE);
321
322   /* Prepare new members.  */
323   if (file_name)
324     new_file_name = strdup (file_name);
325   else
326     {
327       const char *ofile_name = engine_get_file_name (proto);
328       assert (ofile_name);
329       new_file_name = strdup (ofile_name);
330     }
331   if (!new_file_name)
332     return gpg_error_from_errno (errno);
333
334   if (home_dir)
335     {
336       new_home_dir = strdup (home_dir);
337       if (!new_home_dir)
338         {
339           free (new_file_name);
340           return gpg_error_from_errno (errno);
341         }
342     }
343   else
344     new_home_dir = NULL;
345
346   /* Remove the old members.  */
347   assert (info->file_name);
348   free (info->file_name);
349   if (info->home_dir)
350     free (info->home_dir);
351   if (info->version)
352     free (info->version);
353
354   /* Install the new members.  */
355   info->file_name = new_file_name;
356   info->home_dir = new_home_dir;
357   info->version = engine_get_version (proto, new_file_name);
358
359   return 0;
360 }
361
362
363 /* Set the default engine info for the protocol PROTO to the file name
364    FILE_NAME and the home directory HOME_DIR.  */
365 gpgme_error_t
366 gpgme_set_engine_info (gpgme_protocol_t proto,
367                        const char *file_name, const char *home_dir)
368 {
369   gpgme_error_t err;
370   gpgme_engine_info_t info;
371
372   LOCK (engine_info_lock);
373   info = engine_info;
374   if (!info)
375     {
376       /* Make sure it is initialized.  */
377       UNLOCK (engine_info_lock);
378       err = gpgme_get_engine_info (&info);
379       if (err)
380         return err;
381
382       LOCK (engine_info_lock);
383     }
384
385   err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
386   UNLOCK (engine_info_lock);
387   return err;
388 }
389
390 \f
391 gpgme_error_t
392 _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
393 {
394   engine_t engine;
395
396   if (!info->file_name || !info->version)
397     return gpg_error (GPG_ERR_INV_ENGINE);
398
399   engine = calloc (1, sizeof *engine);
400   if (!engine)
401     return gpg_error_from_errno (errno);
402
403   engine->ops = engine_ops[info->protocol];
404   if (engine->ops->new)
405     {
406       gpgme_error_t err;
407       err = (*engine->ops->new) (&engine->engine,
408                                  info->file_name, info->home_dir);
409       if (err)
410         {
411           free (engine);
412           return err;
413         }
414     }
415   else
416     engine->engine = NULL;
417
418   *r_engine = engine;
419   return 0;
420 }
421
422
423 gpgme_error_t
424 _gpgme_engine_reset (engine_t engine)
425 {
426   if (!engine)
427     return gpg_error (GPG_ERR_INV_VALUE);
428
429   if (!engine->ops->reset)
430     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
431
432   return (*engine->ops->reset) (engine->engine);
433 }
434
435
436 void
437 _gpgme_engine_release (engine_t engine)
438 {
439   if (!engine)
440     return;
441
442   if (engine->ops->release)
443     (*engine->ops->release) (engine->engine);
444   free (engine);
445 }
446
447
448 void
449 _gpgme_engine_set_status_handler (engine_t engine,
450                                   engine_status_handler_t fnc, void *fnc_value)
451 {
452   if (!engine)
453     return;
454
455   if (engine->ops->set_status_handler)
456     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
457 }
458
459
460 gpgme_error_t
461 _gpgme_engine_set_command_handler (engine_t engine,
462                                    engine_command_handler_t fnc,
463                                    void *fnc_value,
464                                    gpgme_data_t linked_data)
465 {
466   if (!engine)
467     return gpg_error (GPG_ERR_INV_VALUE);
468
469   if (!engine->ops->set_command_handler)
470     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
471
472   return (*engine->ops->set_command_handler) (engine->engine,
473                                               fnc, fnc_value, linked_data);
474 }
475
476 gpgme_error_t
477 _gpgme_engine_set_colon_line_handler (engine_t engine,
478                                       engine_colon_line_handler_t fnc,
479                                       void *fnc_value)
480 {
481   if (!engine)
482     return gpg_error (GPG_ERR_INV_VALUE);
483
484   if (!engine->ops->set_colon_line_handler)
485     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
486
487   return (*engine->ops->set_colon_line_handler) (engine->engine,
488                                                  fnc, fnc_value);
489 }
490
491 gpgme_error_t
492 _gpgme_engine_set_locale (engine_t engine, int category,
493                           const char *value)
494 {
495   if (!engine)
496     return gpg_error (GPG_ERR_INV_VALUE);
497
498   if (!engine->ops->set_locale)
499     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
500
501   return (*engine->ops->set_locale) (engine->engine, category, value);
502 }
503
504 gpgme_error_t
505 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
506                           gpgme_data_t plain)
507 {
508   if (!engine)
509     return gpg_error (GPG_ERR_INV_VALUE);
510
511   if (!engine->ops->decrypt)
512     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
513
514   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
515 }
516
517 gpgme_error_t
518 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
519                          int allow_secret)
520 {
521   if (!engine)
522     return gpg_error (GPG_ERR_INV_VALUE);
523
524   if (!engine->ops->delete)
525     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
526
527   return (*engine->ops->delete) (engine->engine, key, allow_secret);
528 }
529
530
531 gpgme_error_t
532 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
533                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
534 {
535   if (!engine)
536     return gpg_error (GPG_ERR_INV_VALUE);
537
538   if (!engine->ops->edit)
539     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
540
541   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
542 }
543
544
545 gpgme_error_t
546 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
547                           gpgme_encrypt_flags_t flags,
548                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
549 {
550   if (!engine)
551     return gpg_error (GPG_ERR_INV_VALUE);
552
553   if (!engine->ops->encrypt)
554     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
555
556   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
557                                   use_armor);
558 }
559
560
561 gpgme_error_t
562 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
563                                gpgme_encrypt_flags_t flags,
564                                gpgme_data_t plain, gpgme_data_t ciph,
565                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
566 {
567   if (!engine)
568     return gpg_error (GPG_ERR_INV_VALUE);
569
570   if (!engine->ops->encrypt_sign)
571     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
572
573   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
574                                        plain, ciph, use_armor, ctx);
575 }
576
577
578 gpgme_error_t
579 _gpgme_engine_op_export (engine_t engine, const char *pattern,
580                          unsigned int reserved, gpgme_data_t keydata,
581                          int use_armor)
582 {
583   if (!engine)
584     return gpg_error (GPG_ERR_INV_VALUE);
585
586   if (!engine->ops->export)
587     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
588
589   return (*engine->ops->export) (engine->engine, pattern, reserved,
590                                  keydata, use_armor);
591 }
592
593
594 gpgme_error_t
595 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
596                              unsigned int reserved, gpgme_data_t keydata,
597                              int use_armor)
598 {
599   if (!engine)
600     return gpg_error (GPG_ERR_INV_VALUE);
601
602   if (!engine->ops->export_ext)
603     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
604
605   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
606                                      keydata, use_armor);
607 }
608
609
610 gpgme_error_t
611 _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
612                          int use_armor, gpgme_data_t pubkey,
613                          gpgme_data_t seckey)
614 {
615   if (!engine)
616     return gpg_error (GPG_ERR_INV_VALUE);
617
618   if (!engine->ops->genkey)
619     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
620
621   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
622                                  pubkey, seckey);
623 }
624
625
626 gpgme_error_t
627 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata)
628 {
629   if (!engine)
630     return gpg_error (GPG_ERR_INV_VALUE);
631
632   if (!engine->ops->import)
633     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
634
635   return (*engine->ops->import) (engine->engine, keydata);
636 }
637
638
639 gpgme_error_t
640 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
641                           int secret_only, gpgme_keylist_mode_t mode)
642 {
643   if (!engine)
644     return gpg_error (GPG_ERR_INV_VALUE);
645
646   if (!engine->ops->keylist)
647     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
648
649   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
650 }
651
652
653 gpgme_error_t
654 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
655                               int secret_only, int reserved,
656                               gpgme_keylist_mode_t mode)
657 {
658   if (!engine)
659     return gpg_error (GPG_ERR_INV_VALUE);
660
661   if (!engine->ops->keylist_ext)
662     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
663
664   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
665                                       reserved, mode);
666 }
667
668
669 gpgme_error_t
670 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
671                        gpgme_sig_mode_t mode, int use_armor,
672                        int use_textmode, int include_certs,
673                        gpgme_ctx_t ctx /* FIXME */)
674 {
675   if (!engine)
676     return gpg_error (GPG_ERR_INV_VALUE);
677
678   if (!engine->ops->sign)
679     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
680
681   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
682                                use_textmode, include_certs, ctx);
683 }
684
685
686 gpgme_error_t
687 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
688 {
689   if (!engine)
690     return gpg_error (GPG_ERR_INV_VALUE);
691
692   if (!engine->ops->trustlist)
693     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
694
695   return (*engine->ops->trustlist) (engine->engine, pattern);
696 }
697
698
699 gpgme_error_t
700 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
701                          gpgme_data_t signed_text, gpgme_data_t plaintext)
702 {
703   if (!engine)
704     return gpg_error (GPG_ERR_INV_VALUE);
705
706   if (!engine->ops->verify)
707     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
708
709   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
710 }
711
712
713 gpgme_error_t
714 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
715                               unsigned int flags)
716 {
717   if (!engine)
718     return gpg_error (GPG_ERR_INV_VALUE);
719
720   if (!engine->ops->getauditlog)
721     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
722
723   return (*engine->ops->getauditlog) (engine->engine, output, flags);
724 }
725
726
727 void
728 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
729 {
730   if (!engine)
731     return;
732
733   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
734 }
735
736
737 void
738 _gpgme_engine_io_event (engine_t engine,
739                         gpgme_event_io_t type, void *type_data)
740 {
741   if (!engine)
742     return;
743
744   (*engine->ops->io_event) (engine->engine, type, type_data);
745 }
746
747
748 gpgme_error_t
749 _gpgme_engine_cancel (engine_t engine)
750 {
751   if (!engine)
752     return gpg_error (GPG_ERR_INV_VALUE);
753
754   if (!engine->ops->cancel)
755     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
756
757   return (*engine->ops->cancel) (engine->engine);
758 }