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