doc/
[gpgme.git] / gpgme / engine.c
1 /* engine.c - GPGME engine support.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "gpgme.h"
29 #include "util.h"
30 #include "sema.h"
31 #include "ops.h"
32
33 #include "engine.h"
34 #include "engine-backend.h"
35
36
37 struct engine
38 {
39   struct engine_ops *ops;
40   void *engine;
41 };
42
43
44 static struct engine_ops *engine_ops[] =
45   {
46     &_gpgme_engine_ops_gpg,             /* OpenPGP.  */
47 #ifdef ENABLE_GPGSM
48     &_gpgme_engine_ops_gpgsm            /* CMS.  */
49 #else
50     NULL
51 #endif
52   };
53
54 \f
55 /* Get the file name of the engine for PROTOCOL.  */
56 static const char *
57 engine_get_file_name (gpgme_protocol_t proto)
58 {
59   if (proto > DIM (engine_ops))
60     return NULL;
61
62   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
63     return (*engine_ops[proto]->get_file_name) ();
64   else
65     return NULL;
66 }
67
68
69 /* Get the version number of the engine for PROTOCOL.  */
70 static const char *
71 engine_get_version (gpgme_protocol_t proto)
72 {
73   if (proto > DIM (engine_ops))
74     return NULL;
75
76   if (engine_ops[proto] && engine_ops[proto]->get_version)
77     return (*engine_ops[proto]->get_version) ();
78   else
79     return NULL;
80 }
81
82
83 /* Get the required version number of the engine for PROTOCOL.  */
84 static const char *
85 engine_get_req_version (gpgme_protocol_t proto)
86 {
87   if (proto > DIM (engine_ops))
88     return NULL;
89
90   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
91     return (*engine_ops[proto]->get_req_version) ();
92   else
93     return NULL;
94 }
95
96
97 /* Verify the version requirement for the engine for PROTOCOL.  */
98 gpgme_error_t
99 gpgme_engine_check_version (gpgme_protocol_t proto)
100 {
101   return _gpgme_compare_versions (engine_get_version (proto),
102                                   engine_get_req_version (proto))
103     ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
104 }
105
106
107 /* Get the information about the configured and installed engines.  A
108    pointer to the first engine in the statically allocated linked list
109    is returned in *INFO.  If an error occurs, it is returned.  */
110 gpgme_error_t
111 gpgme_get_engine_info (gpgme_engine_info_t *info)
112 {
113   static gpgme_engine_info_t engine_info;
114   DEFINE_STATIC_LOCK (engine_info_lock);
115
116   LOCK (engine_info_lock);
117   if (!engine_info)
118     {
119       gpgme_engine_info_t *lastp = &engine_info;
120       gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
121                                         GPGME_PROTOCOL_CMS };
122       unsigned int proto;
123
124       for (proto = 0; proto < DIM (proto_list); proto++)
125         {
126           const char *file_name = engine_get_file_name (proto_list[proto]);
127
128           if (!file_name)
129             continue;
130
131           *lastp = malloc (sizeof (*engine_info));
132           if (!*lastp)
133             {
134               int saved_errno = errno;
135
136               while (engine_info)
137                 {
138                   gpgme_engine_info_t next_info = engine_info->next;
139                   free (engine_info);
140                   engine_info = next_info;
141                 }
142               UNLOCK (engine_info_lock);
143               return gpg_error_from_errno (saved_errno);
144             }
145
146           (*lastp)->protocol = proto_list[proto];
147           (*lastp)->file_name = file_name;
148           (*lastp)->version = engine_get_version (proto_list[proto]);
149           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
150           (*lastp)->next = NULL;
151           lastp = &(*lastp)->next;
152         }
153     }
154   UNLOCK (engine_info_lock);
155   *info = engine_info;
156   return 0;
157 }
158
159 \f
160 gpgme_error_t
161 _gpgme_engine_new (gpgme_protocol_t proto, engine_t *r_engine)
162 {
163   engine_t engine;
164
165   const char *file_name;
166   const char *version;
167
168   if (proto > DIM (engine_ops))
169     return gpg_error (GPG_ERR_INV_VALUE);
170
171   if (!engine_ops[proto])
172     return gpg_error (GPG_ERR_INV_ENGINE);
173
174   file_name = engine_get_file_name (proto);
175   version = engine_get_version (proto);
176   if (!file_name || !version)
177     return gpg_error (GPG_ERR_INV_ENGINE);
178
179   engine = calloc (1, sizeof *engine);
180   if (!engine)
181     return gpg_error_from_errno (errno);
182
183   engine->ops = engine_ops[proto];
184   if (engine_ops[proto]->new)
185     {
186       gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine);
187       if (err)
188         {
189           free (engine);
190           return err;
191         }
192     }
193   else
194     engine->engine = NULL;
195
196   *r_engine = engine;
197   return 0;
198 }
199
200
201 void
202 _gpgme_engine_release (engine_t engine)
203 {
204   if (!engine)
205     return;
206
207   if (engine->ops->release)
208     (*engine->ops->release) (engine->engine);
209   free (engine);
210 }
211
212
213 void
214 _gpgme_engine_set_status_handler (engine_t engine,
215                                   engine_status_handler_t fnc, void *fnc_value)
216 {
217   if (!engine)
218     return;
219
220   if (engine->ops->set_status_handler)
221     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
222 }
223
224
225 gpgme_error_t
226 _gpgme_engine_set_command_handler (engine_t engine,
227                                    engine_command_handler_t fnc,
228                                    void *fnc_value,
229                                    gpgme_data_t linked_data)
230 {
231   if (!engine)
232     return gpg_error (GPG_ERR_INV_VALUE);
233
234   if (!engine->ops->set_command_handler)
235     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
236
237   return (*engine->ops->set_command_handler) (engine->engine,
238                                               fnc, fnc_value, linked_data);
239 }
240
241 gpgme_error_t
242 _gpgme_engine_set_colon_line_handler (engine_t engine,
243                                       engine_colon_line_handler_t fnc,
244                                       void *fnc_value)
245 {
246   if (!engine)
247     return gpg_error (GPG_ERR_INV_VALUE);
248
249   if (!engine->ops->set_colon_line_handler)
250     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
251
252   return (*engine->ops->set_colon_line_handler) (engine->engine,
253                                                  fnc, fnc_value);
254 }
255
256 gpgme_error_t
257 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
258                           gpgme_data_t plain)
259 {
260   if (!engine)
261     return gpg_error (GPG_ERR_INV_VALUE);
262
263   if (!engine->ops->decrypt)
264     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
265
266   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
267 }
268
269 gpgme_error_t
270 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
271                          int allow_secret)
272 {
273   if (!engine)
274     return gpg_error (GPG_ERR_INV_VALUE);
275
276   if (!engine->ops->delete)
277     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
278
279   return (*engine->ops->delete) (engine->engine, key, allow_secret);
280 }
281
282
283 gpgme_error_t
284 _gpgme_engine_op_edit (engine_t engine, gpgme_key_t key, gpgme_data_t out,
285                        gpgme_ctx_t ctx /* FIXME */)
286 {
287   if (!engine)
288     return gpg_error (GPG_ERR_INV_VALUE);
289
290   if (!engine->ops->edit)
291     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
292
293   return (*engine->ops->edit) (engine->engine, key, out, ctx);
294 }
295
296
297 gpgme_error_t
298 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
299                           gpgme_encrypt_flags_t flags,
300                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
301 {
302   if (!engine)
303     return gpg_error (GPG_ERR_INV_VALUE);
304
305   if (!engine->ops->encrypt)
306     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
307
308   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
309                                   use_armor);
310 }
311
312
313 gpgme_error_t
314 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
315                                gpgme_encrypt_flags_t flags,
316                                gpgme_data_t plain, gpgme_data_t ciph,
317                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
318 {
319   if (!engine)
320     return gpg_error (GPG_ERR_INV_VALUE);
321
322   if (!engine->ops->encrypt_sign)
323     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
324
325   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
326                                        plain, ciph, use_armor, ctx);
327 }
328
329
330 gpgme_error_t
331 _gpgme_engine_op_export (engine_t engine, const char *pattern,
332                          unsigned int reserved, gpgme_data_t keydata,
333                          int use_armor)
334 {
335   if (!engine)
336     return gpg_error (GPG_ERR_INV_VALUE);
337
338   if (!engine->ops->export)
339     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
340
341   return (*engine->ops->export) (engine->engine, pattern, reserved,
342                                  keydata, use_armor);
343 }
344
345
346 gpgme_error_t
347 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
348                              unsigned int reserved, gpgme_data_t keydata,
349                              int use_armor)
350 {
351   if (!engine)
352     return gpg_error (GPG_ERR_INV_VALUE);
353
354   if (!engine->ops->export_ext)
355     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
356
357   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
358                                      keydata, use_armor);
359 }
360
361
362 gpgme_error_t
363 _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
364                          int use_armor, gpgme_data_t pubkey,
365                          gpgme_data_t seckey)
366 {
367   if (!engine)
368     return gpg_error (GPG_ERR_INV_VALUE);
369
370   if (!engine->ops->genkey)
371     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
372
373   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
374                                  pubkey, seckey);
375 }
376
377
378 gpgme_error_t
379 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata)
380 {
381   if (!engine)
382     return gpg_error (GPG_ERR_INV_VALUE);
383
384   if (!engine->ops->import)
385     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
386
387   return (*engine->ops->import) (engine->engine, keydata);
388 }
389
390
391 gpgme_error_t
392 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
393                           int secret_only, gpgme_keylist_mode_t mode)
394 {
395   if (!engine)
396     return gpg_error (GPG_ERR_INV_VALUE);
397
398   if (!engine->ops->keylist)
399     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
400
401   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
402 }
403
404
405 gpgme_error_t
406 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
407                               int secret_only, int reserved,
408                               gpgme_keylist_mode_t mode)
409 {
410   if (!engine)
411     return gpg_error (GPG_ERR_INV_VALUE);
412
413   if (!engine->ops->keylist_ext)
414     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
415
416   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
417                                       reserved, mode);
418 }
419
420
421 gpgme_error_t
422 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
423                        gpgme_sig_mode_t mode, int use_armor,
424                        int use_textmode, int include_certs,
425                        gpgme_ctx_t ctx /* FIXME */)
426 {
427   if (!engine)
428     return gpg_error (GPG_ERR_INV_VALUE);
429
430   if (!engine->ops->sign)
431     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
432
433   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
434                                use_textmode, include_certs, ctx);
435 }
436
437
438 gpgme_error_t
439 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
440 {
441   if (!engine)
442     return gpg_error (GPG_ERR_INV_VALUE);
443
444   if (!engine->ops->trustlist)
445     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
446
447   return (*engine->ops->trustlist) (engine->engine, pattern);
448 }
449
450
451 gpgme_error_t
452 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
453                          gpgme_data_t signed_text, gpgme_data_t plaintext)
454 {
455   if (!engine)
456     return gpg_error (GPG_ERR_INV_VALUE);
457
458   if (!engine->ops->verify)
459     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
460
461   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
462 }
463
464
465 void
466 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
467 {
468   if (!engine)
469     return;
470
471   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
472 }
473
474
475 void
476 _gpgme_engine_io_event (engine_t engine,
477                         gpgme_event_io_t type, void *type_data)
478 {
479   if (!engine)
480     return;
481
482   (*engine->ops->io_event) (engine->engine, type, type_data);
483 }