Removed temporary passphrase callback
[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   gpgme_data_new_from_mem (&data, cleartext,
777                             1+strlen( cleartext ), 1 );
778   gpgme_data_new ( &sig );
779   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
780
781   if (!err) {
782     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
783     *ciphertext = malloc( rSLen + 1 );
784     if( *ciphertext ) {
785       if( rSLen ) {
786         bOk = true;
787         strncpy((char*)*ciphertext, rSig, rSLen );
788       }
789       ((char*)(*ciphertext))[rSLen] = '\0';
790     }
791     free( rSig );
792   }
793   else {
794     gpgme_data_release( sig );
795     *ciphertext = 0;
796     // hier fehlt eine Fehlerbehandlung, falls das
797     // Signieren schiefging
798   }
799   gpgme_data_release( data );
800   gpgme_release (ctx);
801
802   if( bOk && structuring ) {
803     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
804     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
805     if( structuring->makeMimeObject ) {
806       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
807       storeNewCharPtr( &structuring->contentTypeMain,
808                        GPGMEPLUG_SIGN_CTYPE_MAIN );
809       storeNewCharPtr( &structuring->contentDispMain,
810                        GPGMEPLUG_SIGN_CDISP_MAIN );
811       storeNewCharPtr( &structuring->contentTEncMain,
812                        GPGMEPLUG_SIGN_CTENC_MAIN );
813       if( structuring->makeMultiMime ) {
814         storeNewCharPtr( &structuring->contentTypeVersion,
815                          GPGMEPLUG_SIGN_CTYPE_VERSION );
816         storeNewCharPtr( &structuring->contentDispVersion,
817                          GPGMEPLUG_SIGN_CDISP_VERSION );
818         storeNewCharPtr( &structuring->contentTEncVersion,
819                          GPGMEPLUG_SIGN_CTENC_VERSION );
820         storeNewCharPtr( &structuring->bodyTextVersion,
821                          GPGMEPLUG_SIGN_BTEXT_VERSION );
822         storeNewCharPtr( &structuring->contentTypeCode,
823                          GPGMEPLUG_SIGN_CTYPE_CODE );
824         storeNewCharPtr( &structuring->contentDispCode,
825                          GPGMEPLUG_SIGN_CDISP_CODE );
826         storeNewCharPtr( &structuring->contentTEncCode,
827                          GPGMEPLUG_SIGN_CTENC_CODE );
828       }
829     } else {
830       storeNewCharPtr( &structuring->flatTextPrefix,
831                        GPGMEPLUG_SIGN_FLAT_PREFIX );
832       storeNewCharPtr( &structuring->flatTextSeparator,
833                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
834       storeNewCharPtr( &structuring->flatTextPostfix,
835                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
836     }
837   }
838   return bOk;
839 }
840
841
842 static const char*
843 sig_status_to_string( GpgmeSigStat status )
844 {
845   const char *result;
846
847   switch (status) {
848     case GPGME_SIG_STAT_NONE:
849       result = "Oops: Signature not verified";
850       break;
851     case GPGME_SIG_STAT_NOSIG:
852       result = "No signature found";
853       break;
854     case GPGME_SIG_STAT_GOOD:
855       result = "Good signature";
856       break;
857     case GPGME_SIG_STAT_BAD:
858       result = "BAD signature";
859       break;
860     case GPGME_SIG_STAT_NOKEY:
861       result = "No public key to verify the signature";
862       break;
863     case GPGME_SIG_STAT_ERROR:
864       result = "Error verifying the signature";
865       break;
866     case GPGME_SIG_STAT_DIFF:
867       result = "Different results for signatures";
868       break;
869     default:
870       result = "Error: Unknown status";
871       break;
872   }
873
874   return result;
875 }
876
877
878 bool checkMessageSignature( const char* ciphertext,
879                             const char* signaturetext,
880                             struct SignatureMetaData* sigmeta )
881 {
882   GpgmeCtx ctx;
883   GpgmeSigStat status;
884   GpgmeData datapart, sigpart;
885   GpgmeError err;
886   GpgmeKey key;
887   time_t created;
888   int sig_idx = 0;
889   const char* statusStr;
890   const char* fpr;
891
892   gpgme_new( &ctx );
893   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
894   gpgme_data_new_from_mem( &datapart, ciphertext,
895                           1+strlen( ciphertext ), 1 );
896   gpgme_data_new_from_mem( &sigpart, signaturetext,
897                           1+strlen( signaturetext ), 1 );
898
899   gpgme_op_verify( ctx, sigpart, datapart, &status );
900   gpgme_data_release( datapart );
901   gpgme_data_release( sigpart );
902
903   /* Provide information in the sigmeta struct */
904   /* the status string */
905   statusStr = sig_status_to_string( status );
906   sigmeta->status = malloc( strlen( statusStr ) + 1 );
907   if( sigmeta->status ) {
908     strcpy( sigmeta->status, statusStr );
909     sigmeta->status[strlen( statusStr )] = '\0';
910   } else
911     ; // nothing to do, is already 0
912
913   // Extended information for any number of signatures.
914   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
915   sigmeta->extended_info = 0;
916   while( fpr != NULL ) {
917     struct tm* ctime_val;
918     const char* sig_status;
919
920     void* realloc_return = realloc( sigmeta->extended_info,
921                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
922     if( realloc_return ) {
923       sigmeta->extended_info = realloc_return;
924       // the creation time
925       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
926       if( sigmeta->extended_info[sig_idx].creation_time ) {
927         ctime_val = localtime( &created );
928         memcpy( sigmeta->extended_info[sig_idx].creation_time,
929                 ctime_val, sizeof( struct tm ) );
930       }
931
932       err = gpgme_get_sig_key (ctx, sig_idx, &key);
933       sig_status = sig_status_to_string( status );
934       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
935       if( sigmeta->extended_info[sig_idx].status_text ) {
936         strcpy( sigmeta->extended_info[sig_idx].status_text,
937                 sig_status );
938         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
939       }
940
941       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
942       if( sigmeta->extended_info[sig_idx].fingerprint ) {
943         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
944         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
945       }
946     } else
947       break; // if allocation fails once, it isn't likely to
948               // succeed the next time either
949
950     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
951   }
952   sigmeta->extended_info_count = sig_idx;
953   sigmeta->nota_xml = gpgme_get_notation( ctx );
954   sigmeta->status_code = status;
955
956   gpgme_release( ctx );
957   return ( status == GPGME_SIG_STAT_GOOD );
958 }
959
960 bool storeCertificatesFromMessage(
961         const char* ciphertext ){ return true; }
962
963
964 bool encryptMessage( const char* cleartext,
965                      const char** ciphertext,
966                      const char* addressee,
967                      struct StructuringInfo* structuring )
968 {
969   GpgmeCtx ctx;
970   GpgmeError err;
971   GpgmeData gCiphertext, gPlaintext;
972   GpgmeRecipients rset;
973   size_t rCLen = 0;
974   char*  rCiph = 0;
975   bool   bOk   = false;
976
977   init_StructuringInfo( structuring );
978
979   gpgme_new (&ctx);
980   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
981
982   gpgme_set_armor (ctx, 1);
983   gpgme_set_textmode (ctx, 1);
984
985   gpgme_data_new_from_mem (&gPlaintext, cleartext,
986                             1+strlen( cleartext ), 1 );
987   err = gpgme_data_new ( &gCiphertext );
988
989   gpgme_recipients_new (&rset);
990
991
992   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
993   {
994     gpgme_recipients_add_name_with_validity (rset,
995       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
996       GPGME_VALIDITY_FULL );
997     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
998   }
999   else
1000   {
1001     gpgme_recipients_add_name (rset, addressee);
1002     fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", addressee );
1003   }
1004
1005
1006   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1007   if( err )
1008     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1009
1010   gpgme_recipients_release (rset);
1011   gpgme_data_release (gPlaintext);
1012
1013   if( !err ) {
1014     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1015     *ciphertext = malloc( rCLen + 1 );
1016     if( *ciphertext ) {
1017       if( rCLen ) {
1018         bOk = true;
1019         strncpy((char*)*ciphertext, rCiph, rCLen );
1020       }
1021       ((char*)(*ciphertext))[rCLen] = 0;
1022     }
1023     free( rCiph );
1024   }
1025   else {
1026     gpgme_data_release ( gCiphertext );
1027     *ciphertext = 0;
1028     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1029     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1030     // das signieren.
1031   }
1032
1033   gpgme_release (ctx);
1034
1035   fflush( stderr );
1036
1037   if( bOk && structuring ) {
1038     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1039     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1040     if( structuring->makeMimeObject ) {
1041       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1042       storeNewCharPtr( &structuring->contentTypeMain,
1043                        GPGMEPLUG_ENC_CTYPE_MAIN );
1044       storeNewCharPtr( &structuring->contentDispMain,
1045                        GPGMEPLUG_ENC_CDISP_MAIN );
1046       storeNewCharPtr( &structuring->contentTEncMain,
1047                        GPGMEPLUG_ENC_CTENC_MAIN );
1048       if( structuring->makeMultiMime ) {
1049         storeNewCharPtr( &structuring->contentTypeVersion,
1050                          GPGMEPLUG_ENC_CTYPE_VERSION );
1051         storeNewCharPtr( &structuring->contentDispVersion,
1052                          GPGMEPLUG_ENC_CDISP_VERSION );
1053         storeNewCharPtr( &structuring->contentTEncVersion,
1054                          GPGMEPLUG_ENC_CTENC_VERSION );
1055         storeNewCharPtr( &structuring->bodyTextVersion,
1056                          GPGMEPLUG_ENC_BTEXT_VERSION );
1057         storeNewCharPtr( &structuring->contentTypeCode,
1058                          GPGMEPLUG_ENC_CTYPE_CODE );
1059         storeNewCharPtr( &structuring->contentDispCode,
1060                          GPGMEPLUG_ENC_CDISP_CODE );
1061         storeNewCharPtr( &structuring->contentTEncCode,
1062                          GPGMEPLUG_ENC_CTENC_CODE );
1063       }
1064     } else {
1065       storeNewCharPtr( &structuring->flatTextPrefix,
1066                        GPGMEPLUG_ENC_FLAT_PREFIX );
1067       storeNewCharPtr( &structuring->flatTextSeparator,
1068                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1069       storeNewCharPtr( &structuring->flatTextPostfix,
1070                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1071     }
1072   }
1073   return bOk;
1074 }
1075
1076
1077 bool encryptAndSignMessage( const char* cleartext,
1078                             const char** ciphertext,
1079                             const char* certificate,
1080                             struct StructuringInfo* structuring )
1081 {
1082   bool bOk;
1083
1084   init_StructuringInfo( structuring );
1085
1086   bOk = false;
1087
1088   // implementation of this function is still missing
1089
1090   if( bOk && structuring ) {
1091     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1092     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1093     if( structuring->makeMimeObject ) {
1094       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1095       storeNewCharPtr( &structuring->contentTypeMain,
1096                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1097       storeNewCharPtr( &structuring->contentDispMain,
1098                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1099       storeNewCharPtr( &structuring->contentTEncMain,
1100                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1101       if( structuring->makeMultiMime ) {
1102         storeNewCharPtr( &structuring->contentTypeVersion,
1103                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1104         storeNewCharPtr( &structuring->contentDispVersion,
1105                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1106         storeNewCharPtr( &structuring->contentTEncVersion,
1107                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1108         storeNewCharPtr( &structuring->bodyTextVersion,
1109                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1110         storeNewCharPtr( &structuring->contentTypeCode,
1111                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1112         storeNewCharPtr( &structuring->contentDispCode,
1113                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1114         storeNewCharPtr( &structuring->contentTEncCode,
1115                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1116       }
1117     } else {
1118       storeNewCharPtr( &structuring->flatTextPrefix,
1119                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1120       storeNewCharPtr( &structuring->flatTextSeparator,
1121                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1122       storeNewCharPtr( &structuring->flatTextPostfix,
1123                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1124     }
1125   }
1126   return bOk;
1127 }
1128
1129 bool decryptMessage( const char* ciphertext,
1130                      const char** cleartext,
1131                      const char* certificate )
1132 {
1133   GpgmeCtx ctx;
1134   GpgmeError err;
1135   GpgmeData gCiphertext, gPlaintext;
1136   size_t rCLen = 0;
1137   char*  rCiph = 0;
1138   bool bOk = false;
1139
1140   if( !ciphertext )
1141     return false;
1142
1143   err = gpgme_new (&ctx);
1144   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1145
1146   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1147                            1+strlen( ciphertext ), 1 );
1148   gpgme_data_new( &gPlaintext );
1149
1150   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1151   gpgme_data_release( gCiphertext );
1152
1153   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1154
1155   *cleartext = malloc( rCLen + 1 );
1156   if( *cleartext ) {
1157       if( rCLen ) {
1158           bOk = true;
1159           strncpy((char*)*cleartext, rCiph, rCLen );
1160       }
1161       ((char*)(*cleartext))[rCLen] = 0;
1162   }
1163
1164   free( rCiph );
1165   gpgme_release( ctx );
1166   return bOk;
1167 }
1168
1169 bool decryptAndCheckMessage( const char* ciphertext,
1170           const char** cleartext, const char* certificate,
1171           struct SignatureMetaData* sigmeta ){ return true; }
1172
1173
1174 const char* requestCertificateDialog(){ return 0; }
1175
1176 bool requestDecentralCertificate( const char* name, const char*
1177           email, const char* organization, const char* department,
1178           const char* ca_address ){ return true; }
1179
1180 bool requestCentralCertificateAndPSE( const char* name,
1181           const char* email, const char* organization, const char* department,
1182           const char* ca_address ){ return true; }
1183
1184 bool createPSE(){ return true; }
1185
1186 bool registerCertificate( const char* certificate ){ return true; }
1187
1188 bool requestCertificateProlongation( const char* certificate,
1189                                      const char* ca_address ){ return true; }
1190
1191 const char* certificateChain(){ return 0; }
1192
1193 bool deleteCertificate( const char* certificate ){ return true; }
1194
1195 bool archiveCertificate( const char* certificate ){ return true; }
1196
1197
1198 const char* displayCRL(){ return 0; }
1199
1200 void updateCRL(){}