2002-08-28 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / engine.c
1 /* engine.c 
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME is free software; you can redistribute it and/or modify
8  * it 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,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <time.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <assert.h>
29
30 #include "gpgme.h"
31 #include "util.h"
32 #include "sema.h"
33 #include "io.h"
34
35 #include "engine.h"
36 #include "rungpg.h"
37 #include "engine-gpgsm.h"
38
39
40 struct engine_object_s
41   {
42     GpgmeProtocol protocol;
43
44     const char *path;
45     const char *version;
46
47     union
48       {
49         GpgObject gpg;
50         GpgsmObject gpgsm;
51       } engine;
52 };
53
54
55 /* Get the path of the engine for PROTOCOL.  */
56 const char *
57 _gpgme_engine_get_path (GpgmeProtocol proto)
58 {
59   switch (proto)
60     {
61     case GPGME_PROTOCOL_OpenPGP:
62       return _gpgme_get_gpg_path ();
63     case GPGME_PROTOCOL_CMS:
64       return _gpgme_get_gpgsm_path ();
65     default:
66       return NULL;
67     }
68 }
69
70
71 /* Get the version number of the engine for PROTOCOL.  */
72 const char *
73 _gpgme_engine_get_version (GpgmeProtocol proto)
74 {
75   switch (proto)
76     {
77     case GPGME_PROTOCOL_OpenPGP:
78       return _gpgme_gpg_get_version ();
79     case GPGME_PROTOCOL_CMS:
80       return _gpgme_gpgsm_get_version ();
81     default:
82       return NULL;
83     }
84 }
85
86
87 GpgmeError
88 gpgme_engine_check_version (GpgmeProtocol proto)
89 {
90   switch (proto)
91     {
92     case GPGME_PROTOCOL_OpenPGP:
93       return _gpgme_gpg_check_version ();
94     case GPGME_PROTOCOL_CMS:
95       return _gpgme_gpgsm_check_version ();
96     default:
97       return mk_error (Invalid_Value);
98     }
99 }
100
101
102 const char *
103 _gpgme_engine_get_info (GpgmeProtocol proto)
104 {
105   static const char fmt[] = " <engine>\n"
106     "  <protocol>%s</protocol>\n"
107     "  <version>%s</version>\n"
108     "  <path>%s</path>\n"
109     " </engine>\n";
110   static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
111   static const char *engine_info[3];  /* FIXME: MAX_PROTO + 1*/
112   DEFINE_STATIC_LOCK (engine_info_lock);
113
114   if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
115     return NULL;
116
117   LOCK (engine_info_lock);
118   if (!engine_info[proto])
119     {
120       const char *path = _gpgme_engine_get_path (proto);
121       const char *version = _gpgme_engine_get_version (proto);
122
123       if (path && version)
124         {
125           char *info = xtrymalloc (strlen (fmt) + strlen (strproto[proto])
126                                    + strlen (path) + strlen (version) + 1);
127           if (!info)
128             info = " <engine>\n"
129               "  <error>Out of core</error>\n"
130               " </engine>";
131           else
132             sprintf (info, fmt, strproto[proto], version, path);
133           engine_info[proto] = info;
134         }
135     }
136   UNLOCK (engine_info_lock);
137   return engine_info[proto];
138 }
139
140
141 GpgmeError
142 _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
143 {
144   EngineObject engine;
145   GpgmeError err = 0;
146
147   engine = xtrycalloc (1, sizeof *engine);
148   if (!engine)
149     {
150       err = mk_error (Out_Of_Core);
151       goto leave;
152     }
153
154   engine->protocol = proto;
155   switch (proto)
156     {
157     case GPGME_PROTOCOL_OpenPGP:
158       err =_gpgme_gpg_new (&engine->engine.gpg);
159       break;
160     case GPGME_PROTOCOL_CMS:
161       err = _gpgme_gpgsm_new (&engine->engine.gpgsm);
162       if (err)
163         goto leave;
164       break;
165     default:
166       err = mk_error (Invalid_Value);
167     }
168   if (err)
169     goto leave;
170
171   engine->path = _gpgme_engine_get_path (proto);
172   engine->version = _gpgme_engine_get_version (proto);
173
174   if (!engine->path || !engine->version)
175     {
176       err = mk_error (Invalid_Engine);
177       goto leave;
178     }
179
180  leave:
181   if (err)
182     _gpgme_engine_release (engine);
183   else
184     *r_engine = engine;
185   
186   return err;
187 }
188
189
190 void
191 _gpgme_engine_release (EngineObject engine)
192 {
193   if (!engine)
194     return;
195
196   switch (engine->protocol)
197     {
198     case GPGME_PROTOCOL_OpenPGP:
199       _gpgme_gpg_release (engine->engine.gpg);
200       break;
201     case GPGME_PROTOCOL_CMS:
202       _gpgme_gpgsm_release (engine->engine.gpgsm);
203       break;
204     default:
205       break;
206     }
207   xfree (engine);
208 }
209
210
211 void
212 _gpgme_engine_set_verbosity (EngineObject engine, int verbosity)
213 {
214   if (!engine)
215     return;
216
217   switch (engine->protocol)
218     {
219     case GPGME_PROTOCOL_OpenPGP:
220       while (verbosity-- > 0)
221         _gpgme_gpg_add_arg (engine->engine.gpg, "--verbose");
222       break;
223     case GPGME_PROTOCOL_CMS:
224       /* FIXME */
225       break;
226     default:
227       break;
228     }
229 }
230
231 void
232 _gpgme_engine_set_status_handler (EngineObject engine,
233                                   GpgStatusHandler fnc, void *fnc_value)
234 {
235   if (!engine)
236     return;
237
238   switch (engine->protocol)
239     {
240     case GPGME_PROTOCOL_OpenPGP:
241       _gpgme_gpg_set_status_handler (engine->engine.gpg, fnc, fnc_value);
242       break;
243     case GPGME_PROTOCOL_CMS:
244       _gpgme_gpgsm_set_status_handler (engine->engine.gpgsm, fnc, fnc_value);
245       break;
246     default:
247       break;
248     }
249 }
250
251 GpgmeError
252 _gpgme_engine_set_command_handler (EngineObject engine,
253                                   GpgCommandHandler fnc, void *fnc_value,
254                                    GpgmeData linked_data)
255 {
256   if (!engine)
257     return mk_error (Invalid_Value);
258
259   switch (engine->protocol)
260     {
261     case GPGME_PROTOCOL_OpenPGP:
262       return _gpgme_gpg_set_command_handler (engine->engine.gpg,
263                                              fnc, fnc_value, linked_data);
264     case GPGME_PROTOCOL_CMS:
265       /* FIXME */
266       break;
267     default:
268       break;
269     }
270   return 0;
271 }
272
273 GpgmeError _gpgme_engine_set_colon_line_handler (EngineObject engine,
274                                                  GpgColonLineHandler fnc,
275                                                  void *fnc_value)
276 {
277   if (!engine)
278     return mk_error (Invalid_Value);
279
280   switch (engine->protocol)
281     {
282     case GPGME_PROTOCOL_OpenPGP:
283       return _gpgme_gpg_set_colon_line_handler (engine->engine.gpg, 
284                                                 fnc, fnc_value);
285     case GPGME_PROTOCOL_CMS:
286       _gpgme_gpgsm_set_colon_line_handler (engine->engine.gpgsm,
287                                            fnc, fnc_value);
288       break;
289
290     default:
291       break;
292     }
293   return 0;
294 }
295
296 GpgmeError
297 _gpgme_engine_op_decrypt (EngineObject engine, GpgmeData ciph, GpgmeData plain)
298 {
299   if (!engine)
300     return mk_error (Invalid_Value);
301
302   switch (engine->protocol)
303     {
304     case GPGME_PROTOCOL_OpenPGP:
305       return _gpgme_gpg_op_decrypt (engine->engine.gpg, ciph, plain);
306     case GPGME_PROTOCOL_CMS:
307       return _gpgme_gpgsm_op_decrypt (engine->engine.gpgsm, ciph, plain);
308     default:
309       break;
310     }
311   return 0;
312 }
313
314 GpgmeError
315 _gpgme_engine_op_delete (EngineObject engine, GpgmeKey key, int allow_secret)
316 {
317   if (!engine)
318     return mk_error (Invalid_Value);
319
320   switch (engine->protocol)
321     {
322     case GPGME_PROTOCOL_OpenPGP:
323       return _gpgme_gpg_op_delete (engine->engine.gpg, key, allow_secret);
324     case GPGME_PROTOCOL_CMS:
325       return _gpgme_gpgsm_op_delete (engine->engine.gpgsm, key, allow_secret);
326     default:
327       break;
328     }
329   return 0;
330 }
331
332
333 GpgmeError
334 _gpgme_engine_op_edit (EngineObject engine, GpgmeKey key, GpgmeData out)
335 {
336   if (!engine)
337     return mk_error (Invalid_Value);
338
339   switch (engine->protocol)
340     {
341     case GPGME_PROTOCOL_OpenPGP:
342       return _gpgme_gpg_op_edit (engine->engine.gpg, key, out);
343     case GPGME_PROTOCOL_CMS:
344       /* FIXME */
345       return mk_error (Not_Implemented);
346     default:
347       break;
348     }
349   return 0;
350 }
351
352 GpgmeError
353 _gpgme_engine_op_encrypt (EngineObject engine, GpgmeRecipients recp,
354                           GpgmeData plain, GpgmeData ciph, int use_armor)
355 {
356   if (!engine)
357     return mk_error (Invalid_Value);
358
359   switch (engine->protocol)
360     {
361     case GPGME_PROTOCOL_OpenPGP:
362       return _gpgme_gpg_op_encrypt (engine->engine.gpg, recp, plain, ciph,
363                                     use_armor);
364     case GPGME_PROTOCOL_CMS:
365       return _gpgme_gpgsm_op_encrypt (engine->engine.gpgsm, recp, plain, ciph,
366                                       use_armor);
367     default:
368       break;
369     }
370   return 0;
371 }
372
373
374 GpgmeError
375 _gpgme_engine_op_encrypt_sign (EngineObject engine, GpgmeRecipients recp,
376                                GpgmeData plain, GpgmeData ciph, int use_armor,
377                                GpgmeCtx ctx /* FIXME */)
378 {
379   if (!engine)
380     return mk_error (Invalid_Value);
381
382   switch (engine->protocol)
383     {
384     case GPGME_PROTOCOL_OpenPGP:
385       return _gpgme_gpg_op_encrypt_sign (engine->engine.gpg, recp, plain, ciph,
386                                          use_armor, ctx);
387     case GPGME_PROTOCOL_CMS:
388       return mk_error (Not_Implemented);
389     default:
390       break;
391     }
392   return 0;
393 }
394
395
396 GpgmeError
397 _gpgme_engine_op_export (EngineObject engine, GpgmeRecipients recp,
398                          GpgmeData keydata, int use_armor)
399 {
400   if (!engine)
401     return mk_error (Invalid_Value);
402
403   switch (engine->protocol)
404     {
405     case GPGME_PROTOCOL_OpenPGP:
406       return _gpgme_gpg_op_export (engine->engine.gpg, recp, keydata,
407                                    use_armor);
408     case GPGME_PROTOCOL_CMS:
409       return _gpgme_gpgsm_op_export (engine->engine.gpgsm, recp, keydata,
410                                      use_armor);
411     default:
412       break;
413     }
414   return 0;
415 }
416
417 GpgmeError
418 _gpgme_engine_op_genkey (EngineObject engine, GpgmeData help_data,
419                          int use_armor, GpgmeData pubkey, GpgmeData seckey)
420 {
421   if (!engine)
422     return mk_error (Invalid_Value);
423
424   switch (engine->protocol)
425     {
426     case GPGME_PROTOCOL_OpenPGP:
427       return _gpgme_gpg_op_genkey (engine->engine.gpg, help_data, use_armor,
428                                    pubkey, seckey);
429     case GPGME_PROTOCOL_CMS:
430       return _gpgme_gpgsm_op_genkey (engine->engine.gpgsm, help_data, use_armor,
431                                      pubkey, seckey);
432     default:
433       break;
434     }
435   return 0;
436 }
437
438 GpgmeError
439 _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata)
440 {
441   if (!engine)
442     return mk_error (Invalid_Value);
443
444   switch (engine->protocol)
445     {
446     case GPGME_PROTOCOL_OpenPGP:
447       return _gpgme_gpg_op_import (engine->engine.gpg, keydata);
448     case GPGME_PROTOCOL_CMS:
449       return _gpgme_gpgsm_op_import (engine->engine.gpgsm, keydata);
450     default:
451       break;
452     }
453   return 0;
454 }
455
456
457 GpgmeError
458 _gpgme_engine_op_keylist (EngineObject engine, const char *pattern,
459                           int secret_only, int keylist_mode)
460 {
461   if (!engine)
462     return mk_error (Invalid_Value);
463
464   switch (engine->protocol)
465     {
466     case GPGME_PROTOCOL_OpenPGP:
467       return _gpgme_gpg_op_keylist (engine->engine.gpg, pattern, secret_only,
468                                     keylist_mode);
469     case GPGME_PROTOCOL_CMS:
470       return _gpgme_gpgsm_op_keylist (engine->engine.gpgsm, pattern, secret_only,
471                                       keylist_mode);
472     default:
473       break;
474     }
475   return 0;
476 }
477
478
479 GpgmeError
480 _gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[],
481                               int secret_only, int reserved, int keylist_mode)
482 {
483   if (!engine)
484     return mk_error (Invalid_Value);
485
486   switch (engine->protocol)
487     {
488     case GPGME_PROTOCOL_OpenPGP:
489       return _gpgme_gpg_op_keylist_ext (engine->engine.gpg, pattern,
490                                         secret_only, reserved, keylist_mode);
491     case GPGME_PROTOCOL_CMS:
492       return _gpgme_gpgsm_op_keylist_ext (engine->engine.gpgsm, pattern,
493                                           secret_only, reserved, keylist_mode);
494     default:
495       break;
496     }
497   return 0;
498 }
499
500
501 GpgmeError
502 _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out,
503                        GpgmeSigMode mode, int use_armor,
504                        int use_textmode, int include_certs,
505                        GpgmeCtx ctx /* FIXME */)
506 {
507   if (!engine)
508     return mk_error (Invalid_Value);
509
510   switch (engine->protocol)
511     {
512     case GPGME_PROTOCOL_OpenPGP:
513       return _gpgme_gpg_op_sign (engine->engine.gpg, in, out, mode, use_armor,
514                                  use_textmode, ctx);
515     case GPGME_PROTOCOL_CMS:
516       return _gpgme_gpgsm_op_sign (engine->engine.gpgsm, in, out, mode,
517                                    use_armor, use_textmode, include_certs, ctx);
518       break;
519     default:
520       break;
521     }
522   return 0;
523 }
524
525 GpgmeError
526 _gpgme_engine_op_trustlist (EngineObject engine, const char *pattern)
527 {
528   if (!engine)
529     return mk_error (Invalid_Value);
530
531   switch (engine->protocol)
532     {
533     case GPGME_PROTOCOL_OpenPGP:
534       return _gpgme_gpg_op_trustlist (engine->engine.gpg, pattern);
535     case GPGME_PROTOCOL_CMS:
536       return _gpgme_gpgsm_op_trustlist (engine->engine.gpgsm, pattern);
537     default:
538       break;
539     }
540   return 0;
541 }
542
543 GpgmeError
544 _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig, GpgmeData text)
545 {
546   if (!engine)
547     return mk_error (Invalid_Value);
548
549   switch (engine->protocol)
550     {
551     case GPGME_PROTOCOL_OpenPGP:
552       return _gpgme_gpg_op_verify (engine->engine.gpg, sig, text);
553     case GPGME_PROTOCOL_CMS:
554       return _gpgme_gpgsm_op_verify (engine->engine.gpgsm, sig, text);
555     default:
556       break;
557     }
558   return 0;
559 }
560
561 GpgmeError
562 _gpgme_engine_start (EngineObject engine, void *opaque)
563 {
564   if (!engine)
565     return mk_error (Invalid_Value);
566
567   switch (engine->protocol)
568     {
569     case GPGME_PROTOCOL_OpenPGP:
570       return _gpgme_gpg_spawn (engine->engine.gpg, opaque);
571     case GPGME_PROTOCOL_CMS:
572       return _gpgme_gpgsm_start (engine->engine.gpgsm, opaque);
573     default:
574       break;
575     }
576   return 0;
577 }
578
579 void
580 _gpgme_engine_set_io_cbs (EngineObject engine,
581                           struct GpgmeIOCbs *io_cbs)
582 {
583   if (!engine)
584     return;
585
586   switch (engine->protocol)
587     {
588     case GPGME_PROTOCOL_OpenPGP:
589       _gpgme_gpg_set_io_cbs (engine->engine.gpg, io_cbs);
590       break;
591     case GPGME_PROTOCOL_CMS:
592       _gpgme_gpgsm_set_io_cbs (engine->engine.gpgsm, io_cbs);
593       break;
594     default:
595       break;
596     }
597 }
598
599 void
600 _gpgme_engine_io_event (EngineObject engine,
601                         GpgmeEventIO type, void *type_data)
602 {
603   if (!engine)
604     return;
605
606   switch (engine->protocol)
607     {
608     case GPGME_PROTOCOL_OpenPGP:
609       _gpgme_gpg_io_event (engine->engine.gpg, type, type_data);
610       break;
611     case GPGME_PROTOCOL_CMS:
612       _gpgme_gpgsm_io_event (engine->engine.gpgsm, type, type_data);
613       break;
614     default:
615       break;
616     }
617 }