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