now signMessage() calls the gpgme_set_include_certs() function before each call of...
[gpgme.git] / gpgmeplug / gpgmeplug.c
1 /* -*- Mode: C -*-
2
3   $Id$
4
5   GPGMEPLUG - an GPGME based cryptography plug-in following
6               the common CRYPTPLUG specification.
7
8   Copyright (C) 2001 by Klarälvdalens Datakonsult AB
9
10   GPGMEPLUG is free software; you can redistribute it and/or modify
11   it under the terms of GNU General Public License as published by
12   the Free Software Foundation; version 2 of the License.
13
14   GPGMEPLUG is distributed in the hope that it will be useful,
15   it under the terms of GNU General Public License as published by
16   the Free Software Foundation; version 2 of the License
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
24 */
25
26
27
28 /*! \file gpgmeplug.c
29     \brief GPGME implementation of CRYPTPLUG following the
30     specification located in common API header cryptplug.h.
31
32     CRYPTPLUG is an independent cryptography plug-in API
33     developed for Sphinx-enabeling KMail and Mutt.
34
35     CRYPTPLUG was designed for the Aegypten project, but it may
36     be used by 3rd party developers as well to design pluggable
37     crypto backends for the above mentioned MUAs.
38
39     \note All string parameters appearing in this API are to be
40     interpreted as UTF-8 encoded.
41
42     \see cryptplug.h
43 */
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48 #include <stdio.h>
49 #include <string.h>
50 #include <assert.h>
51 #include <errno.h>
52 #include <time.h>
53
54 #ifndef BUG_URL
55 #define BUG_URL "http:://www.gnupg.org/aegypten/"
56 #endif
57
58 #include "gpgme.h"
59 #ifndef GPGMEPLUG_PROTOCOL
60 #define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
61 #endif
62
63 // definitions for signing
64 #ifndef GPGMEPLUG_SIGN_MAKE_MIME_OBJECT
65 #define GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT true
66 #define GPGMEPLUG_SIGN_MAKE_MIME_OBJECT  true
67 #define GPGMEPLUG_SIGN_MAKE_MULTI_MIME   true
68 #define GPGMEPLUG_SIGN_CTYPE_MAIN        "multipart/signed;protocol=application/pgp-signature;micalg=pgp-sha1"
69 #define GPGMEPLUG_SIGN_CDISP_MAIN        ""
70 #define GPGMEPLUG_SIGN_CTENC_MAIN        ""
71 #define GPGMEPLUG_SIGN_CTYPE_VERSION     ""
72 #define GPGMEPLUG_SIGN_CDISP_VERSION     ""
73 #define GPGMEPLUG_SIGN_CTENC_VERSION     ""
74 #define GPGMEPLUG_SIGN_BTEXT_VERSION     ""
75 #define GPGMEPLUG_SIGN_CTYPE_CODE        "application/pgp-signature"
76 #define GPGMEPLUG_SIGN_CDISP_CODE        ""
77 #define GPGMEPLUG_SIGN_CTENC_CODE        ""
78 #define GPGMEPLUG_SIGN_FLAT_PREFIX       ""
79 #define GPGMEPLUG_SIGN_FLAT_SEPARATOR    ""
80 #define GPGMEPLUG_SIGN_FLAT_POSTFIX      ""
81 #endif
82 // definitions for encoding
83 #ifndef GPGMEPLUG_ENC_MAKE_MIME_OBJECT
84 #define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT  false
85 #define GPGMEPLUG_ENC_MAKE_MIME_OBJECT   true
86 #define GPGMEPLUG_ENC_MAKE_MULTI_MIME    true
87 #define GPGMEPLUG_ENC_CTYPE_MAIN         "multipart/encrypted; protocol=application/pgp-encrypted"
88 #define GPGMEPLUG_ENC_CDISP_MAIN         ""
89 #define GPGMEPLUG_ENC_CTENC_MAIN         ""
90 #define GPGMEPLUG_ENC_CTYPE_VERSION      "application/pgp-encrypted"
91 #define GPGMEPLUG_ENC_CDISP_VERSION      "attachment"
92 #define GPGMEPLUG_ENC_CTENC_VERSION      ""
93 #define GPGMEPLUG_ENC_BTEXT_VERSION      "Version: 1"
94 #define GPGMEPLUG_ENC_CTYPE_CODE         "application/octet-stream"
95 #define GPGMEPLUG_ENC_CDISP_CODE         "inline; filename=\"msg.asc\""
96 #define GPGMEPLUG_ENC_CTENC_CODE         ""
97 #define GPGMEPLUG_ENC_FLAT_PREFIX        ""
98 #define GPGMEPLUG_ENC_FLAT_SEPARATOR     ""
99 #define GPGMEPLUG_ENC_FLAT_POSTFIX       ""
100 #endif
101 // Note: The following specification will result in
102 //       function encryptAndSignMessage() producing
103 //       _empty_ mails.
104 //       This must be changed as soon as our plugin
105 //       is supporting the encryptAndSignMessage() function.
106 #ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
107 #define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
108 #define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT  false
109 #define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME   false
110 #define GPGMEPLUG_ENCSIGN_CTYPE_MAIN        ""
111 #define GPGMEPLUG_ENCSIGN_CDISP_MAIN        ""
112 #define GPGMEPLUG_ENCSIGN_CTENC_MAIN        ""
113 #define GPGMEPLUG_ENCSIGN_CTYPE_VERSION     ""
114 #define GPGMEPLUG_ENCSIGN_CDISP_VERSION     ""
115 #define GPGMEPLUG_ENCSIGN_CTENC_VERSION     ""
116 #define GPGMEPLUG_ENCSIGN_BTEXT_VERSION     ""
117 #define GPGMEPLUG_ENCSIGN_CTYPE_CODE        ""
118 #define GPGMEPLUG_ENCSIGN_CDISP_CODE        ""
119 #define GPGMEPLUG_ENCSIGN_CTENC_CODE        ""
120 #define GPGMEPLUG_ENCSIGN_FLAT_PREFIX       ""
121 #define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR    ""
122 #define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX      ""
123 #endif
124
125 #include "cryptplug.h"
126
127
128 typedef struct {
129   const char*             bugURL;
130   const char*             signatureKeyCertificate;
131   SignatureAlgorithm      signatureAlgorithm;
132   SendCertificates        sendCertificates;
133   SignEmail               signEmail;
134   bool                    saveSentSignatures;
135   bool                    warnNoCertificate;
136   PinRequests             numPINRequests;
137   bool                    checkSignatureCertificatePathToRoot;
138   bool                    signatureUseCRLs;
139   EncryptionAlgorithm     encryptionAlgorithm;
140   EncryptEmail            encryptEmail;
141   bool                    saveMessagesEncrypted;
142   bool                    checkEncryptionCertificatePathToRoot;
143   bool                    encryptionUseCRLs;
144   bool                    encryptionCRLExpiryNearWarning;
145   int                     encryptionCRLNearExpiryInterval;
146   struct DirectoryServer *directoryServers;
147   unsigned int            numDirectoryServers;
148   CertificateSource       certificateSource;
149   CertificateSource       cRLSource;
150   bool                    warnSendUnsigned;
151   int                     numPINRequestsInterval;
152   bool                    signatureCertificateExpiryNearWarning;
153   int                     signatureCertificateExpiryNearInterval;
154   bool                    cACertificateExpiryNearWarning;
155   int                     cACertificateExpiryNearInterval;
156   bool                    rootCertificateExpiryNearWarning;
157   int                     rootCertificateExpiryNearInterval;
158   bool                    warnSendUnencrypted;
159   bool                    checkCertificatePath;
160   bool                    receiverCertificateExpiryNearWarning;
161   int                     receiverCertificateExpiryNearWarningInterval;
162   bool                    certificateInChainExpiryNearWarning;
163   int                     certificateInChainExpiryNearWarningInterval;
164   bool                    receiverEmailAddressNotInCertificateWarning;
165 } Config;
166
167
168 Config config;
169
170 #define NEAR_EXPIRY 14
171
172 bool initialize()
173 {
174   config.bugURL                               = malloc( strlen( BUG_URL ) + 1 );
175   strcpy( (char* )config.bugURL,                BUG_URL );
176   config.signatureKeyCertificate              = malloc( 1 );
177   strcpy( (char* )config.signatureKeyCertificate, "" );
178   config.signatureAlgorithm                   = SignAlg_SHA1;
179   config.sendCertificates                     = SendCert_SendChainWithRoot;
180   config.signEmail                            = SignEmail_SignAll;
181   config.saveSentSignatures                   = true;
182   config.warnNoCertificate                    = true;
183   config.numPINRequests                       = PinRequest_Always;
184   config.checkSignatureCertificatePathToRoot  = true;
185   config.signatureUseCRLs                     = true;
186   config.encryptionAlgorithm                  = EncryptAlg_RSA;
187   config.encryptEmail                         = EncryptEmail_Ask;
188   config.saveMessagesEncrypted                = true;
189   config.checkEncryptionCertificatePathToRoot = true;
190   config.encryptionUseCRLs                    = true;
191   config.encryptionCRLExpiryNearWarning       = true;
192   config.encryptionCRLNearExpiryInterval      = NEAR_EXPIRY;
193   config.directoryServers                     = NULL;
194   config.numDirectoryServers                  = 0;
195   config.certificateSource                    = CertSrc_Server;
196   config.cRLSource                            = CertSrc_Server;
197   config.warnSendUnsigned                             = true;
198   config.numPINRequestsInterval                       = NEAR_EXPIRY;
199   config.signatureCertificateExpiryNearWarning        = true;
200   config.signatureCertificateExpiryNearInterval       = NEAR_EXPIRY;
201   config.cACertificateExpiryNearWarning               = true;
202   config.cACertificateExpiryNearInterval              = NEAR_EXPIRY;
203   config.rootCertificateExpiryNearWarning             = true;
204   config.rootCertificateExpiryNearInterval            = NEAR_EXPIRY;
205   config.warnSendUnencrypted                          = false;
206   config.checkCertificatePath                         = true;
207   config.receiverCertificateExpiryNearWarning         = true;
208   config.receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY;
209   config.certificateInChainExpiryNearWarning          = true;
210   config.certificateInChainExpiryNearWarningInterval  = NEAR_EXPIRY;
211   config.receiverEmailAddressNotInCertificateWarning  = true;
212
213   return true;
214 };
215
216
217 void deinitialize()
218 {
219   unsigned int i;
220   for( i = 0; i < config.numDirectoryServers; ++i ) {
221     free( (char *)config.directoryServers[i].servername );
222     free( (char *)config.directoryServers[i].description );
223   }
224   free( config.directoryServers );
225 }
226
227
228 bool hasFeature( Feature flag )
229 {
230   switch ( flag ) {
231     case CryptPlugFeat_SignMessages:              return true;
232     case CryptPlugFeat_VerifySignatures:          return true;
233     case CryptPlugFeat_EncryptMessages:           return true;
234     case CryptPlugFeat_DecryptMessages:           return true;
235     // undefined or not yet implemented:
236     case CryptPlugFeat_undef:                     return false;
237     default:                                      return false;
238   }
239 }
240
241
242 const char* bugURL(){ return config.bugURL; }
243
244
245 void unsafeStationery( void** pixmap, const char** menutext, char* accel,
246           const char** tooltip, const char** statusbartext ){}
247
248 void signedStationery( void** pixmap, const char** menutext, char* accel,
249           const char** tooltip, const char** statusbartext ){}
250
251 void encryptedStationery( void** pixmap, const char**
252           menutext, char* accel,
253           const char** tooltip, const char** statusbartext ){}
254
255 void signedEncryptedStationery( void** pixmap, const char**
256           menutext, char* accel,
257           const char** tooltip, const char** statusbartext ){}
258
259 const char* signatureConfigurationDialog(){ return 0; }
260
261 const char* signatureKeySelectionDialog(){ return 0; }
262
263 const char* signatureAlgorithmDialog(){ return 0; }
264
265 const char* signatureHandlingDialog(){ return 0; }
266
267 void setSignatureKeyCertificate( const char* certificate )
268 {
269   config.signatureKeyCertificate = certificate;
270 }
271
272 const char* signatureKeyCertificate()
273 {
274   return config.signatureKeyCertificate;
275 }
276
277 void setSignatureAlgorithm( SignatureAlgorithm sigAlg )
278 {
279   config.signatureAlgorithm = sigAlg;
280 }
281
282 SignatureAlgorithm signatureAlgorithm()
283 {
284   return config.signatureAlgorithm;
285 }
286
287 void setSendCertificates( SendCertificates sendCert )
288 {
289   config.sendCertificates = sendCert;
290 }
291
292 SendCertificates sendCertificates()
293 {
294   return config.sendCertificates;
295 }
296
297 void setSignEmail( SignEmail signMail )
298 {
299   config.signEmail = signMail;
300 }
301
302 SignEmail signEmail()
303 {
304   return config.signEmail;
305 }
306
307
308
309
310
311 void setWarnSendUnsigned( bool flag )
312 {
313   config.warnSendUnsigned = flag;
314 }
315
316 bool warnSendUnsigned()
317 {
318   return config.warnSendUnsigned;
319 }
320
321
322
323
324
325
326 void setSaveSentSignatures( bool flag )
327 {
328   config.saveSentSignatures = flag;
329 }
330
331 bool saveSentSignatures()
332 {
333   return config.saveSentSignatures;
334 }
335
336 void setWarnNoCertificate( bool flag )
337 {
338   config.warnNoCertificate = flag;
339 }
340
341 bool warnNoCertificate()
342 {
343   return config.warnNoCertificate;
344 }
345
346 void setNumPINRequests( PinRequests reqMode )
347 {
348   config.numPINRequests = reqMode;
349 }
350
351 PinRequests numPINRequests()
352 {
353   return config.numPINRequests;
354 }
355
356
357
358
359
360 void setNumPINRequestsInterval( int interval )
361 {
362   config.numPINRequestsInterval = interval;
363 }
364
365 int numPINRequestsInterval()
366 {
367   return config.numPINRequestsInterval;
368 }
369
370
371
372
373
374
375
376 void setCheckSignatureCertificatePathToRoot( bool flag )
377 {
378   config.checkSignatureCertificatePathToRoot = flag;
379 }
380
381 bool checkSignatureCertificatePathToRoot()
382 {
383   return config.checkSignatureCertificatePathToRoot;
384 }
385
386 void setSignatureUseCRLs( bool flag )
387 {
388   config.signatureUseCRLs = flag;
389 }
390
391 bool signatureUseCRLs()
392 {
393   return config.signatureUseCRLs;
394 }
395
396
397
398
399
400
401 void setSignatureCertificateExpiryNearWarning( bool flag )
402 {
403   config.signatureCertificateExpiryNearWarning = flag;
404 }
405
406 bool signatureCertificateExpiryNearWarning( void )
407 {
408   return config.signatureCertificateExpiryNearWarning;
409 }
410
411 void setSignatureCertificateExpiryNearInterval( int interval )
412 {
413   config.signatureCertificateExpiryNearInterval = interval;
414 }
415
416 int signatureCertificateExpiryNearInterval( void )
417 {
418   return config.signatureCertificateExpiryNearInterval;
419 }
420
421 void setCACertificateExpiryNearWarning( bool flag )
422 {
423   config.cACertificateExpiryNearWarning = flag;
424 }
425
426 bool caCertificateExpiryNearWarning( void )
427 {
428   return config.cACertificateExpiryNearWarning;
429 }
430
431 void setCACertificateExpiryNearInterval( int interval )
432 {
433   config.cACertificateExpiryNearInterval = interval;
434 }
435
436 int caCertificateExpiryNearInterval( void )
437 {
438   return config.cACertificateExpiryNearInterval;
439 }
440
441 void setRootCertificateExpiryNearWarning( bool flag )
442 {
443   config.rootCertificateExpiryNearWarning = flag;
444 }
445
446 bool rootCertificateExpiryNearWarning( void )
447 {
448   return config.rootCertificateExpiryNearWarning;
449 }
450
451 void setRootCertificateExpiryNearInterval( int interval )
452 {
453   config.rootCertificateExpiryNearInterval = interval;
454 }
455
456 int rootCertificateExpiryNearInterval( void )
457 {
458   return config.rootCertificateExpiryNearInterval;
459 }
460
461
462
463
464
465
466
467
468 const char* encryptionConfigurationDialog(){ return 0; }
469
470 const char* encryptionAlgorithmDialog(){ return 0; }
471
472 const char* encryptionHandlingDialog(){ return 0; }
473
474 const char* encryptionReceiverDialog(){ return 0; }
475
476 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
477 {
478   config.encryptionAlgorithm = cryptAlg;
479 }
480
481 EncryptionAlgorithm encryptionAlgorithm()
482 {
483   return config.encryptionAlgorithm;
484 }
485
486 void setEncryptEmail( EncryptEmail cryptMode )
487 {
488   config.encryptEmail = cryptMode;
489 }
490
491 EncryptEmail encryptEmail()
492 {
493   return config.encryptEmail;
494 }
495
496
497
498
499
500
501 void setWarnSendUnencrypted( bool flag )
502 {
503   config.warnSendUnencrypted = flag;
504 }
505
506 bool warnSendUnencrypted()
507 {
508   return config.warnSendUnencrypted;
509 }
510
511
512
513
514
515
516
517
518
519 void setSaveMessagesEncrypted( bool flag )
520 {
521   config.saveMessagesEncrypted = flag;
522 }
523
524 bool saveMessagesEncrypted()
525 {
526   return config.saveMessagesEncrypted;
527 }
528
529
530
531
532
533
534
535 void setCheckCertificatePath( bool flag )
536 {
537   config.checkCertificatePath = flag;
538 }
539
540 bool checkCertificatePath()
541 {
542   return config.checkCertificatePath;
543 }
544
545
546
547
548
549
550
551
552 void setCheckEncryptionCertificatePathToRoot( bool flag )
553 {
554   config.checkEncryptionCertificatePathToRoot = flag;
555 }
556
557 bool checkEncryptionCertificatePathToRoot()
558 {
559   return config.checkEncryptionCertificatePathToRoot;
560 }
561
562
563
564
565
566
567
568 void setReceiverCertificateExpiryNearWarning( bool flag )
569 {
570   config.receiverCertificateExpiryNearWarning = flag;
571 }
572
573 bool receiverCertificateExpiryNearWarning()
574 {
575   return config.receiverCertificateExpiryNearWarning;
576 }
577
578 void setReceiverCertificateExpiryNearWarningInterval( int interval )
579 {
580   config.receiverCertificateExpiryNearWarningInterval = interval;
581 }
582
583 int receiverCertificateExpiryNearWarningInterval()
584 {
585   return config.receiverCertificateExpiryNearWarningInterval;
586 }
587
588 void setCertificateInChainExpiryNearWarning( bool flag )
589 {
590   config.certificateInChainExpiryNearWarning = flag;
591 }
592
593 bool certificateInChainExpiryNearWarning()
594 {
595   return config.certificateInChainExpiryNearWarning;
596 }
597
598 void setCertificateInChainExpiryNearWarningInterval( int interval )
599 {
600   config.certificateInChainExpiryNearWarningInterval = interval;
601 }
602
603 int certificateInChainExpiryNearWarningInterval()
604 {
605   return config.certificateInChainExpiryNearWarningInterval;
606 }
607
608 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
609 {
610   config.receiverEmailAddressNotInCertificateWarning = flag;
611 }
612
613 bool receiverEmailAddressNotInCertificateWarning()
614 {
615   return config.receiverEmailAddressNotInCertificateWarning;
616 }
617
618
619
620
621
622
623
624
625 void setEncryptionUseCRLs( bool flag )
626 {
627   config.encryptionUseCRLs = flag;
628 }
629
630 bool encryptionUseCRLs()
631 {
632   return config.encryptionUseCRLs;
633 }
634
635 void setEncryptionCRLExpiryNearWarning( bool flag )
636 {
637   config.encryptionCRLExpiryNearWarning = flag;
638 }
639
640 bool encryptionCRLExpiryNearWarning()
641 {
642   return config.encryptionCRLExpiryNearWarning;
643 }
644
645 void setEncryptionCRLNearExpiryInterval( int interval )
646 {
647   config.encryptionCRLNearExpiryInterval = interval;
648 }
649
650 int encryptionCRLNearExpiryInterval()
651 {
652   return config.encryptionCRLNearExpiryInterval;
653 }
654
655
656 const char* directoryServiceConfigurationDialog(){ return 0; }
657
658 void appendDirectoryServer( const char* servername,
659                             int         port,
660                             const char* description )
661 {
662   struct DirectoryServer *newServers = NULL;
663   newServers = realloc( config.directoryServers,
664                         (1+config.numDirectoryServers) * sizeof *newServers );
665   if( newServers ) {
666     config.directoryServers = newServers;
667     newServers[ config.numDirectoryServers ].servername =
668       malloc( 1+strlen( servername ) );
669     if( newServers[ config.numDirectoryServers ].servername ) {
670       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
671         servername );
672       newServers[ config.numDirectoryServers ].description =
673         malloc( 1+strlen(  description ) );
674       if( newServers[ config.numDirectoryServers ].description ) {
675         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
676           description );
677         newServers[ config.numDirectoryServers ].port = port;
678         config.numDirectoryServers += 1;
679       }
680     }
681   }
682 }
683
684 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
685 {
686   unsigned int i;
687   int oldSize = config.numDirectoryServers;
688   struct DirectoryServer *newServers = NULL;
689   newServers = calloc ( size, sizeof *newServers );
690   if( newServers ) {
691     for( i=0; i < oldSize; ++i ) {
692       free( (char *)config.directoryServers[i].servername );
693       free( (char *)config.directoryServers[i].description );
694     }
695     free( config.directoryServers );
696     for( i=0; i < size; ++i ) {
697       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
698       if( newServers[ i ].servername ) {
699         strcpy( (char *)newServers[ i ].servername, server[i].servername );
700         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
701         if( newServers[ i ].description ) {
702           strcpy( (char *)newServers[ i ].description, server[i].description );
703           newServers[ i ].port = server[i].port;
704         }
705       }
706     }
707     config.directoryServers = newServers;
708     config.numDirectoryServers = size;
709   }
710 }
711
712 struct DirectoryServer * directoryServers( int* numServers )
713 {
714   if( numServers )
715     *numServers = config.numDirectoryServers;
716   return config.directoryServers;
717 };
718
719 void setCertificateSource( CertificateSource source )
720 {
721   config.certificateSource = source;
722 }
723
724 CertificateSource certificateSource()
725 {
726   return config.certificateSource;
727 }
728
729 void setCRLSource( CertificateSource source )
730 {
731   config.cRLSource = source;
732 }
733
734 CertificateSource crlSource()
735 {
736   return config.cRLSource;
737 }
738
739
740 bool certificateValidity( const char* certificate,
741                           int* level ){ return true; }
742
743
744 void storeNewCharPtr( char** dest, const char* src )
745 {
746   int sLen = strlen( src );
747   *dest = malloc( sLen + 1 );
748   strcpy( *dest, src );
749   (*dest)[sLen] = '\0';
750 }
751
752
753 bool signMessage( const char*  cleartext,
754                   const char** ciphertext,
755                   const char*  certificate,
756                   struct StructuringInfo* structuring )
757 {
758   GpgmeCtx ctx;
759   GpgmeError err;
760   GpgmeData data,  sig;
761   size_t rSLen = 0;
762   char*  rSig  = 0;
763   bool   bOk   = false;
764
765   init_StructuringInfo( structuring );
766
767   if( !ciphertext )
768     return false;
769
770   err = gpgme_new (&ctx);
771   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
772
773   gpgme_set_armor (ctx, 1);
774   gpgme_set_textmode (ctx, 1);
775
776   int sendCerts;
777   switch ( config.sendCertificates() ) {
778     case SendCert_undef:
779       break;
780     case SendCert_DontSend:
781       sendCerts = 0;
782       break;
783     case SendCert_SendOwn:
784       sendCerts = 1;
785       break;
786     case SendCert_SendChainWithoutRoot:
787       sendCerts = -2;
788       break;
789     case SendCert_SendChainWithRoot:
790       sendCerts = -1;
791       break;
792     default:
793       sendCerts = 0;
794       break;
795   }
796   gpgme_set_include_certs (ctx, sendCerts);
797
798   gpgme_data_new_from_mem (&data, cleartext,
799                             1+strlen( cleartext ), 1 );
800   gpgme_data_new ( &sig );
801   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
802
803   if (!err) {
804     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
805     *ciphertext = malloc( rSLen + 1 );
806     if( *ciphertext ) {
807       if( rSLen ) {
808         bOk = true;
809         strncpy((char*)*ciphertext, rSig, rSLen );
810       }
811       ((char*)(*ciphertext))[rSLen] = '\0';
812     }
813     free( rSig );
814   }
815   else {
816     gpgme_data_release( sig );
817     *ciphertext = 0;
818     // hier fehlt eine Fehlerbehandlung, falls das
819     // Signieren schiefging
820   }
821   gpgme_data_release( data );
822   gpgme_release (ctx);
823
824   if( bOk && structuring ) {
825     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
826     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
827     if( structuring->makeMimeObject ) {
828       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
829       storeNewCharPtr( &structuring->contentTypeMain,
830                        GPGMEPLUG_SIGN_CTYPE_MAIN );
831       storeNewCharPtr( &structuring->contentDispMain,
832                        GPGMEPLUG_SIGN_CDISP_MAIN );
833       storeNewCharPtr( &structuring->contentTEncMain,
834                        GPGMEPLUG_SIGN_CTENC_MAIN );
835       if( structuring->makeMultiMime ) {
836         storeNewCharPtr( &structuring->contentTypeVersion,
837                          GPGMEPLUG_SIGN_CTYPE_VERSION );
838         storeNewCharPtr( &structuring->contentDispVersion,
839                          GPGMEPLUG_SIGN_CDISP_VERSION );
840         storeNewCharPtr( &structuring->contentTEncVersion,
841                          GPGMEPLUG_SIGN_CTENC_VERSION );
842         storeNewCharPtr( &structuring->bodyTextVersion,
843                          GPGMEPLUG_SIGN_BTEXT_VERSION );
844         storeNewCharPtr( &structuring->contentTypeCode,
845                          GPGMEPLUG_SIGN_CTYPE_CODE );
846         storeNewCharPtr( &structuring->contentDispCode,
847                          GPGMEPLUG_SIGN_CDISP_CODE );
848         storeNewCharPtr( &structuring->contentTEncCode,
849                          GPGMEPLUG_SIGN_CTENC_CODE );
850       }
851     } else {
852       storeNewCharPtr( &structuring->flatTextPrefix,
853                        GPGMEPLUG_SIGN_FLAT_PREFIX );
854       storeNewCharPtr( &structuring->flatTextSeparator,
855                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
856       storeNewCharPtr( &structuring->flatTextPostfix,
857                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
858     }
859   }
860   return bOk;
861 }
862
863
864 static const char*
865 sig_status_to_string( GpgmeSigStat status )
866 {
867   const char *result;
868
869   switch (status) {
870     case GPGME_SIG_STAT_NONE:
871       result = "Oops: Signature not verified";
872       break;
873     case GPGME_SIG_STAT_NOSIG:
874       result = "No signature found";
875       break;
876     case GPGME_SIG_STAT_GOOD:
877       result = "Good signature";
878       break;
879     case GPGME_SIG_STAT_BAD:
880       result = "BAD signature";
881       break;
882     case GPGME_SIG_STAT_NOKEY:
883       result = "No public key to verify the signature";
884       break;
885     case GPGME_SIG_STAT_ERROR:
886       result = "Error verifying the signature";
887       break;
888     case GPGME_SIG_STAT_DIFF:
889       result = "Different results for signatures";
890       break;
891     default:
892       result = "Error: Unknown status";
893       break;
894   }
895
896   return result;
897 }
898
899
900 bool checkMessageSignature( const char* ciphertext,
901                             const char* signaturetext,
902                             struct SignatureMetaData* sigmeta )
903 {
904   GpgmeCtx ctx;
905   GpgmeSigStat status;
906   GpgmeData datapart, sigpart;
907   GpgmeError err;
908   GpgmeKey key;
909   time_t created;
910   int sig_idx = 0;
911   const char* statusStr;
912   const char* fpr;
913
914   gpgme_new( &ctx );
915   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
916   gpgme_data_new_from_mem( &datapart, ciphertext,
917                           1+strlen( ciphertext ), 1 );
918   gpgme_data_new_from_mem( &sigpart, signaturetext,
919                           1+strlen( signaturetext ), 1 );
920
921   gpgme_op_verify( ctx, sigpart, datapart, &status );
922   gpgme_data_release( datapart );
923   gpgme_data_release( sigpart );
924
925   /* Provide information in the sigmeta struct */
926   /* the status string */
927   statusStr = sig_status_to_string( status );
928   sigmeta->status = malloc( strlen( statusStr ) + 1 );
929   if( sigmeta->status ) {
930     strcpy( sigmeta->status, statusStr );
931     sigmeta->status[strlen( statusStr )] = '\0';
932   } else
933     ; // nothing to do, is already 0
934
935   // Extended information for any number of signatures.
936   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
937   sigmeta->extended_info = 0;
938   while( fpr != NULL ) {
939     struct tm* ctime_val;
940     const char* sig_status;
941
942     void* realloc_return = realloc( sigmeta->extended_info,
943                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
944     if( realloc_return ) {
945       sigmeta->extended_info = realloc_return;
946       // the creation time
947       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
948       if( sigmeta->extended_info[sig_idx].creation_time ) {
949         ctime_val = localtime( &created );
950         memcpy( sigmeta->extended_info[sig_idx].creation_time,
951                 ctime_val, sizeof( struct tm ) );
952       }
953
954       err = gpgme_get_sig_key (ctx, sig_idx, &key);
955       sig_status = sig_status_to_string( status );
956       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
957       if( sigmeta->extended_info[sig_idx].status_text ) {
958         strcpy( sigmeta->extended_info[sig_idx].status_text,
959                 sig_status );
960         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
961       }
962
963       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
964       if( sigmeta->extended_info[sig_idx].fingerprint ) {
965         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
966         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
967       }
968     } else
969       break; // if allocation fails once, it isn't likely to
970               // succeed the next time either
971
972     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
973   }
974   sigmeta->extended_info_count = sig_idx;
975   sigmeta->nota_xml = gpgme_get_notation( ctx );
976   sigmeta->status_code = status;
977
978   gpgme_release( ctx );
979   return ( status == GPGME_SIG_STAT_GOOD );
980 }
981
982 bool storeCertificatesFromMessage(
983         const char* ciphertext ){ return true; }
984
985
986 bool encryptMessage( const char* cleartext,
987                      const char** ciphertext,
988                      const char* addressee,
989                      struct StructuringInfo* structuring )
990 {
991   GpgmeCtx ctx;
992   GpgmeError err;
993   GpgmeData gCiphertext, gPlaintext;
994   GpgmeRecipients rset;
995   size_t rCLen = 0;
996   char*  rCiph = 0;
997   bool   bOk   = false;
998
999   init_StructuringInfo( structuring );
1000
1001   gpgme_new (&ctx);
1002   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1003
1004   gpgme_set_armor (ctx, 1);
1005   gpgme_set_textmode (ctx, 1);
1006
1007   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1008                             1+strlen( cleartext ), 1 );
1009   err = gpgme_data_new ( &gCiphertext );
1010
1011   gpgme_recipients_new (&rset);
1012
1013
1014   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1015   {
1016     gpgme_recipients_add_name_with_validity (rset,
1017       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
1018       GPGME_VALIDITY_FULL );
1019     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1020   }
1021   else
1022   {
1023     gpgme_recipients_add_name (rset, addressee);
1024     fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", addressee );
1025   }
1026
1027
1028   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1029   if( err )
1030     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1031
1032   gpgme_recipients_release (rset);
1033   gpgme_data_release (gPlaintext);
1034
1035   if( !err ) {
1036     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1037     *ciphertext = malloc( rCLen + 1 );
1038     if( *ciphertext ) {
1039       if( rCLen ) {
1040         bOk = true;
1041         strncpy((char*)*ciphertext, rCiph, rCLen );
1042       }
1043       ((char*)(*ciphertext))[rCLen] = 0;
1044     }
1045     free( rCiph );
1046   }
1047   else {
1048     gpgme_data_release ( gCiphertext );
1049     *ciphertext = 0;
1050     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1051     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1052     // das signieren.
1053   }
1054
1055   gpgme_release (ctx);
1056
1057   fflush( stderr );
1058
1059   if( bOk && structuring ) {
1060     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1061     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1062     if( structuring->makeMimeObject ) {
1063       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1064       storeNewCharPtr( &structuring->contentTypeMain,
1065                        GPGMEPLUG_ENC_CTYPE_MAIN );
1066       storeNewCharPtr( &structuring->contentDispMain,
1067                        GPGMEPLUG_ENC_CDISP_MAIN );
1068       storeNewCharPtr( &structuring->contentTEncMain,
1069                        GPGMEPLUG_ENC_CTENC_MAIN );
1070       if( structuring->makeMultiMime ) {
1071         storeNewCharPtr( &structuring->contentTypeVersion,
1072                          GPGMEPLUG_ENC_CTYPE_VERSION );
1073         storeNewCharPtr( &structuring->contentDispVersion,
1074                          GPGMEPLUG_ENC_CDISP_VERSION );
1075         storeNewCharPtr( &structuring->contentTEncVersion,
1076                          GPGMEPLUG_ENC_CTENC_VERSION );
1077         storeNewCharPtr( &structuring->bodyTextVersion,
1078                          GPGMEPLUG_ENC_BTEXT_VERSION );
1079         storeNewCharPtr( &structuring->contentTypeCode,
1080                          GPGMEPLUG_ENC_CTYPE_CODE );
1081         storeNewCharPtr( &structuring->contentDispCode,
1082                          GPGMEPLUG_ENC_CDISP_CODE );
1083         storeNewCharPtr( &structuring->contentTEncCode,
1084                          GPGMEPLUG_ENC_CTENC_CODE );
1085       }
1086     } else {
1087       storeNewCharPtr( &structuring->flatTextPrefix,
1088                        GPGMEPLUG_ENC_FLAT_PREFIX );
1089       storeNewCharPtr( &structuring->flatTextSeparator,
1090                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1091       storeNewCharPtr( &structuring->flatTextPostfix,
1092                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1093     }
1094   }
1095   return bOk;
1096 }
1097
1098
1099 bool encryptAndSignMessage( const char* cleartext,
1100                             const char** ciphertext,
1101                             const char* certificate,
1102                             struct StructuringInfo* structuring )
1103 {
1104   bool bOk;
1105
1106   init_StructuringInfo( structuring );
1107
1108   bOk = false;
1109
1110   // implementation of this function is still missing
1111
1112   if( bOk && structuring ) {
1113     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1114     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1115     if( structuring->makeMimeObject ) {
1116       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1117       storeNewCharPtr( &structuring->contentTypeMain,
1118                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1119       storeNewCharPtr( &structuring->contentDispMain,
1120                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1121       storeNewCharPtr( &structuring->contentTEncMain,
1122                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1123       if( structuring->makeMultiMime ) {
1124         storeNewCharPtr( &structuring->contentTypeVersion,
1125                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1126         storeNewCharPtr( &structuring->contentDispVersion,
1127                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1128         storeNewCharPtr( &structuring->contentTEncVersion,
1129                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1130         storeNewCharPtr( &structuring->bodyTextVersion,
1131                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1132         storeNewCharPtr( &structuring->contentTypeCode,
1133                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1134         storeNewCharPtr( &structuring->contentDispCode,
1135                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1136         storeNewCharPtr( &structuring->contentTEncCode,
1137                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1138       }
1139     } else {
1140       storeNewCharPtr( &structuring->flatTextPrefix,
1141                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1142       storeNewCharPtr( &structuring->flatTextSeparator,
1143                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1144       storeNewCharPtr( &structuring->flatTextPostfix,
1145                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1146     }
1147   }
1148   return bOk;
1149 }
1150
1151 bool decryptMessage( const char* ciphertext,
1152                      const char** cleartext,
1153                      const char* certificate )
1154 {
1155   GpgmeCtx ctx;
1156   GpgmeError err;
1157   GpgmeData gCiphertext, gPlaintext;
1158   size_t rCLen = 0;
1159   char*  rCiph = 0;
1160   bool bOk = false;
1161
1162   if( !ciphertext )
1163     return false;
1164
1165   err = gpgme_new (&ctx);
1166   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1167
1168   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1169                            1+strlen( ciphertext ), 1 );
1170   gpgme_data_new( &gPlaintext );
1171
1172   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1173   gpgme_data_release( gCiphertext );
1174
1175   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1176
1177   *cleartext = malloc( rCLen + 1 );
1178   if( *cleartext ) {
1179       if( rCLen ) {
1180           bOk = true;
1181           strncpy((char*)*cleartext, rCiph, rCLen );
1182       }
1183       ((char*)(*cleartext))[rCLen] = 0;
1184   }
1185
1186   free( rCiph );
1187   gpgme_release( ctx );
1188   return bOk;
1189 }
1190
1191 bool decryptAndCheckMessage( const char* ciphertext,
1192           const char** cleartext, const char* certificate,
1193           struct SignatureMetaData* sigmeta ){ return true; }
1194
1195
1196 const char* requestCertificateDialog(){ return 0; }
1197
1198 bool requestDecentralCertificate( const char* name, const char*
1199           email, const char* organization, const char* department,
1200           const char* ca_address ){ return true; }
1201
1202 bool requestCentralCertificateAndPSE( const char* name,
1203           const char* email, const char* organization, const char* department,
1204           const char* ca_address ){ return true; }
1205
1206 bool createPSE(){ return true; }
1207
1208 bool registerCertificate( const char* certificate ){ return true; }
1209
1210 bool requestCertificateProlongation( const char* certificate,
1211                                      const char* ca_address ){ return true; }
1212
1213 const char* certificateChain(){ return 0; }
1214
1215 bool deleteCertificate( const char* certificate ){ return true; }
1216
1217 bool archiveCertificate( const char* certificate ){ return true; }
1218
1219
1220 const char* displayCRL(){ return 0; }
1221
1222 void updateCRL(){}