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