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