2004-05-21 Marcus Brinkmann <marcus@g10code.de>
[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                    const char *lc_ctype, const char *lc_messages)
163 {
164   engine_t engine;
165
166   const char *file_name;
167   const char *version;
168
169   if (proto > DIM (engine_ops))
170     return gpg_error (GPG_ERR_INV_VALUE);
171
172   if (!engine_ops[proto])
173     return gpg_error (GPG_ERR_INV_ENGINE);
174
175   file_name = engine_get_file_name (proto);
176   version = engine_get_version (proto);
177   if (!file_name || !version)
178     return gpg_error (GPG_ERR_INV_ENGINE);
179
180   engine = calloc (1, sizeof *engine);
181   if (!engine)
182     return gpg_error_from_errno (errno);
183
184   engine->ops = engine_ops[proto];
185   if (engine_ops[proto]->new)
186     {
187       gpgme_error_t err = (*engine_ops[proto]->new) (&engine->engine,
188                                                      lc_ctype,
189                                                      lc_messages);
190       if (err)
191         {
192           free (engine);
193           return err;
194         }
195     }
196   else
197     engine->engine = NULL;
198
199   *r_engine = engine;
200   return 0;
201 }
202
203
204 void
205 _gpgme_engine_release (engine_t engine)
206 {
207   if (!engine)
208     return;
209
210   if (engine->ops->release)
211     (*engine->ops->release) (engine->engine);
212   free (engine);
213 }
214
215
216 void
217 _gpgme_engine_set_status_handler (engine_t engine,
218                                   engine_status_handler_t fnc, void *fnc_value)
219 {
220   if (!engine)
221     return;
222
223   if (engine->ops->set_status_handler)
224     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
225 }
226
227
228 gpgme_error_t
229 _gpgme_engine_set_command_handler (engine_t engine,
230                                    engine_command_handler_t fnc,
231                                    void *fnc_value,
232                                    gpgme_data_t linked_data)
233 {
234   if (!engine)
235     return gpg_error (GPG_ERR_INV_VALUE);
236
237   if (!engine->ops->set_command_handler)
238     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
239
240   return (*engine->ops->set_command_handler) (engine->engine,
241                                               fnc, fnc_value, linked_data);
242 }
243
244 gpgme_error_t
245 _gpgme_engine_set_colon_line_handler (engine_t engine,
246                                       engine_colon_line_handler_t fnc,
247                                       void *fnc_value)
248 {
249   if (!engine)
250     return gpg_error (GPG_ERR_INV_VALUE);
251
252   if (!engine->ops->set_colon_line_handler)
253     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
254
255   return (*engine->ops->set_colon_line_handler) (engine->engine,
256                                                  fnc, fnc_value);
257 }
258
259 gpgme_error_t
260 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
261                           gpgme_data_t plain)
262 {
263   if (!engine)
264     return gpg_error (GPG_ERR_INV_VALUE);
265
266   if (!engine->ops->decrypt)
267     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
268
269   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
270 }
271
272 gpgme_error_t
273 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
274                          int allow_secret)
275 {
276   if (!engine)
277     return gpg_error (GPG_ERR_INV_VALUE);
278
279   if (!engine->ops->delete)
280     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
281
282   return (*engine->ops->delete) (engine->engine, key, allow_secret);
283 }
284
285
286 gpgme_error_t
287 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
288                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
289 {
290   if (!engine)
291     return gpg_error (GPG_ERR_INV_VALUE);
292
293   if (!engine->ops->edit)
294     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
295
296   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
297 }
298
299
300 gpgme_error_t
301 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
302                           gpgme_encrypt_flags_t flags,
303                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
304 {
305   if (!engine)
306     return gpg_error (GPG_ERR_INV_VALUE);
307
308   if (!engine->ops->encrypt)
309     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
310
311   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
312                                   use_armor);
313 }
314
315
316 gpgme_error_t
317 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
318                                gpgme_encrypt_flags_t flags,
319                                gpgme_data_t plain, gpgme_data_t ciph,
320                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
321 {
322   if (!engine)
323     return gpg_error (GPG_ERR_INV_VALUE);
324
325   if (!engine->ops->encrypt_sign)
326     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
327
328   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
329                                        plain, ciph, use_armor, ctx);
330 }
331
332
333 gpgme_error_t
334 _gpgme_engine_op_export (engine_t engine, const char *pattern,
335                          unsigned int reserved, gpgme_data_t keydata,
336                          int use_armor)
337 {
338   if (!engine)
339     return gpg_error (GPG_ERR_INV_VALUE);
340
341   if (!engine->ops->export)
342     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
343
344   return (*engine->ops->export) (engine->engine, pattern, reserved,
345                                  keydata, use_armor);
346 }
347
348
349 gpgme_error_t
350 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
351                              unsigned int reserved, gpgme_data_t keydata,
352                              int use_armor)
353 {
354   if (!engine)
355     return gpg_error (GPG_ERR_INV_VALUE);
356
357   if (!engine->ops->export_ext)
358     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
359
360   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
361                                      keydata, use_armor);
362 }
363
364
365 gpgme_error_t
366 _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
367                          int use_armor, gpgme_data_t pubkey,
368                          gpgme_data_t seckey)
369 {
370   if (!engine)
371     return gpg_error (GPG_ERR_INV_VALUE);
372
373   if (!engine->ops->genkey)
374     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
375
376   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
377                                  pubkey, seckey);
378 }
379
380
381 gpgme_error_t
382 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata)
383 {
384   if (!engine)
385     return gpg_error (GPG_ERR_INV_VALUE);
386
387   if (!engine->ops->import)
388     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
389
390   return (*engine->ops->import) (engine->engine, keydata);
391 }
392
393
394 gpgme_error_t
395 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
396                           int secret_only, gpgme_keylist_mode_t mode)
397 {
398   if (!engine)
399     return gpg_error (GPG_ERR_INV_VALUE);
400
401   if (!engine->ops->keylist)
402     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
403
404   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
405 }
406
407
408 gpgme_error_t
409 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
410                               int secret_only, int reserved,
411                               gpgme_keylist_mode_t mode)
412 {
413   if (!engine)
414     return gpg_error (GPG_ERR_INV_VALUE);
415
416   if (!engine->ops->keylist_ext)
417     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
418
419   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
420                                       reserved, mode);
421 }
422
423
424 gpgme_error_t
425 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
426                        gpgme_sig_mode_t mode, int use_armor,
427                        int use_textmode, int include_certs,
428                        gpgme_ctx_t ctx /* FIXME */)
429 {
430   if (!engine)
431     return gpg_error (GPG_ERR_INV_VALUE);
432
433   if (!engine->ops->sign)
434     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
435
436   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
437                                use_textmode, include_certs, ctx);
438 }
439
440
441 gpgme_error_t
442 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
443 {
444   if (!engine)
445     return gpg_error (GPG_ERR_INV_VALUE);
446
447   if (!engine->ops->trustlist)
448     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
449
450   return (*engine->ops->trustlist) (engine->engine, pattern);
451 }
452
453
454 gpgme_error_t
455 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
456                          gpgme_data_t signed_text, gpgme_data_t plaintext)
457 {
458   if (!engine)
459     return gpg_error (GPG_ERR_INV_VALUE);
460
461   if (!engine->ops->verify)
462     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
463
464   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
465 }
466
467
468 void
469 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
470 {
471   if (!engine)
472     return;
473
474   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
475 }
476
477
478 void
479 _gpgme_engine_io_event (engine_t engine,
480                         gpgme_event_io_t type, void *type_data)
481 {
482   if (!engine)
483     return;
484
485   (*engine->ops->io_event) (engine->engine, type, type_data);
486 }
487
488
489 gpgme_error_t
490 _gpgme_engine_cancel (engine_t engine)
491 {
492   if (!engine)
493     return gpg_error (GPG_ERR_INV_VALUE);
494
495   if (!engine->ops->cancel)
496     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
497
498   return (*engine->ops->cancel) (engine->engine);
499 }