Bugfix: forgot to initialize the list of certificates in findCertificates() before...
[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 #include <ctype.h>
54
55 #ifndef BUG_URL
56 #define BUG_URL "http:://www.gnupg.org/aegypten/"
57 #endif
58
59 #include "gpgme.h"
60 #ifndef GPGMEPLUG_PROTOCOL
61 #define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
62 #endif
63
64 // definitions for signing
65 #ifndef GPGMEPLUG_SIGN_MAKE_MIME_OBJECT
66 #define GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT true
67 #define GPGMEPLUG_SIGN_MAKE_MIME_OBJECT  true
68 #define GPGMEPLUG_SIGN_MAKE_MULTI_MIME   true
69 #define GPGMEPLUG_SIGN_CTYPE_MAIN        "multipart/signed;protocol=application/pgp-signature;micalg=pgp-sha1"
70 #define GPGMEPLUG_SIGN_CDISP_MAIN        ""
71 #define GPGMEPLUG_SIGN_CTENC_MAIN        ""
72 #define GPGMEPLUG_SIGN_CTYPE_VERSION     ""
73 #define GPGMEPLUG_SIGN_CDISP_VERSION     ""
74 #define GPGMEPLUG_SIGN_CTENC_VERSION     ""
75 #define GPGMEPLUG_SIGN_BTEXT_VERSION     ""
76 #define GPGMEPLUG_SIGN_CTYPE_CODE        "application/pgp-signature"
77 #define GPGMEPLUG_SIGN_CDISP_CODE        ""
78 #define GPGMEPLUG_SIGN_CTENC_CODE        ""
79 #define GPGMEPLUG_SIGN_FLAT_PREFIX       ""
80 #define GPGMEPLUG_SIGN_FLAT_SEPARATOR    ""
81 #define GPGMEPLUG_SIGN_FLAT_POSTFIX      ""
82 #endif
83 // definitions for encoding
84 #ifndef GPGMEPLUG_ENC_MAKE_MIME_OBJECT
85 #define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT  false
86 #define GPGMEPLUG_ENC_MAKE_MIME_OBJECT   true
87 #define GPGMEPLUG_ENC_MAKE_MULTI_MIME    true
88 #define GPGMEPLUG_ENC_CTYPE_MAIN         "multipart/encrypted; protocol=application/pgp-encrypted"
89 #define GPGMEPLUG_ENC_CDISP_MAIN         ""
90 #define GPGMEPLUG_ENC_CTENC_MAIN         ""
91 #define GPGMEPLUG_ENC_CTYPE_VERSION      "application/pgp-encrypted"
92 #define GPGMEPLUG_ENC_CDISP_VERSION      "attachment"
93 #define GPGMEPLUG_ENC_CTENC_VERSION      ""
94 #define GPGMEPLUG_ENC_BTEXT_VERSION      "Version: 1"
95 #define GPGMEPLUG_ENC_CTYPE_CODE         "application/octet-stream"
96 #define GPGMEPLUG_ENC_CDISP_CODE         "inline; filename=\"msg.asc\""
97 #define GPGMEPLUG_ENC_CTENC_CODE         ""
98 #define GPGMEPLUG_ENC_FLAT_PREFIX        ""
99 #define GPGMEPLUG_ENC_FLAT_SEPARATOR     ""
100 #define GPGMEPLUG_ENC_FLAT_POSTFIX       ""
101 #endif
102 // Note: The following specification will result in
103 //       function encryptAndSignMessage() producing
104 //       _empty_ mails.
105 //       This must be changed as soon as our plugin
106 //       is supporting the encryptAndSignMessage() function.
107 #ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
108 #define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
109 #define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT  false
110 #define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME   false
111 #define GPGMEPLUG_ENCSIGN_CTYPE_MAIN        ""
112 #define GPGMEPLUG_ENCSIGN_CDISP_MAIN        ""
113 #define GPGMEPLUG_ENCSIGN_CTENC_MAIN        ""
114 #define GPGMEPLUG_ENCSIGN_CTYPE_VERSION     ""
115 #define GPGMEPLUG_ENCSIGN_CDISP_VERSION     ""
116 #define GPGMEPLUG_ENCSIGN_CTENC_VERSION     ""
117 #define GPGMEPLUG_ENCSIGN_BTEXT_VERSION     ""
118 #define GPGMEPLUG_ENCSIGN_CTYPE_CODE        ""
119 #define GPGMEPLUG_ENCSIGN_CDISP_CODE        ""
120 #define GPGMEPLUG_ENCSIGN_CTENC_CODE        ""
121 #define GPGMEPLUG_ENCSIGN_FLAT_PREFIX       ""
122 #define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR    ""
123 #define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX      ""
124 #endif
125
126 #include "cryptplug.h"
127
128
129 typedef struct {
130   const char*             bugURL;
131   const char*             signatureKeyCertificate;
132   SignatureAlgorithm      signatureAlgorithm;
133   SendCertificates        sendCertificates;
134   SignEmail               signEmail;
135   bool                    saveSentSignatures;
136   bool                    warnNoCertificate;
137   PinRequests             numPINRequests;
138   bool                    checkSignatureCertificatePathToRoot;
139   bool                    signatureUseCRLs;
140   EncryptionAlgorithm     encryptionAlgorithm;
141   EncryptEmail            encryptEmail;
142   bool                    saveMessagesEncrypted;
143   bool                    checkEncryptionCertificatePathToRoot;
144   bool                    encryptionUseCRLs;
145   bool                    encryptionCRLExpiryNearWarning;
146   int                     encryptionCRLNearExpiryInterval;
147   struct DirectoryServer *directoryServers;
148   unsigned int            numDirectoryServers;
149   CertificateSource       certificateSource;
150   CertificateSource       cRLSource;
151   bool                    warnSendUnsigned;
152   int                     numPINRequestsInterval;
153   bool                    signatureCertificateExpiryNearWarning;
154   int                     signatureCertificateExpiryNearInterval;
155   bool                    cACertificateExpiryNearWarning;
156   int                     cACertificateExpiryNearInterval;
157   bool                    rootCertificateExpiryNearWarning;
158   int                     rootCertificateExpiryNearInterval;
159   bool                    warnSendUnencrypted;
160   bool                    checkCertificatePath;
161   bool                    receiverCertificateExpiryNearWarning;
162   int                     receiverCertificateExpiryNearWarningInterval;
163   bool                    certificateInChainExpiryNearWarning;
164   int                     certificateInChainExpiryNearWarningInterval;
165   bool                    receiverEmailAddressNotInCertificateWarning;
166 } Config;
167
168
169 Config config;
170
171 #define NEAR_EXPIRY 14
172
173 bool initialize()
174 {
175   config.bugURL                               = malloc( strlen( BUG_URL ) + 1 );
176   strcpy( (char* )config.bugURL,                BUG_URL );
177   config.signatureKeyCertificate              = malloc( 1 );
178   strcpy( (char* )config.signatureKeyCertificate, "" );
179   config.signatureAlgorithm                   = SignAlg_SHA1;
180   config.sendCertificates                     = SendCert_SendChainWithRoot;
181   config.signEmail                            = SignEmail_SignAll;
182   config.saveSentSignatures                   = true;
183   config.warnNoCertificate                    = true;
184   config.numPINRequests                       = PinRequest_Always;
185   config.checkSignatureCertificatePathToRoot  = true;
186   config.signatureUseCRLs                     = true;
187   config.encryptionAlgorithm                  = EncryptAlg_RSA;
188   config.encryptEmail                         = EncryptEmail_Ask;
189   config.saveMessagesEncrypted                = true;
190   config.checkEncryptionCertificatePathToRoot = true;
191   config.encryptionUseCRLs                    = true;
192   config.encryptionCRLExpiryNearWarning       = true;
193   config.encryptionCRLNearExpiryInterval      = NEAR_EXPIRY;
194   config.directoryServers                     = NULL;
195   config.numDirectoryServers                  = 0;
196   config.certificateSource                    = CertSrc_Server;
197   config.cRLSource                            = CertSrc_Server;
198   config.warnSendUnsigned                             = true;
199   config.numPINRequestsInterval                       = NEAR_EXPIRY;
200   config.signatureCertificateExpiryNearWarning        = true;
201   config.signatureCertificateExpiryNearInterval       = NEAR_EXPIRY;
202   config.cACertificateExpiryNearWarning               = true;
203   config.cACertificateExpiryNearInterval              = NEAR_EXPIRY;
204   config.rootCertificateExpiryNearWarning             = true;
205   config.rootCertificateExpiryNearInterval            = NEAR_EXPIRY;
206   config.warnSendUnencrypted                          = false;
207   config.checkCertificatePath                         = true;
208   config.receiverCertificateExpiryNearWarning         = true;
209   config.receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY;
210   config.certificateInChainExpiryNearWarning          = true;
211   config.certificateInChainExpiryNearWarningInterval  = NEAR_EXPIRY;
212   config.receiverEmailAddressNotInCertificateWarning  = true;
213
214   return true;
215 };
216
217
218 void deinitialize()
219 {
220   unsigned int i;
221   for( i = 0; i < config.numDirectoryServers; ++i ) {
222     free( (char *)config.directoryServers[i].servername );
223     free( (char *)config.directoryServers[i].description );
224   }
225   free( config.directoryServers );
226 }
227
228
229 bool hasFeature( Feature flag )
230 {
231   switch ( flag ) {
232     case CryptPlugFeat_SignMessages:              return true;
233     case CryptPlugFeat_VerifySignatures:          return true;
234     case CryptPlugFeat_EncryptMessages:           return true;
235     case CryptPlugFeat_DecryptMessages:           return true;
236     // undefined or not yet implemented:
237     case CryptPlugFeat_undef:                     return false;
238     default:                                      return false;
239   }
240 }
241
242
243 const char* bugURL(){ return config.bugURL; }
244
245
246 void unsafeStationery( void** pixmap, const char** menutext, char* accel,
247           const char** tooltip, const char** statusbartext ){}
248
249 void signedStationery( void** pixmap, const char** menutext, char* accel,
250           const char** tooltip, const char** statusbartext ){}
251
252 void encryptedStationery( void** pixmap, const char**
253           menutext, char* accel,
254           const char** tooltip, const char** statusbartext ){}
255
256 void signedEncryptedStationery( void** pixmap, const char**
257           menutext, char* accel,
258           const char** tooltip, const char** statusbartext ){}
259
260 const char* signatureConfigurationDialog(){ return 0; }
261
262 const char* signatureKeySelectionDialog(){ return 0; }
263
264 const char* signatureAlgorithmDialog(){ return 0; }
265
266 const char* signatureHandlingDialog(){ return 0; }
267
268 void setSignatureKeyCertificate( const char* certificate )
269 {
270   config.signatureKeyCertificate = certificate;
271 }
272
273 const char* signatureKeyCertificate()
274 {
275   return config.signatureKeyCertificate;
276 }
277
278 void setSignatureAlgorithm( SignatureAlgorithm sigAlg )
279 {
280   config.signatureAlgorithm = sigAlg;
281 }
282
283 SignatureAlgorithm signatureAlgorithm()
284 {
285   return config.signatureAlgorithm;
286 }
287
288 void setSendCertificates( SendCertificates sendCert )
289 {
290   config.sendCertificates = sendCert;
291 }
292
293 SendCertificates sendCertificates()
294 {
295   return config.sendCertificates;
296 }
297
298 void setSignEmail( SignEmail signMail )
299 {
300   config.signEmail = signMail;
301 }
302
303 SignEmail signEmail()
304 {
305   return config.signEmail;
306 }
307
308
309
310
311
312 void setWarnSendUnsigned( bool flag )
313 {
314   config.warnSendUnsigned = flag;
315 }
316
317 bool warnSendUnsigned()
318 {
319   return config.warnSendUnsigned;
320 }
321
322
323
324
325
326
327 void setSaveSentSignatures( bool flag )
328 {
329   config.saveSentSignatures = flag;
330 }
331
332 bool saveSentSignatures()
333 {
334   return config.saveSentSignatures;
335 }
336
337 void setWarnNoCertificate( bool flag )
338 {
339   config.warnNoCertificate = flag;
340 }
341
342 bool warnNoCertificate()
343 {
344   return config.warnNoCertificate;
345 }
346
347
348 bool isEmailInCertificate( const char* email, const char* certificate )
349 {
350     /* PENDING(g10) this function should return true if the email
351        address passed as the first parameter is contained in the
352        certificate passed as the second parameter, and false
353        otherwise. This is used to alert the user if his own email
354        address is not contained in the certificate he uses for
355        signing.
356        Note that the parameter email can be anything that is allowed
357        in a From: line.
358        Another note: OK, OK, we'll handle that in the MUA. You can
359        assume that you only get the email address.
360     */
361     return false; // dummy
362 }
363
364
365 void setNumPINRequests( PinRequests reqMode )
366 {
367   config.numPINRequests = reqMode;
368
369   /* PENDING(g10) Put this value into gpg and make it ask for the pin
370      according to this. Note that there is also
371      setNumPINRequestsInterval() which is only used if reqMode ==
372      PinRequest_AfterMinutes.
373   */
374 }
375
376 PinRequests numPINRequests()
377 {
378   return config.numPINRequests;
379 }
380
381
382
383 void setNumPINRequestsInterval( int interval )
384 {
385   config.numPINRequestsInterval = interval;
386
387   /* PENDING(g10) Put this value into gpg and make it ask for the pin
388      according to this. Note that this should only be used if
389      config.numPINRequests (set with setNumPINRequests()) has the
390      value PinRequest_AfterMinutes.
391   */
392 }
393
394 int numPINRequestsInterval()
395 {
396   return config.numPINRequestsInterval;
397 }
398
399
400
401 void setCheckSignatureCertificatePathToRoot( bool flag )
402 {
403   config.checkSignatureCertificatePathToRoot = flag;
404 }
405
406 bool checkSignatureCertificatePathToRoot()
407 {
408   return config.checkSignatureCertificatePathToRoot;
409 }
410
411 void setSignatureUseCRLs( bool flag )
412 {
413   config.signatureUseCRLs = flag;
414 }
415
416 bool signatureUseCRLs()
417 {
418   return config.signatureUseCRLs;
419 }
420
421
422
423
424
425
426 void setSignatureCertificateExpiryNearWarning( bool flag )
427 {
428   config.signatureCertificateExpiryNearWarning = flag;
429 }
430
431 bool signatureCertificateExpiryNearWarning( void )
432 {
433   return config.signatureCertificateExpiryNearWarning;
434 }
435
436
437 int signatureCertificateDaysLeftToExpiry( const char* certificate )
438 {
439     /* PENDING(g10)
440        Please return the number of days that are left until the
441        certificate specified in the parameter certificate expires.
442     */
443     return 10; // dummy that triggers a warning in the MUA
444 }
445
446
447 void setSignatureCertificateExpiryNearInterval( int interval )
448 {
449   config.signatureCertificateExpiryNearInterval = interval;
450 }
451
452 int signatureCertificateExpiryNearInterval( void )
453 {
454   return config.signatureCertificateExpiryNearInterval;
455 }
456
457 void setCACertificateExpiryNearWarning( bool flag )
458 {
459   config.cACertificateExpiryNearWarning = flag;
460 }
461
462 bool caCertificateExpiryNearWarning( void )
463 {
464   return config.cACertificateExpiryNearWarning;
465 }
466
467 int caCertificateDaysLeftToExpiry( const char* certificate )
468 {
469     /* PENDING(g10)
470        Please return the number of days that are left until the
471        CA certificate for the certificate specified in the parameter
472        certificate expires.
473     */
474     return 10; // dummy that triggers a warning in the MUA
475 }
476
477 void setCACertificateExpiryNearInterval( int interval )
478 {
479   config.cACertificateExpiryNearInterval = interval;
480 }
481
482 int caCertificateExpiryNearInterval( void )
483 {
484   return config.cACertificateExpiryNearInterval;
485 }
486
487 void setRootCertificateExpiryNearWarning( bool flag )
488 {
489   config.rootCertificateExpiryNearWarning = flag;
490 }
491
492 bool rootCertificateExpiryNearWarning( void )
493 {
494   return config.rootCertificateExpiryNearWarning;
495 }
496
497 int rootCertificateDaysLeftToExpiry( const char* certificate )
498 {
499     /* PENDING(g10)
500        Please return the number of days that are left until the
501        root certificate for the certificate specified in the parameter
502        certificate expires.
503     */
504     return 10; // dummy that triggers a warning in the MUA
505 }
506
507
508 void setRootCertificateExpiryNearInterval( int interval )
509 {
510   config.rootCertificateExpiryNearInterval = interval;
511 }
512
513 int rootCertificateExpiryNearInterval( void )
514 {
515   return config.rootCertificateExpiryNearInterval;
516 }
517
518
519
520
521
522
523
524
525 const char* encryptionConfigurationDialog(){ return 0; }
526
527 const char* encryptionAlgorithmDialog(){ return 0; }
528
529 const char* encryptionHandlingDialog(){ return 0; }
530
531 const char* encryptionReceiverDialog(){ return 0; }
532
533 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
534 {
535   config.encryptionAlgorithm = cryptAlg;
536 }
537
538 EncryptionAlgorithm encryptionAlgorithm()
539 {
540   return config.encryptionAlgorithm;
541 }
542
543 void setEncryptEmail( EncryptEmail cryptMode )
544 {
545   config.encryptEmail = cryptMode;
546 }
547
548 EncryptEmail encryptEmail()
549 {
550   return config.encryptEmail;
551 }
552
553
554
555
556
557
558 void setWarnSendUnencrypted( bool flag )
559 {
560   config.warnSendUnencrypted = flag;
561 }
562
563 bool warnSendUnencrypted()
564 {
565   return config.warnSendUnencrypted;
566 }
567
568
569
570
571
572
573
574
575
576 void setSaveMessagesEncrypted( bool flag )
577 {
578   config.saveMessagesEncrypted = flag;
579 }
580
581 bool saveMessagesEncrypted()
582 {
583   return config.saveMessagesEncrypted;
584 }
585
586
587
588
589
590
591
592 void setCheckCertificatePath( bool flag )
593 {
594   config.checkCertificatePath = flag;
595 }
596
597 bool checkCertificatePath()
598 {
599   return config.checkCertificatePath;
600 }
601
602
603
604
605
606
607
608
609 void setCheckEncryptionCertificatePathToRoot( bool flag )
610 {
611   config.checkEncryptionCertificatePathToRoot = flag;
612 }
613
614 bool checkEncryptionCertificatePathToRoot()
615 {
616   return config.checkEncryptionCertificatePathToRoot;
617 }
618
619
620
621
622
623
624
625 void setReceiverCertificateExpiryNearWarning( bool flag )
626 {
627   config.receiverCertificateExpiryNearWarning = flag;
628 }
629
630 bool receiverCertificateExpiryNearWarning()
631 {
632   return config.receiverCertificateExpiryNearWarning;
633 }
634
635
636 int receiverCertificateDaysLeftToExpiry( const char* certificate )
637 {
638     /* PENDING(g10)
639        Please return the number of days that are left until the
640        certificate specified in the parameter certificate expires.
641     */
642     return 10; // dummy that triggers a warning in the MUA
643 }
644
645
646 void setReceiverCertificateExpiryNearWarningInterval( int interval )
647 {
648   config.receiverCertificateExpiryNearWarningInterval = interval;
649 }
650
651 int receiverCertificateExpiryNearWarningInterval()
652 {
653   return config.receiverCertificateExpiryNearWarningInterval;
654 }
655
656 void setCertificateInChainExpiryNearWarning( bool flag )
657 {
658   config.certificateInChainExpiryNearWarning = flag;
659 }
660
661 bool certificateInChainExpiryNearWarning()
662 {
663   return config.certificateInChainExpiryNearWarning;
664 }
665
666
667 int certificateInChainDaysLeftToExpiry( const char* certificate )
668 {
669     /* PENDING(g10)
670        Please return the number of days that are left until the
671        the first certificate in the chain of the specified certificate
672        expires.
673     */
674     return 10; // dummy that triggers a warning in the MUA
675 }
676
677
678 void setCertificateInChainExpiryNearWarningInterval( int interval )
679 {
680   config.certificateInChainExpiryNearWarningInterval = interval;
681 }
682
683 int certificateInChainExpiryNearWarningInterval()
684 {
685   return config.certificateInChainExpiryNearWarningInterval;
686 }
687
688 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
689 {
690   config.receiverEmailAddressNotInCertificateWarning = flag;
691 }
692
693 bool receiverEmailAddressNotInCertificateWarning()
694 {
695   return config.receiverEmailAddressNotInCertificateWarning;
696 }
697
698
699
700
701
702
703
704
705 void setEncryptionUseCRLs( bool flag )
706 {
707   config.encryptionUseCRLs = flag;
708
709   /* PENDING(g10) Store this setting in gpgme and use it. If true,
710      every certificate used for encryption should be checked against
711      applicable CRLs.
712   */
713 }
714
715 bool encryptionUseCRLs()
716 {
717   return config.encryptionUseCRLs;
718 }
719
720
721 int encryptionCRLsDaysLeftToExpiry()
722 {
723     /* PENDING(g10)
724        Please return the number of days that are left until the
725        CRL used for encryption expires.
726     */
727     return 10; // dummy that triggers a warning in the MUA
728 }
729
730 void setEncryptionCRLExpiryNearWarning( bool flag )
731 {
732   config.encryptionCRLExpiryNearWarning = flag;
733 }
734
735 bool encryptionCRLExpiryNearWarning()
736 {
737   return config.encryptionCRLExpiryNearWarning;
738 }
739
740 void setEncryptionCRLNearExpiryInterval( int interval )
741 {
742   config.encryptionCRLNearExpiryInterval = interval;
743 }
744
745 int encryptionCRLNearExpiryInterval()
746 {
747   return config.encryptionCRLNearExpiryInterval;
748 }
749
750
751 const char* directoryServiceConfigurationDialog(){ return 0; }
752
753 void appendDirectoryServer( const char* servername,
754                             int         port,
755                             const char* description )
756 {
757   struct DirectoryServer *newServers = NULL;
758   newServers = realloc( config.directoryServers,
759                         (1+config.numDirectoryServers) * sizeof *newServers );
760   if( newServers ) {
761     config.directoryServers = newServers;
762     newServers[ config.numDirectoryServers ].servername =
763       malloc( 1+strlen( servername ) );
764     if( newServers[ config.numDirectoryServers ].servername ) {
765       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
766         servername );
767       newServers[ config.numDirectoryServers ].description =
768         malloc( 1+strlen(  description ) );
769       if( newServers[ config.numDirectoryServers ].description ) {
770         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
771           description );
772         newServers[ config.numDirectoryServers ].port = port;
773         config.numDirectoryServers += 1;
774       }
775     }
776   }
777 }
778
779 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
780 {
781   unsigned int i;
782   int oldSize = config.numDirectoryServers;
783   struct DirectoryServer *newServers = NULL;
784   newServers = calloc ( size, sizeof *newServers );
785   if( newServers ) {
786     for( i=0; i < oldSize; ++i ) {
787       free( (char *)config.directoryServers[i].servername );
788       free( (char *)config.directoryServers[i].description );
789     }
790     free( config.directoryServers );
791     for( i=0; i < size; ++i ) {
792       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
793       if( newServers[ i ].servername ) {
794         strcpy( (char *)newServers[ i ].servername, server[i].servername );
795         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
796         if( newServers[ i ].description ) {
797           strcpy( (char *)newServers[ i ].description, server[i].description );
798           newServers[ i ].port = server[i].port;
799         }
800       }
801     }
802     config.directoryServers = newServers;
803     config.numDirectoryServers = size;
804   }
805 }
806
807 struct DirectoryServer * directoryServers( int* numServers )
808 {
809   if( numServers )
810     *numServers = config.numDirectoryServers;
811   return config.directoryServers;
812 };
813
814 void setCertificateSource( CertificateSource source )
815 {
816   config.certificateSource = source;
817 }
818
819 CertificateSource certificateSource()
820 {
821   return config.certificateSource;
822 }
823
824 void setCRLSource( CertificateSource source )
825 {
826   config.cRLSource = source;
827 }
828
829 CertificateSource crlSource()
830 {
831   return config.cRLSource;
832 }
833
834
835 bool certificateValidity( const char* certificate,
836                           int* level ){ return true; }
837
838
839 void storeNewCharPtr( char** dest, const char* src )
840 {
841   int sLen = strlen( src );
842   *dest = malloc( sLen + 1 );
843   strcpy( *dest, src );
844   (*dest)[sLen] = '\0';
845 }
846
847
848 bool signMessage( const char*  cleartext,
849                   const char** ciphertext,
850                   const char*  certificate,
851                   struct StructuringInfo* structuring )
852 {
853   GpgmeCtx ctx;
854   GpgmeError err;
855   GpgmeData data,  sig;
856   size_t rSLen = 0;
857   char*  rSig  = 0;
858   bool   bOk   = false;
859   int sendCerts = 1;
860
861   init_StructuringInfo( structuring );
862
863   if( !ciphertext )
864     return false;
865
866   err = gpgme_new (&ctx);
867   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
868
869   gpgme_set_armor (ctx, 1);
870   gpgme_set_textmode (ctx, 1);
871
872   switch ( config.sendCertificates ) {
873     case SendCert_undef:
874       break;
875     case SendCert_DontSend:
876       sendCerts = 0;
877       break;
878     case SendCert_SendOwn:
879       sendCerts = 1;
880       break;
881     case SendCert_SendChainWithoutRoot:
882       sendCerts = -2;
883       break;
884     case SendCert_SendChainWithRoot:
885       sendCerts = -1;
886       break;
887     default:
888       sendCerts = 0;
889       break;
890   }
891   gpgme_set_include_certs (ctx, sendCerts);
892
893   // PENDING(g10) Implement this
894   //gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm );
895
896   gpgme_data_new_from_mem (&data, cleartext,
897                             strlen( cleartext ), 1 );
898   gpgme_data_new ( &sig );
899   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
900
901   if (!err) {
902     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
903     *ciphertext = malloc( rSLen + 1 );
904     if( *ciphertext ) {
905       if( rSLen ) {
906         bOk = true;
907         strncpy((char*)*ciphertext, rSig, rSLen );
908       }
909       ((char*)(*ciphertext))[rSLen] = '\0';
910     }
911     free( rSig );
912   }
913   else {
914     gpgme_data_release( sig );
915     *ciphertext = 0;
916     // hier fehlt eine Fehlerbehandlung, falls das
917     // Signieren schiefging
918   }
919   gpgme_data_release( data );
920   gpgme_release (ctx);
921
922   if( bOk && structuring ) {
923     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
924     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
925     if( structuring->makeMimeObject ) {
926       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
927       storeNewCharPtr( &structuring->contentTypeMain,
928                        GPGMEPLUG_SIGN_CTYPE_MAIN );
929       storeNewCharPtr( &structuring->contentDispMain,
930                        GPGMEPLUG_SIGN_CDISP_MAIN );
931       storeNewCharPtr( &structuring->contentTEncMain,
932                        GPGMEPLUG_SIGN_CTENC_MAIN );
933       if( structuring->makeMultiMime ) {
934         storeNewCharPtr( &structuring->contentTypeVersion,
935                          GPGMEPLUG_SIGN_CTYPE_VERSION );
936         storeNewCharPtr( &structuring->contentDispVersion,
937                          GPGMEPLUG_SIGN_CDISP_VERSION );
938         storeNewCharPtr( &structuring->contentTEncVersion,
939                          GPGMEPLUG_SIGN_CTENC_VERSION );
940         storeNewCharPtr( &structuring->bodyTextVersion,
941                          GPGMEPLUG_SIGN_BTEXT_VERSION );
942         storeNewCharPtr( &structuring->contentTypeCode,
943                          GPGMEPLUG_SIGN_CTYPE_CODE );
944         storeNewCharPtr( &structuring->contentDispCode,
945                          GPGMEPLUG_SIGN_CDISP_CODE );
946         storeNewCharPtr( &structuring->contentTEncCode,
947                          GPGMEPLUG_SIGN_CTENC_CODE );
948       }
949     } else {
950       storeNewCharPtr( &structuring->flatTextPrefix,
951                        GPGMEPLUG_SIGN_FLAT_PREFIX );
952       storeNewCharPtr( &structuring->flatTextSeparator,
953                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
954       storeNewCharPtr( &structuring->flatTextPostfix,
955                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
956     }
957   }
958   return bOk;
959 }
960
961
962 static const char*
963 sig_status_to_string( GpgmeSigStat status )
964 {
965   const char *result;
966
967   switch (status) {
968     case GPGME_SIG_STAT_NONE:
969       result = "Oops: Signature not verified";
970       break;
971     case GPGME_SIG_STAT_NOSIG:
972       result = "No signature found";
973       break;
974     case GPGME_SIG_STAT_GOOD:
975       result = "Good signature";
976       break;
977     case GPGME_SIG_STAT_BAD:
978       result = "BAD signature";
979       break;
980     case GPGME_SIG_STAT_NOKEY:
981       result = "No public key to verify the signature";
982       break;
983     case GPGME_SIG_STAT_ERROR:
984       result = "Error verifying the signature";
985       break;
986     case GPGME_SIG_STAT_DIFF:
987       result = "Different results for signatures";
988       break;
989     default:
990       result = "Error: Unknown status";
991       break;
992   }
993
994   return result;
995 }
996
997
998 bool checkMessageSignature( const char* ciphertext,
999                             const char* signaturetext,
1000                             bool signatureIsBinary,
1001                             int signatureLen,
1002                             struct SignatureMetaData* sigmeta )
1003 {
1004   GpgmeCtx ctx;
1005   GpgmeSigStat status;
1006   GpgmeData datapart, sigpart;
1007   GpgmeError err;
1008   GpgmeKey key;
1009   time_t created;
1010   int sig_idx = 0;
1011   const char* statusStr;
1012   const char* fpr;
1013
1014   gpgme_new( &ctx );
1015   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1016   gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
1017 //  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1);
1018
1019   gpgme_data_new_from_mem( &datapart, ciphertext,
1020                           strlen( ciphertext ), 1 );
1021
1022   gpgme_data_new_from_mem( &sigpart,
1023                            signaturetext,
1024                            signatureIsBinary
1025                            ? signatureLen
1026                            : strlen( signaturetext ),
1027                            1 );
1028
1029   gpgme_op_verify( ctx, sigpart, datapart, &status );
1030   gpgme_data_release( datapart );
1031   gpgme_data_release( sigpart );
1032
1033   /* Provide information in the sigmeta struct */
1034   /* the status string */
1035   statusStr = sig_status_to_string( status );
1036   sigmeta->status = malloc( strlen( statusStr ) + 1 );
1037   if( sigmeta->status ) {
1038     strcpy( sigmeta->status, statusStr );
1039     sigmeta->status[strlen( statusStr )] = '\0';
1040   } else
1041     ; // nothing to do, is already 0
1042
1043   // Extended information for any number of signatures.
1044   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
1045   sigmeta->extended_info = 0;
1046   while( fpr != NULL ) {
1047     struct tm* ctime_val;
1048     const char* sig_status;
1049
1050     void* realloc_return = realloc( sigmeta->extended_info,
1051                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1052     if( realloc_return ) {
1053       sigmeta->extended_info = realloc_return;
1054       // the creation time
1055       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1056       if( sigmeta->extended_info[sig_idx].creation_time ) {
1057         ctime_val = localtime( &created );
1058         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1059                 ctime_val, sizeof( struct tm ) );
1060       }
1061
1062       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1063       sig_status = sig_status_to_string( status );
1064       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
1065       if( sigmeta->extended_info[sig_idx].status_text ) {
1066         strcpy( sigmeta->extended_info[sig_idx].status_text,
1067                 sig_status );
1068         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
1069       }
1070
1071       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1072       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1073         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1074         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1075       }
1076     } else
1077       break; // if allocation fails once, it isn't likely to
1078               // succeed the next time either
1079
1080     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1081   }
1082   sigmeta->extended_info_count = sig_idx;
1083   sigmeta->nota_xml = gpgme_get_notation( ctx );
1084   sigmeta->status_code = status;
1085
1086   gpgme_release( ctx );
1087   return ( status == GPGME_SIG_STAT_GOOD );
1088 }
1089
1090 bool storeCertificatesFromMessage(
1091         const char* ciphertext ){ return true; }
1092
1093
1094 /* returns address if address doesn't contain a <xxx> part
1095  * else it returns a new string xxx and frees address
1096  */
1097 static char* parseAddress( char* address )
1098 {
1099   char* result = address;
1100   char* i;
1101   char* j;
1102   if( !result ) return result;
1103   i = index( address, '<' );
1104   if( i ) {
1105     j = index( i+1, '>' );
1106     if( j == NULL ) j = address+strlen(address);
1107     result = malloc( j-i );
1108     strncpy( result, i+1, j-i-1 );
1109     result[j-i-1] = '\0';
1110     free( address );
1111   } else {
1112     i = address;
1113     j = i+strlen(address);
1114   }
1115   {
1116     /* remove surrounding whitespace */
1117     char* k = result+(j-i-1);
1118     char* l = result;
1119     while( isspace( *l ) ) ++l;
1120     while( isspace( *k ) ) --k;
1121     if( l != result || k != result+(j-i-1) ) {
1122       char* result2 = malloc( k-l+2 );
1123       strncpy( result2, l, k-l+1 );
1124       result2[k-l+1] = '\0';
1125       free(result);
1126       result = result2;
1127     }
1128   }
1129   return result;
1130 }
1131
1132 static char* nextAddress( const char** address )
1133 {
1134   const char *start = *address;
1135   char* result = NULL;
1136   int quote = 0;
1137   int comment = 0;
1138   int found = 0;
1139   if( *address == NULL ) return NULL;
1140   while( **address ) {
1141
1142     switch( **address ) {
1143     case '\\': /* escaped character */
1144       ++(*address);
1145       break;
1146     case '"':
1147       if( comment == 0 ) {
1148         if( quote > 0 ) --quote;
1149         else ++quote;
1150       }
1151       break;
1152     case '(': /* comment start */
1153       if( quote == 0 ) ++comment;
1154       break;
1155     case ')': /* comment end */
1156       if( quote == 0 ) --comment;
1157       break;
1158     case '\0':
1159     case '\1': /* delimiter */
1160       if( quote == 0 && comment == 0 ) {
1161         found = 1;
1162       }
1163       break;
1164     }
1165     ++(*address);
1166     if( found ) break;
1167   }
1168   if( found || **address == 0 ) {
1169     size_t len;
1170     len = *address - start;
1171     if( len > 0 ) {
1172       if( **address != 0 ) --len;
1173       result = malloc( len*sizeof(char)+1 );
1174       strncpy( result, start, len );
1175       result[len] = '\0';
1176     }
1177   }
1178   return parseAddress(result);
1179 }
1180
1181 /*
1182   Find all certificate for a given addressee and return them in a
1183   '\1' separated list.
1184   NOTE: The certificate parameter must point to an allready allocated
1185   block of memory which is large enough to hold the complete list.
1186 */
1187 bool findCertificates( const char* addressee, char** certificates )
1188 {
1189   GpgmeCtx ctx;
1190   GpgmeError err;
1191   GpgmeKey rKey;
1192   const char *s;
1193   const char *s2;
1194   bool bOk = false;
1195   
1196   strcpy( *certificates, "" );
1197
1198   gpgme_new (&ctx);
1199   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1200
1201   err = gpgme_op_keylist_start(ctx, addressee, 0);
1202   while( GPGME_No_Error == err ) {
1203     err = gpgme_op_keylist_next(ctx, &rKey);
1204     if( GPGME_No_Error == err ) {
1205       bOk = true;
1206       s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
1207       if( s ) {
1208         s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
1209         if( s2 ) {
1210           strcat( *certificates, s );
1211           strcat( *certificates, "(" );
1212           strcat( *certificates, s2 );
1213           strcat( *certificates, ")\1" );
1214         }
1215       }
1216     }
1217   }
1218   gpgme_op_keylist_end( ctx );
1219   return bOk;
1220 }
1221
1222 bool encryptMessage( const char*  cleartext,
1223                      const char** ciphertext,
1224                      const char*  certificate,
1225                      struct StructuringInfo* structuring )
1226 {
1227   GpgmeCtx ctx;
1228   GpgmeError err;
1229   GpgmeData gCiphertext, gPlaintext;
1230   GpgmeRecipients rset;
1231   size_t rCLen = 0;
1232   char*  rCiph = 0;
1233   bool   bOk   = false;
1234
1235   init_StructuringInfo( structuring );
1236
1237   gpgme_new (&ctx);
1238   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1239
1240   gpgme_set_armor (ctx, 1);
1241   gpgme_set_textmode (ctx, 1);
1242
1243   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1244                             1+strlen( cleartext ), 1 );
1245   err = gpgme_data_new ( &gCiphertext );
1246
1247   gpgme_recipients_new (&rset);
1248
1249   /*
1250   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1251   {
1252     gpgme_recipients_add_name_with_validity (rset,
1253       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
1254       GPGME_VALIDITY_FULL );
1255     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1256   }
1257   else
1258   */
1259   {
1260     const char* p = certificate;
1261     char* tok;
1262     while( (tok = nextAddress( &p ) ) != 0 ) {
1263       if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1264         gpgme_recipients_add_name_with_validity (rset, tok, GPGME_VALIDITY_FULL );
1265       else
1266         gpgme_recipients_add_name (rset, tok);
1267       fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
1268       free(tok);
1269     }
1270   }
1271
1272   // PENDING(g10) Implement this
1273   // Possible values: RSA = 1, SHA1 = 2, TripleDES = 3
1274   //gpgme_set_encryption_algorithm( ctx, config.encryptionAlgorithm );
1275
1276
1277   // PENDING(g10) Implement this
1278   // gpgme_set_encryption_check_certificate_path(
1279   // config.checkCertificatePath )
1280
1281   // PENDING(g10) Implement this
1282   // gpgme_set_encryption_check_certificate_path_to_root(
1283   // config.checkEncryptionCertificatePathToRoot )
1284
1285
1286   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1287   if( err )
1288     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1289
1290   gpgme_recipients_release (rset);
1291   gpgme_data_release (gPlaintext);
1292
1293   if( !err ) {
1294     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1295     *ciphertext = malloc( rCLen + 1 );
1296     if( *ciphertext ) {
1297       if( rCLen ) {
1298         bOk = true;
1299         strncpy((char*)*ciphertext, rCiph, rCLen );
1300       }
1301       ((char*)(*ciphertext))[rCLen] = 0;
1302     }
1303     free( rCiph );
1304   }
1305   else {
1306     gpgme_data_release ( gCiphertext );
1307     *ciphertext = 0;
1308     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1309     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1310     // das signieren.
1311   }
1312
1313   gpgme_release (ctx);
1314
1315   fflush( stderr );
1316
1317   if( bOk && structuring ) {
1318     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1319     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1320     if( structuring->makeMimeObject ) {
1321       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1322       storeNewCharPtr( &structuring->contentTypeMain,
1323                        GPGMEPLUG_ENC_CTYPE_MAIN );
1324       storeNewCharPtr( &structuring->contentDispMain,
1325                        GPGMEPLUG_ENC_CDISP_MAIN );
1326       storeNewCharPtr( &structuring->contentTEncMain,
1327                        GPGMEPLUG_ENC_CTENC_MAIN );
1328       if( structuring->makeMultiMime ) {
1329         storeNewCharPtr( &structuring->contentTypeVersion,
1330                          GPGMEPLUG_ENC_CTYPE_VERSION );
1331         storeNewCharPtr( &structuring->contentDispVersion,
1332                          GPGMEPLUG_ENC_CDISP_VERSION );
1333         storeNewCharPtr( &structuring->contentTEncVersion,
1334                          GPGMEPLUG_ENC_CTENC_VERSION );
1335         storeNewCharPtr( &structuring->bodyTextVersion,
1336                          GPGMEPLUG_ENC_BTEXT_VERSION );
1337         storeNewCharPtr( &structuring->contentTypeCode,
1338                          GPGMEPLUG_ENC_CTYPE_CODE );
1339         storeNewCharPtr( &structuring->contentDispCode,
1340                          GPGMEPLUG_ENC_CDISP_CODE );
1341         storeNewCharPtr( &structuring->contentTEncCode,
1342                          GPGMEPLUG_ENC_CTENC_CODE );
1343       }
1344     } else {
1345       storeNewCharPtr( &structuring->flatTextPrefix,
1346                        GPGMEPLUG_ENC_FLAT_PREFIX );
1347       storeNewCharPtr( &structuring->flatTextSeparator,
1348                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1349       storeNewCharPtr( &structuring->flatTextPostfix,
1350                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1351     }
1352   }
1353   return bOk;
1354 }
1355
1356
1357 bool encryptAndSignMessage( const char* cleartext,
1358                             const char** ciphertext,
1359                             const char* certificate,
1360                             struct StructuringInfo* structuring )
1361 {
1362   bool bOk;
1363
1364   init_StructuringInfo( structuring );
1365
1366   bOk = false;
1367
1368   // implementation of this function is still missing
1369
1370   if( bOk && structuring ) {
1371     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1372     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1373     if( structuring->makeMimeObject ) {
1374       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1375       storeNewCharPtr( &structuring->contentTypeMain,
1376                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1377       storeNewCharPtr( &structuring->contentDispMain,
1378                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1379       storeNewCharPtr( &structuring->contentTEncMain,
1380                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1381       if( structuring->makeMultiMime ) {
1382         storeNewCharPtr( &structuring->contentTypeVersion,
1383                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1384         storeNewCharPtr( &structuring->contentDispVersion,
1385                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1386         storeNewCharPtr( &structuring->contentTEncVersion,
1387                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1388         storeNewCharPtr( &structuring->bodyTextVersion,
1389                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1390         storeNewCharPtr( &structuring->contentTypeCode,
1391                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1392         storeNewCharPtr( &structuring->contentDispCode,
1393                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1394         storeNewCharPtr( &structuring->contentTEncCode,
1395                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1396       }
1397     } else {
1398       storeNewCharPtr( &structuring->flatTextPrefix,
1399                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1400       storeNewCharPtr( &structuring->flatTextSeparator,
1401                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1402       storeNewCharPtr( &structuring->flatTextPostfix,
1403                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1404     }
1405   }
1406   return bOk;
1407 }
1408
1409 bool decryptMessage( const char* ciphertext,
1410                      const char** cleartext,
1411                      const char* certificate )
1412 {
1413   GpgmeCtx ctx;
1414   GpgmeError err;
1415   GpgmeData gCiphertext, gPlaintext;
1416   size_t rCLen = 0;
1417   char*  rCiph = 0;
1418   bool bOk = false;
1419
1420   if( !ciphertext )
1421     return false;
1422
1423   err = gpgme_new (&ctx);
1424   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1425
1426   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1427                            1+strlen( ciphertext ), 1 );
1428   gpgme_data_new( &gPlaintext );
1429
1430   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1431   gpgme_data_release( gCiphertext );
1432
1433   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1434
1435   *cleartext = malloc( rCLen + 1 );
1436   if( *cleartext ) {
1437       if( rCLen ) {
1438           bOk = true;
1439           strncpy((char*)*cleartext, rCiph, rCLen );
1440       }
1441       ((char*)(*cleartext))[rCLen] = 0;
1442   }
1443
1444   free( rCiph );
1445   gpgme_release( ctx );
1446   return bOk;
1447 }
1448
1449 bool decryptAndCheckMessage( const char* ciphertext,
1450           const char** cleartext, const char* certificate,
1451           struct SignatureMetaData* sigmeta ){ return true; }
1452
1453
1454 const char* requestCertificateDialog(){ return 0; }
1455
1456 bool requestDecentralCertificate( const char* name, const char*
1457           email, const char* organization, const char* department,
1458           const char* ca_address ){ return true; }
1459
1460 bool requestCentralCertificateAndPSE( const char* name,
1461           const char* email, const char* organization, const char* department,
1462           const char* ca_address ){ return true; }
1463
1464 bool createPSE(){ return true; }
1465
1466 bool registerCertificate( const char* certificate ){ return true; }
1467
1468 bool requestCertificateProlongation( const char* certificate,
1469                                      const char* ca_address ){ return true; }
1470
1471 const char* certificateChain(){ return 0; }
1472
1473 bool deleteCertificate( const char* certificate ){ return true; }
1474
1475 bool archiveCertificate( const char* certificate ){ return true; }
1476
1477
1478 const char* displayCRL(){ return 0; }
1479
1480 void updateCRL(){}