f5891b9ac9d39ebed7cc2cb94a2a1c1b3e798304
[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_verbosity (EngineObject engine, int verbosity)
211 {
212   if (!engine)
213     return;
214
215   if (engine->ops->set_verbosity)
216     (*engine->ops->set_verbosity) (engine->engine, verbosity);
217 }
218
219
220 void
221 _gpgme_engine_set_status_handler (EngineObject engine,
222                                   EngineStatusHandler fnc, void *fnc_value)
223 {
224   if (!engine)
225     return;
226
227   if (engine->ops->set_status_handler)
228     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
229 }
230
231
232 GpgmeError
233 _gpgme_engine_set_command_handler (EngineObject engine,
234                                    EngineCommandHandler fnc, void *fnc_value,
235                                    GpgmeData linked_data)
236 {
237   if (!engine)
238     return GPGME_Invalid_Value;
239
240   if (!engine->ops->set_command_handler)
241     return GPGME_Not_Implemented;
242
243   return (*engine->ops->set_command_handler) (engine->engine,
244                                               fnc, fnc_value, linked_data);
245 }
246
247 GpgmeError _gpgme_engine_set_colon_line_handler (EngineObject engine,
248                                                  EngineColonLineHandler fnc,
249                                                  void *fnc_value)
250 {
251   if (!engine)
252     return GPGME_Invalid_Value;
253
254   if (!engine->ops->set_colon_line_handler)
255     return GPGME_Not_Implemented;
256
257   return (*engine->ops->set_colon_line_handler) (engine->engine,
258                                                  fnc, fnc_value);
259 }
260
261 GpgmeError
262 _gpgme_engine_op_decrypt (EngineObject engine, GpgmeData ciph, GpgmeData plain)
263 {
264   if (!engine)
265     return GPGME_Invalid_Value;
266
267   if (!engine->ops->decrypt)
268     return GPGME_Not_Implemented;
269
270   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
271 }
272
273 GpgmeError
274 _gpgme_engine_op_delete (EngineObject engine, GpgmeKey key, int allow_secret)
275 {
276   if (!engine)
277     return GPGME_Invalid_Value;
278
279   if (!engine->ops->delete)
280     return GPGME_Not_Implemented;
281
282   return (*engine->ops->delete) (engine->engine, key, allow_secret);
283 }
284
285
286 GpgmeError
287 _gpgme_engine_op_edit (EngineObject engine, GpgmeKey key, GpgmeData out,
288                        GpgmeCtx ctx /* FIXME */)
289 {
290   if (!engine)
291     return GPGME_Invalid_Value;
292
293   if (!engine->ops->edit)
294     return GPGME_Not_Implemented;
295
296   return (*engine->ops->edit) (engine->engine, key, out, ctx);
297 }
298
299
300 GpgmeError
301 _gpgme_engine_op_encrypt (EngineObject engine, GpgmeRecipients recp,
302                           GpgmeData plain, GpgmeData ciph, int use_armor)
303 {
304   if (!engine)
305     return GPGME_Invalid_Value;
306
307   if (!engine->ops->encrypt)
308     return GPGME_Not_Implemented;
309
310   return (*engine->ops->encrypt) (engine->engine, recp, plain, ciph,
311                                   use_armor);
312 }
313
314
315 GpgmeError
316 _gpgme_engine_op_encrypt_sign (EngineObject engine, GpgmeRecipients recp,
317                                GpgmeData plain, GpgmeData ciph, int use_armor,
318                                GpgmeCtx ctx /* FIXME */)
319 {
320   if (!engine)
321     return GPGME_Invalid_Value;
322
323   if (!engine->ops->encrypt_sign)
324     return GPGME_Not_Implemented;
325
326   return (*engine->ops->encrypt_sign) (engine->engine, recp, plain, ciph,
327                                        use_armor, ctx);
328 }
329
330
331 GpgmeError
332 _gpgme_engine_op_export (EngineObject engine, GpgmeRecipients recp,
333                          GpgmeData keydata, int use_armor)
334 {
335   if (!engine)
336     return GPGME_Invalid_Value;
337
338   if (!engine->ops->export)
339     return GPGME_Not_Implemented;
340
341   return (*engine->ops->export) (engine->engine, recp, keydata,
342                                  use_armor);
343 }
344
345
346 GpgmeError
347 _gpgme_engine_op_genkey (EngineObject engine, GpgmeData help_data,
348                          int use_armor, GpgmeData pubkey, GpgmeData seckey)
349 {
350   if (!engine)
351     return GPGME_Invalid_Value;
352
353   if (!engine->ops->genkey)
354     return GPGME_Not_Implemented;
355
356   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
357                                  pubkey, seckey);
358 }
359
360
361 GpgmeError
362 _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata)
363 {
364   if (!engine)
365     return GPGME_Invalid_Value;
366
367   if (!engine->ops->import)
368     return GPGME_Not_Implemented;
369
370   return (*engine->ops->import) (engine->engine, keydata);
371 }
372
373
374 GpgmeError
375 _gpgme_engine_op_keylist (EngineObject engine, const char *pattern,
376                           int secret_only, int keylist_mode)
377 {
378   if (!engine)
379     return GPGME_Invalid_Value;
380
381   if (!engine->ops->keylist)
382     return GPGME_Not_Implemented;
383
384   return (*engine->ops->keylist) (engine->engine, pattern, secret_only,
385                                   keylist_mode);
386 }
387
388
389 GpgmeError
390 _gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[],
391                               int secret_only, int reserved, int keylist_mode)
392 {
393   if (!engine)
394     return GPGME_Invalid_Value;
395
396   if (!engine->ops->keylist_ext)
397     return GPGME_Not_Implemented;
398
399   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
400                                       reserved, keylist_mode);
401 }
402
403
404 GpgmeError
405 _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out,
406                        GpgmeSigMode mode, int use_armor,
407                        int use_textmode, int include_certs,
408                        GpgmeCtx ctx /* FIXME */)
409 {
410   if (!engine)
411     return GPGME_Invalid_Value;
412
413   if (!engine->ops->sign)
414     return GPGME_Not_Implemented;
415
416   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
417                                use_textmode, include_certs, ctx);
418 }
419
420
421 GpgmeError
422 _gpgme_engine_op_trustlist (EngineObject engine, const char *pattern)
423 {
424   if (!engine)
425     return GPGME_Invalid_Value;
426
427   if (!engine->ops->trustlist)
428     return GPGME_Not_Implemented;
429
430   return (*engine->ops->trustlist) (engine->engine, pattern);
431 }
432
433
434 GpgmeError
435 _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
436                          GpgmeData signed_text, GpgmeData plaintext)
437 {
438   if (!engine)
439     return GPGME_Invalid_Value;
440
441   if (!engine->ops->verify)
442     return GPGME_Not_Implemented;
443
444   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
445 }
446
447
448 void
449 _gpgme_engine_set_io_cbs (EngineObject engine,
450                           struct GpgmeIOCbs *io_cbs)
451 {
452   if (!engine)
453     return;
454
455   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
456 }
457
458
459 void
460 _gpgme_engine_io_event (EngineObject engine,
461                         GpgmeEventIO type, void *type_data)
462 {
463   if (!engine)
464     return;
465
466   (*engine->ops->io_event) (engine->engine, type, type_data);
467 }