gpgme/
[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                        GpgmeCtx ctx /* FIXME */)
336 {
337   if (!engine)
338     return mk_error (Invalid_Value);
339
340   switch (engine->protocol)
341     {
342     case GPGME_PROTOCOL_OpenPGP:
343       return _gpgme_gpg_op_edit (engine->engine.gpg, key, out, ctx);
344     case GPGME_PROTOCOL_CMS:
345       /* FIXME */
346       return mk_error (Not_Implemented);
347     default:
348       break;
349     }
350   return 0;
351 }
352
353 GpgmeError
354 _gpgme_engine_op_encrypt (EngineObject engine, GpgmeRecipients recp,
355                           GpgmeData plain, GpgmeData ciph, int use_armor)
356 {
357   if (!engine)
358     return mk_error (Invalid_Value);
359
360   switch (engine->protocol)
361     {
362     case GPGME_PROTOCOL_OpenPGP:
363       return _gpgme_gpg_op_encrypt (engine->engine.gpg, recp, plain, ciph,
364                                     use_armor);
365     case GPGME_PROTOCOL_CMS:
366       return _gpgme_gpgsm_op_encrypt (engine->engine.gpgsm, recp, plain, ciph,
367                                       use_armor);
368     default:
369       break;
370     }
371   return 0;
372 }
373
374
375 GpgmeError
376 _gpgme_engine_op_encrypt_sign (EngineObject engine, GpgmeRecipients recp,
377                                GpgmeData plain, GpgmeData ciph, int use_armor,
378                                GpgmeCtx ctx /* FIXME */)
379 {
380   if (!engine)
381     return mk_error (Invalid_Value);
382
383   switch (engine->protocol)
384     {
385     case GPGME_PROTOCOL_OpenPGP:
386       return _gpgme_gpg_op_encrypt_sign (engine->engine.gpg, recp, plain, ciph,
387                                          use_armor, ctx);
388     case GPGME_PROTOCOL_CMS:
389       return mk_error (Not_Implemented);
390     default:
391       break;
392     }
393   return 0;
394 }
395
396
397 GpgmeError
398 _gpgme_engine_op_export (EngineObject engine, GpgmeRecipients recp,
399                          GpgmeData keydata, int use_armor)
400 {
401   if (!engine)
402     return mk_error (Invalid_Value);
403
404   switch (engine->protocol)
405     {
406     case GPGME_PROTOCOL_OpenPGP:
407       return _gpgme_gpg_op_export (engine->engine.gpg, recp, keydata,
408                                    use_armor);
409     case GPGME_PROTOCOL_CMS:
410       return _gpgme_gpgsm_op_export (engine->engine.gpgsm, recp, keydata,
411                                      use_armor);
412     default:
413       break;
414     }
415   return 0;
416 }
417
418 GpgmeError
419 _gpgme_engine_op_genkey (EngineObject engine, GpgmeData help_data,
420                          int use_armor, GpgmeData pubkey, GpgmeData seckey)
421 {
422   if (!engine)
423     return mk_error (Invalid_Value);
424
425   switch (engine->protocol)
426     {
427     case GPGME_PROTOCOL_OpenPGP:
428       return _gpgme_gpg_op_genkey (engine->engine.gpg, help_data, use_armor,
429                                    pubkey, seckey);
430     case GPGME_PROTOCOL_CMS:
431       return _gpgme_gpgsm_op_genkey (engine->engine.gpgsm, help_data, use_armor,
432                                      pubkey, seckey);
433     default:
434       break;
435     }
436   return 0;
437 }
438
439 GpgmeError
440 _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata)
441 {
442   if (!engine)
443     return mk_error (Invalid_Value);
444
445   switch (engine->protocol)
446     {
447     case GPGME_PROTOCOL_OpenPGP:
448       return _gpgme_gpg_op_import (engine->engine.gpg, keydata);
449     case GPGME_PROTOCOL_CMS:
450       return _gpgme_gpgsm_op_import (engine->engine.gpgsm, keydata);
451     default:
452       break;
453     }
454   return 0;
455 }
456
457
458 GpgmeError
459 _gpgme_engine_op_keylist (EngineObject engine, const char *pattern,
460                           int secret_only, int keylist_mode)
461 {
462   if (!engine)
463     return mk_error (Invalid_Value);
464
465   switch (engine->protocol)
466     {
467     case GPGME_PROTOCOL_OpenPGP:
468       return _gpgme_gpg_op_keylist (engine->engine.gpg, pattern, secret_only,
469                                     keylist_mode);
470     case GPGME_PROTOCOL_CMS:
471       return _gpgme_gpgsm_op_keylist (engine->engine.gpgsm, pattern, secret_only,
472                                       keylist_mode);
473     default:
474       break;
475     }
476   return 0;
477 }
478
479
480 GpgmeError
481 _gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[],
482                               int secret_only, int reserved, int keylist_mode)
483 {
484   if (!engine)
485     return mk_error (Invalid_Value);
486
487   switch (engine->protocol)
488     {
489     case GPGME_PROTOCOL_OpenPGP:
490       return _gpgme_gpg_op_keylist_ext (engine->engine.gpg, pattern,
491                                         secret_only, reserved, keylist_mode);
492     case GPGME_PROTOCOL_CMS:
493       return _gpgme_gpgsm_op_keylist_ext (engine->engine.gpgsm, pattern,
494                                           secret_only, reserved, keylist_mode);
495     default:
496       break;
497     }
498   return 0;
499 }
500
501
502 GpgmeError
503 _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out,
504                        GpgmeSigMode mode, int use_armor,
505                        int use_textmode, int include_certs,
506                        GpgmeCtx ctx /* FIXME */)
507 {
508   if (!engine)
509     return mk_error (Invalid_Value);
510
511   switch (engine->protocol)
512     {
513     case GPGME_PROTOCOL_OpenPGP:
514       return _gpgme_gpg_op_sign (engine->engine.gpg, in, out, mode, use_armor,
515                                  use_textmode, ctx);
516     case GPGME_PROTOCOL_CMS:
517       return _gpgme_gpgsm_op_sign (engine->engine.gpgsm, in, out, mode,
518                                    use_armor, use_textmode, include_certs, ctx);
519       break;
520     default:
521       break;
522     }
523   return 0;
524 }
525
526 GpgmeError
527 _gpgme_engine_op_trustlist (EngineObject engine, const char *pattern)
528 {
529   if (!engine)
530     return mk_error (Invalid_Value);
531
532   switch (engine->protocol)
533     {
534     case GPGME_PROTOCOL_OpenPGP:
535       return _gpgme_gpg_op_trustlist (engine->engine.gpg, pattern);
536     case GPGME_PROTOCOL_CMS:
537       return _gpgme_gpgsm_op_trustlist (engine->engine.gpgsm, pattern);
538     default:
539       break;
540     }
541   return 0;
542 }
543
544 GpgmeError
545 _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
546                          GpgmeData signed_text, GpgmeData plaintext)
547 {
548   if (!engine)
549     return mk_error (Invalid_Value);
550
551   switch (engine->protocol)
552     {
553     case GPGME_PROTOCOL_OpenPGP:
554       return _gpgme_gpg_op_verify (engine->engine.gpg, sig,
555                                    signed_text, plaintext);
556     case GPGME_PROTOCOL_CMS:
557       return _gpgme_gpgsm_op_verify (engine->engine.gpgsm, sig,
558                                      signed_text, plaintext);
559     default:
560       break;
561     }
562   return 0;
563 }
564
565 GpgmeError
566 _gpgme_engine_start (EngineObject engine, void *opaque)
567 {
568   if (!engine)
569     return mk_error (Invalid_Value);
570
571   switch (engine->protocol)
572     {
573     case GPGME_PROTOCOL_OpenPGP:
574       return _gpgme_gpg_spawn (engine->engine.gpg, opaque);
575     case GPGME_PROTOCOL_CMS:
576       return _gpgme_gpgsm_start (engine->engine.gpgsm, opaque);
577     default:
578       break;
579     }
580   return 0;
581 }
582
583 void
584 _gpgme_engine_set_io_cbs (EngineObject engine,
585                           struct GpgmeIOCbs *io_cbs)
586 {
587   if (!engine)
588     return;
589
590   switch (engine->protocol)
591     {
592     case GPGME_PROTOCOL_OpenPGP:
593       _gpgme_gpg_set_io_cbs (engine->engine.gpg, io_cbs);
594       break;
595     case GPGME_PROTOCOL_CMS:
596       _gpgme_gpgsm_set_io_cbs (engine->engine.gpgsm, io_cbs);
597       break;
598     default:
599       break;
600     }
601 }
602
603 void
604 _gpgme_engine_io_event (EngineObject engine,
605                         GpgmeEventIO type, void *type_data)
606 {
607   if (!engine)
608     return;
609
610   switch (engine->protocol)
611     {
612     case GPGME_PROTOCOL_OpenPGP:
613       _gpgme_gpg_io_event (engine->engine.gpg, type, type_data);
614       break;
615     case GPGME_PROTOCOL_CMS:
616       _gpgme_gpgsm_io_event (engine->engine.gpgsm, type, type_data);
617       break;
618     default:
619       break;
620     }
621 }