Include the protocol parameter of multipart/.. content-type messages into double...
[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   GpgmeCtx ctx;
456   GpgmeError err;
457   GpgmeKey rKey;
458   time_t daysLeft = 0;
459
460   gpgme_new( &ctx );
461   gpgme_set_protocol( ctx, GPGMEPLUG_PROTOCOL );
462
463   err = gpgme_op_keylist_start( ctx, certificate, 0 );
464   if ( GPGME_No_Error == err ) {
465     err = gpgme_op_keylist_next( ctx, &rKey );
466     gpgme_op_keylist_end( ctx );
467     if ( GPGME_No_Error == err ) {
468       time_t expire_time = gpgme_key_get_ulong_attr(
469                              rKey,GPGME_ATTR_EXPIRE, NULL, 0 );
470       time_t cur_time = time (NULL);
471       daysLeft = expire_time - cur_time;
472       // convert seconds into days
473       daysLeft /= 43200;
474       gpgme_key_release( rKey );
475     }
476   }
477   gpgme_release( ctx );
478
479   return daysLeft;
480 }
481
482
483 void setSignatureCertificateExpiryNearInterval( int interval )
484 {
485   config.signatureCertificateExpiryNearInterval = interval;
486 }
487
488 int signatureCertificateExpiryNearInterval( void )
489 {
490   return config.signatureCertificateExpiryNearInterval;
491 }
492
493 void setCACertificateExpiryNearWarning( bool flag )
494 {
495   config.cACertificateExpiryNearWarning = flag;
496 }
497
498 bool caCertificateExpiryNearWarning( void )
499 {
500   return config.cACertificateExpiryNearWarning;
501 }
502
503 int caCertificateDaysLeftToExpiry( const char* certificate )
504 {
505     /* PENDING(g10)
506        Please return the number of days that are left until the
507        CA certificate for the certificate specified in the parameter
508        certificate expires.
509     */
510   return 10; /* dummy that triggers a warning in the MUA */
511 }
512
513 void setCACertificateExpiryNearInterval( int interval )
514 {
515   config.cACertificateExpiryNearInterval = interval;
516 }
517
518 int caCertificateExpiryNearInterval( void )
519 {
520   return config.cACertificateExpiryNearInterval;
521 }
522
523 void setRootCertificateExpiryNearWarning( bool flag )
524 {
525   config.rootCertificateExpiryNearWarning = flag;
526 }
527
528 bool rootCertificateExpiryNearWarning( void )
529 {
530   return config.rootCertificateExpiryNearWarning;
531 }
532
533 int rootCertificateDaysLeftToExpiry( const char* certificate )
534 {
535     /* PENDING(g10)
536        Please return the number of days that are left until the
537        root certificate for the certificate specified in the parameter
538        certificate expires.
539     */
540   return 10; /* dummy that triggers a warning in the MUA */
541 }
542
543
544 void setRootCertificateExpiryNearInterval( int interval )
545 {
546   config.rootCertificateExpiryNearInterval = interval;
547 }
548
549 int rootCertificateExpiryNearInterval( void )
550 {
551   return config.rootCertificateExpiryNearInterval;
552 }
553
554
555
556
557
558
559
560
561 const char* encryptionConfigurationDialog(){ return 0; }
562
563 const char* encryptionAlgorithmDialog(){ return 0; }
564
565 const char* encryptionHandlingDialog(){ return 0; }
566
567 const char* encryptionReceiverDialog(){ return 0; }
568
569 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
570 {
571   config.encryptionAlgorithm = cryptAlg;
572 }
573
574 EncryptionAlgorithm encryptionAlgorithm()
575 {
576   return config.encryptionAlgorithm;
577 }
578
579 void setEncryptEmail( EncryptEmail cryptMode )
580 {
581   config.encryptEmail = cryptMode;
582 }
583
584 EncryptEmail encryptEmail()
585 {
586   return config.encryptEmail;
587 }
588
589
590
591
592
593
594 void setWarnSendUnencrypted( bool flag )
595 {
596   config.warnSendUnencrypted = flag;
597 }
598
599 bool warnSendUnencrypted()
600 {
601   return config.warnSendUnencrypted;
602 }
603
604
605
606
607
608
609
610
611
612 void setSaveMessagesEncrypted( bool flag )
613 {
614   config.saveMessagesEncrypted = flag;
615 }
616
617 bool saveMessagesEncrypted()
618 {
619   return config.saveMessagesEncrypted;
620 }
621
622
623
624
625
626
627
628 void setCheckCertificatePath( bool flag )
629 {
630   config.checkCertificatePath = flag;
631 }
632
633 bool checkCertificatePath()
634 {
635   return config.checkCertificatePath;
636 }
637
638
639
640
641
642
643
644
645 void setCheckEncryptionCertificatePathToRoot( bool flag )
646 {
647   config.checkEncryptionCertificatePathToRoot = flag;
648 }
649
650 bool checkEncryptionCertificatePathToRoot()
651 {
652   return config.checkEncryptionCertificatePathToRoot;
653 }
654
655
656
657
658
659
660
661 void setReceiverCertificateExpiryNearWarning( bool flag )
662 {
663   config.receiverCertificateExpiryNearWarning = flag;
664 }
665
666 bool receiverCertificateExpiryNearWarning()
667 {
668   return config.receiverCertificateExpiryNearWarning;
669 }
670
671
672 int receiverCertificateDaysLeftToExpiry( const char* certificate )
673 {
674     /* PENDING(g10)
675        Please return the number of days that are left until the
676        certificate specified in the parameter certificate expires.
677     */
678   return 10; /* dummy that triggers a warning in the MUA */
679 }
680
681
682 void setReceiverCertificateExpiryNearWarningInterval( int interval )
683 {
684   config.receiverCertificateExpiryNearWarningInterval = interval;
685 }
686
687 int receiverCertificateExpiryNearWarningInterval()
688 {
689   return config.receiverCertificateExpiryNearWarningInterval;
690 }
691
692 void setCertificateInChainExpiryNearWarning( bool flag )
693 {
694   config.certificateInChainExpiryNearWarning = flag;
695 }
696
697 bool certificateInChainExpiryNearWarning()
698 {
699   return config.certificateInChainExpiryNearWarning;
700 }
701
702
703 int certificateInChainDaysLeftToExpiry( const char* certificate )
704 {
705     /* PENDING(g10)
706        Please return the number of days that are left until the
707        the first certificate in the chain of the specified certificate
708        expires.
709     */
710   return 10; /* dummy that triggers a warning in the MUA */
711 }
712
713
714 void setCertificateInChainExpiryNearWarningInterval( int interval )
715 {
716   config.certificateInChainExpiryNearWarningInterval = interval;
717 }
718
719 int certificateInChainExpiryNearWarningInterval()
720 {
721   return config.certificateInChainExpiryNearWarningInterval;
722 }
723
724 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
725 {
726   config.receiverEmailAddressNotInCertificateWarning = flag;
727 }
728
729 bool receiverEmailAddressNotInCertificateWarning()
730 {
731   return config.receiverEmailAddressNotInCertificateWarning;
732 }
733
734
735
736
737
738
739
740
741 void setEncryptionUseCRLs( bool flag )
742 {
743   config.encryptionUseCRLs = flag;
744
745   /* PENDING(g10) Store this setting in gpgme and use it. If true,
746      every certificate used for encryption should be checked against
747      applicable CRLs.
748   */
749 }
750
751 bool encryptionUseCRLs()
752 {
753   return config.encryptionUseCRLs;
754 }
755
756
757 int encryptionCRLsDaysLeftToExpiry()
758 {
759     /* PENDING(g10)
760        Please return the number of days that are left until the
761        CRL used for encryption expires.
762     */
763   return 10; /* dummy that triggers a warning in the MUA */
764 }
765
766 void setEncryptionCRLExpiryNearWarning( bool flag )
767 {
768   config.encryptionCRLExpiryNearWarning = flag;
769 }
770
771 bool encryptionCRLExpiryNearWarning()
772 {
773   return config.encryptionCRLExpiryNearWarning;
774 }
775
776 void setEncryptionCRLNearExpiryInterval( int interval )
777 {
778   config.encryptionCRLNearExpiryInterval = interval;
779 }
780
781 int encryptionCRLNearExpiryInterval()
782 {
783   return config.encryptionCRLNearExpiryInterval;
784 }
785
786
787 const char* directoryServiceConfigurationDialog(){ return 0; }
788
789 void appendDirectoryServer( const char* servername,
790                             int         port,
791                             const char* description )
792 {
793   struct DirectoryServer *newServers = NULL;
794   newServers = realloc( config.directoryServers,
795                         (1+config.numDirectoryServers) * sizeof *newServers );
796   if( newServers ) {
797     config.directoryServers = newServers;
798     newServers[ config.numDirectoryServers ].servername =
799       malloc( 1+strlen( servername ) );
800     if( newServers[ config.numDirectoryServers ].servername ) {
801       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
802         servername );
803       newServers[ config.numDirectoryServers ].description =
804         malloc( 1+strlen(  description ) );
805       if( newServers[ config.numDirectoryServers ].description ) {
806         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
807           description );
808         newServers[ config.numDirectoryServers ].port = port;
809         config.numDirectoryServers += 1;
810       }
811     }
812   }
813 }
814
815 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
816 {
817   unsigned int i;
818   int oldSize = config.numDirectoryServers;
819   struct DirectoryServer *newServers = NULL;
820   newServers = calloc ( size, sizeof *newServers );
821   if( newServers ) {
822     for( i=0; i < oldSize; ++i ) {
823       free( (char *)config.directoryServers[i].servername );
824       free( (char *)config.directoryServers[i].description );
825     }
826     free( config.directoryServers );
827     for( i=0; i < size; ++i ) {
828       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
829       if( newServers[ i ].servername ) {
830         strcpy( (char *)newServers[ i ].servername, server[i].servername );
831         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
832         if( newServers[ i ].description ) {
833           strcpy( (char *)newServers[ i ].description, server[i].description );
834           newServers[ i ].port = server[i].port;
835         }
836       }
837     }
838     config.directoryServers = newServers;
839     config.numDirectoryServers = size;
840   }
841 }
842
843 struct DirectoryServer * directoryServers( int* numServers )
844 {
845   if( numServers )
846     *numServers = config.numDirectoryServers;
847   return config.directoryServers;
848 };
849
850 void setCertificateSource( CertificateSource source )
851 {
852   config.certificateSource = source;
853 }
854
855 CertificateSource certificateSource()
856 {
857   return config.certificateSource;
858 }
859
860 void setCRLSource( CertificateSource source )
861 {
862   config.cRLSource = source;
863 }
864
865 CertificateSource crlSource()
866 {
867   return config.cRLSource;
868 }
869
870
871 bool certificateValidity( const char* certificate,
872                           int* level ){ return true; }
873
874
875 void storeNewCharPtr( char** dest, const char* src )
876 {
877   int sLen = strlen( src );
878   *dest = malloc( sLen + 1 );
879   strcpy( *dest, src );
880   (*dest)[sLen] = '\0';
881 }
882
883
884 bool signMessage( const char*  cleartext,
885                   char** ciphertext,
886                   const size_t* cipherLen,
887                   const char*  certificate,
888                   struct StructuringInfo* structuring,
889                   int* errId,
890                   char** errTxt )
891 {
892   GpgmeCtx ctx;
893   GpgmeError err;
894   GpgmeData data,  sig;
895   char* rSig  = 0;
896   bool  bOk   = false;
897   int sendCerts = 1;
898
899   init_StructuringInfo( structuring );
900
901   if( !ciphertext )
902     return false;
903
904   err = gpgme_new (&ctx);
905   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
906
907   gpgme_set_armor (ctx, __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ? 0 : 1);
908   /*  gpgme_set_textmode (ctx, 1); */
909
910   switch ( config.sendCertificates ) {
911     case SendCert_undef:
912       break;
913     case SendCert_DontSend:
914       sendCerts = 0;
915       break;
916     case SendCert_SendOwn:
917       sendCerts = 1;
918       break;
919     case SendCert_SendChainWithoutRoot:
920       sendCerts = -2;
921       break;
922     case SendCert_SendChainWithRoot:
923       sendCerts = -1;
924       break;
925     default:
926       sendCerts = 0;
927       break;
928   }
929   gpgme_set_include_certs (ctx, sendCerts);
930
931   /* PENDING(g10) Implement this
932
933      gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm )
934      --> This does not make sense.  The algorithm is a property of
935      the certificate used [wk 2002-03-23] */
936
937   gpgme_data_new_from_mem (&data, cleartext,
938                             strlen( cleartext ), 1 );
939   gpgme_data_new ( &sig );
940   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
941
942   if (!err) {
943     if( __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ) {
944       *ciphertext = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
945       bOk = true;
946     }
947     else {
948       rSig = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
949       *ciphertext = malloc( *cipherLen + 1 );
950       if( *ciphertext ) {
951         if( *cipherLen ) {
952           bOk = true;
953           strncpy((char*)*ciphertext, rSig, *cipherLen );
954         }
955         (*ciphertext)[*cipherLen] = '\0';
956       }
957       free( rSig );
958     }
959   }
960   else {
961     gpgme_data_release( sig );
962     *ciphertext = 0;
963     fprintf( stderr, "\ngpgme_op_sign() returned this error code:  %i\n\n", err );
964     if( errId )
965       *errId = err;
966     if( errTxt ) {
967       const char* _errTxt = gpgme_strerror( err );
968       *errTxt = malloc( strlen( _errTxt ) + 1 );
969       if( *errTxt )
970         strcpy(*errTxt, _errTxt );
971     }
972   }
973   gpgme_data_release( data );
974   gpgme_release (ctx);
975
976   if( bOk && structuring ) {
977     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
978     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
979     if( structuring->makeMimeObject ) {
980       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
981       storeNewCharPtr( &structuring->contentTypeMain,
982                        GPGMEPLUG_SIGN_CTYPE_MAIN );
983       storeNewCharPtr( &structuring->contentDispMain,
984                        GPGMEPLUG_SIGN_CDISP_MAIN );
985       storeNewCharPtr( &structuring->contentTEncMain,
986                        GPGMEPLUG_SIGN_CTENC_MAIN );
987       if( structuring->makeMultiMime ) {
988         storeNewCharPtr( &structuring->contentTypeVersion,
989                          GPGMEPLUG_SIGN_CTYPE_VERSION );
990         storeNewCharPtr( &structuring->contentDispVersion,
991                          GPGMEPLUG_SIGN_CDISP_VERSION );
992         storeNewCharPtr( &structuring->contentTEncVersion,
993                          GPGMEPLUG_SIGN_CTENC_VERSION );
994         storeNewCharPtr( &structuring->bodyTextVersion,
995                          GPGMEPLUG_SIGN_BTEXT_VERSION );
996         storeNewCharPtr( &structuring->contentTypeCode,
997                          GPGMEPLUG_SIGN_CTYPE_CODE );
998         storeNewCharPtr( &structuring->contentDispCode,
999                          GPGMEPLUG_SIGN_CDISP_CODE );
1000         storeNewCharPtr( &structuring->contentTEncCode,
1001                          GPGMEPLUG_SIGN_CTENC_CODE );
1002       }
1003     } else {
1004       storeNewCharPtr( &structuring->flatTextPrefix,
1005                        GPGMEPLUG_SIGN_FLAT_PREFIX );
1006       storeNewCharPtr( &structuring->flatTextSeparator,
1007                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
1008       storeNewCharPtr( &structuring->flatTextPostfix,
1009                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
1010     }
1011   }
1012   return bOk;
1013 }
1014
1015
1016 static const char*
1017 sig_status_to_string( GpgmeSigStat status )
1018 {
1019   const char *result;
1020
1021   switch (status) {
1022     case GPGME_SIG_STAT_NONE:
1023       result = "Oops: Signature not verified";
1024       break;
1025     case GPGME_SIG_STAT_NOSIG:
1026       result = "No signature found";
1027       break;
1028     case GPGME_SIG_STAT_GOOD:
1029       result = "Good signature";
1030       break;
1031     case GPGME_SIG_STAT_BAD:
1032       result = "BAD signature";
1033       break;
1034     case GPGME_SIG_STAT_NOKEY:
1035       result = "No public key to verify the signature";
1036       break;
1037     case GPGME_SIG_STAT_ERROR:
1038       result = "Error verifying the signature";
1039       break;
1040     case GPGME_SIG_STAT_DIFF:
1041       result = "Different results for signatures";
1042       break;
1043     default:
1044       result = "Error: Unknown status";
1045       break;
1046   }
1047
1048   return result;
1049 }
1050
1051
1052 bool checkMessageSignature( char** cleartext,
1053                             const char* signaturetext,
1054                             bool signatureIsBinary,
1055                             int signatureLen,
1056                             struct SignatureMetaData* sigmeta )
1057 {
1058   GpgmeCtx ctx;
1059   GpgmeSigStat status;
1060   GpgmeData datapart, sigpart;
1061   char* rClear = 0;
1062   size_t clearLen;
1063   GpgmeError err;
1064   GpgmeKey key;
1065   time_t created;
1066   int sig_idx = 0;
1067   const char* statusStr;
1068   const char* fpr;
1069   bool isOpaqueSigned;
1070
1071   if( !cleartext ) {
1072     if( sigmeta ) {
1073       sigmeta->status = malloc( strlen( __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO ) + 1 );
1074       if( sigmeta->status ) {
1075         strcpy( sigmeta->status, __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
1076         sigmeta->status[ strlen( __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO ) ] = '\0';
1077       }
1078     }
1079     return false;
1080   }
1081
1082   isOpaqueSigned = !*cleartext;
1083
1084   gpgme_new( &ctx );
1085   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1086   gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
1087   /*  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */
1088
1089   if( isOpaqueSigned )
1090     gpgme_data_new( &datapart );
1091   else
1092     gpgme_data_new_from_mem( &datapart, *cleartext,
1093                              strlen( *cleartext ), 1 );
1094
1095   gpgme_data_new_from_mem( &sigpart,
1096                            signaturetext,
1097                            signatureIsBinary
1098                            ? signatureLen
1099                            : strlen( signaturetext ),
1100                            1 );
1101
1102   gpgme_op_verify( ctx, sigpart, datapart, &status );
1103
1104   if( isOpaqueSigned ) {
1105     rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
1106     *cleartext = malloc( clearLen + 1 );
1107     if( *cleartext ) {
1108       if( clearLen )
1109         strncpy(*cleartext, rClear, clearLen );
1110       (*cleartext)[clearLen] = '\0';
1111     }
1112     free( rClear );
1113   }
1114   else
1115     gpgme_data_release( datapart );
1116
1117   gpgme_data_release( sigpart );
1118
1119   /* Provide information in the sigmeta struct */
1120   /* the status string */
1121   statusStr = sig_status_to_string( status );
1122   sigmeta->status = malloc( strlen( statusStr ) + 1 );
1123   if( sigmeta->status ) {
1124     strcpy( sigmeta->status, statusStr );
1125     sigmeta->status[strlen( statusStr )] = '\0';
1126   } else
1127     ; /* nothing to do, is already 0 */
1128
1129   /* Extended information for any number of signatures. */
1130   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
1131   sigmeta->extended_info = 0;
1132   while( fpr != NULL ) {
1133     struct tm* ctime_val;
1134     const char* sig_status;
1135
1136     void* realloc_return = realloc( sigmeta->extended_info,
1137                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1138     if( realloc_return ) {
1139       sigmeta->extended_info = realloc_return;
1140       /* the creation time */
1141       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1142       if( sigmeta->extended_info[sig_idx].creation_time ) {
1143         ctime_val = localtime( &created );
1144         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1145                 ctime_val, sizeof( struct tm ) );
1146       }
1147
1148       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1149       sig_status = sig_status_to_string( status );
1150       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
1151       if( sigmeta->extended_info[sig_idx].status_text ) {
1152         strcpy( sigmeta->extended_info[sig_idx].status_text,
1153                 sig_status );
1154         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
1155       }
1156
1157       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1158       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1159         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1160         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1161       }
1162     } else
1163       break; /* if allocation fails once, it isn't likely to
1164                 succeed the next time either */
1165
1166     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1167   }
1168   sigmeta->extended_info_count = sig_idx;
1169   sigmeta->nota_xml = gpgme_get_notation( ctx );
1170   sigmeta->status_code = status;
1171
1172   gpgme_release( ctx );
1173   return ( status == GPGME_SIG_STAT_GOOD );
1174 }
1175
1176 bool storeCertificatesFromMessage(
1177         const char* ciphertext ){ return true; }
1178
1179
1180 /* returns address if address doesn't contain a <xxx> part
1181  * else it returns a new string xxx and frees address
1182  */
1183 static char* parseAddress( char* address )
1184 {
1185   char* result = address;
1186   char* i;
1187   char* j;
1188   if( !result ) return result;
1189   i = index( address, '<' );
1190   if( i ) {
1191     j = index( i+1, '>' );
1192     if( j == NULL ) j = address+strlen(address);
1193     result = malloc( j-i );
1194     strncpy( result, i+1, j-i-1 );
1195     result[j-i-1] = '\0';
1196     free( address );
1197   } else {
1198     i = address;
1199     j = i+strlen(address);
1200   }
1201   {
1202     /* remove surrounding whitespace */
1203     char* k = result+(j-i-1);
1204     char* l = result;
1205     while( isspace( *l ) ) ++l;
1206     while( isspace( *k ) ) --k;
1207     if( l != result || k != result+(j-i-1) ) {
1208       char* result2 = malloc( k-l+2 );
1209       strncpy( result2, l, k-l+1 );
1210       result2[k-l+1] = '\0';
1211       free(result);
1212       result = result2;
1213     }
1214   }
1215   return result;
1216 }
1217
1218 static char* nextAddress( const char** address )
1219 {
1220   const char *start = *address;
1221   char* result = NULL;
1222   int quote = 0;
1223   int comment = 0;
1224   int found = 0;
1225   if( *address == NULL ) return NULL;
1226   while( **address ) {
1227
1228     switch( **address ) {
1229     case '\\': /* escaped character */
1230       ++(*address);
1231       break;
1232     case '"':
1233       if( comment == 0 ) {
1234         if( quote > 0 ) --quote;
1235         else ++quote;
1236       }
1237       break;
1238     case '(': /* comment start */
1239       if( quote == 0 ) ++comment;
1240       break;
1241     case ')': /* comment end */
1242       if( quote == 0 ) --comment;
1243       break;
1244     case '\0':
1245     case '\1': /* delimiter */
1246       if( quote == 0 && comment == 0 ) {
1247         found = 1;
1248       }
1249       break;
1250     }
1251     ++(*address);
1252     if( found ) break;
1253   }
1254   if( found || **address == 0 ) {
1255     size_t len;
1256     len = *address - start;
1257     if( len > 0 ) {
1258       if( **address != 0 ) --len;
1259       result = malloc( len*sizeof(char)+1 );
1260       strncpy( result, start, len );
1261       result[len] = '\0';
1262     }
1263   }
1264   return parseAddress(result);
1265 }
1266
1267 /*
1268   Find all certificate for a given addressee and return them in a
1269   '\1' separated list.
1270   NOTE: The certificate parameter must point to an allready allocated
1271   block of memory which is large enough to hold the complete list.
1272 */
1273 bool findCertificates( const char* addressee, char** certificates )
1274 {
1275   GpgmeCtx ctx;
1276   GpgmeError err;
1277   GpgmeKey rKey;
1278   const char *s;
1279   const char *s2;
1280   int nFound = 0;
1281
1282   strcpy( *certificates, "" );
1283
1284   gpgme_new (&ctx);
1285   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1286
1287   err = gpgme_op_keylist_start(ctx, addressee, 0);
1288   while( GPGME_No_Error == err ) {
1289     err = gpgme_op_keylist_next(ctx, &rKey);
1290     if( GPGME_No_Error == err ) {
1291       s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
1292       if( s ) {
1293         s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
1294         if( s2 ) {
1295           if( nFound )
1296             strcat(*certificates,"\1" );
1297           strcat( *certificates, s );
1298           strcat( *certificates, "    (" );
1299           strcat( *certificates, s2 );
1300           strcat( *certificates, ")" );
1301           ++nFound;
1302         }
1303       }
1304     }
1305   }
1306   gpgme_op_keylist_end( ctx );
1307   gpgme_release (ctx);
1308
1309   return ( 0 < nFound );
1310 }
1311
1312 bool encryptMessage( const char*  cleartext,
1313                      const char** ciphertext,
1314                      const size_t* cipherLen,
1315                      const char*  certificate,
1316                      struct StructuringInfo* structuring,
1317                      int* errId,
1318                      char** errTxt )
1319 {
1320   GpgmeCtx ctx;
1321   GpgmeError err;
1322   GpgmeData gCiphertext, gPlaintext;
1323   GpgmeRecipients rset;
1324   char*  rCiph = 0;
1325   bool   bOk   = false;
1326
1327   init_StructuringInfo( structuring );
1328
1329   gpgme_new (&ctx);
1330   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1331
1332   gpgme_set_armor (ctx, __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ? 0 : 1);
1333   /*  gpgme_set_textmode (ctx, 1); */
1334
1335   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1336                             1+strlen( cleartext ), 1 );
1337   err = gpgme_data_new ( &gCiphertext );
1338
1339   gpgme_recipients_new (&rset);
1340
1341   /*
1342   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1343   {
1344     gpgme_recipients_add_name (rset,
1345       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE" );
1346
1347     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1348   }
1349   else
1350   */
1351   {
1352     const char* p = certificate;
1353     char* tok;
1354     while( (tok = nextAddress( &p ) ) != 0 ) {
1355       gpgme_recipients_add_name (rset, tok );
1356       fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
1357       free(tok);
1358     }
1359   }
1360
1361   /* PENDING(g10) Implement this
1362      Possible values: RSA = 1, SHA1 = 2, TripleDES = 3
1363      gpgme_set_encryption_algorithm( ctx, config.encryptionAlgorithm );
1364
1365      -> Your are mixing public key and symmetric algorithms.  The
1366      latter may be configured but the sphix specifications do opnly
1367      allow 3-DES so this is not nothing we need to do.  The proper way
1368      to select the symmetric algorithm is anyway by looking at the
1369      capabilities of the certificate because this is the only way to
1370      know what the recipient can accept. [wk 2002-03-23]
1371
1372      PENDING(g10) Implement this
1373      gpgme_set_encryption_check_certificate_path(
1374      config.checkCertificatePath )
1375
1376      PENDING(g10) Implement this
1377      gpgme_set_encryption_check_certificate_path_to_root(
1378      config.checkEncryptionCertificatePathToRoot )
1379
1380      -> Not checking a certificate up to the ROOT CA is dangerous and
1381      stupid. There is no need for those options.  [wk 2002-03-23] */
1382
1383
1384
1385   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1386   if( err ) {
1387     fprintf( stderr, "\ngpgme_op_encrypt() returned this error code:  %i\n\n", err );
1388     if( errId )
1389       *errId = err;
1390     if( errTxt ) {
1391       const char* _errTxt = gpgme_strerror( err );
1392       *errTxt = malloc( strlen( _errTxt ) + 1 );
1393       if( *errTxt )
1394         strcpy(*errTxt, _errTxt );
1395     }
1396   }
1397
1398   gpgme_recipients_release (rset);
1399   gpgme_data_release (gPlaintext);
1400
1401   if( !err ) {
1402     if( __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ) {
1403       *ciphertext = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
1404       bOk = true;
1405     }
1406     else {
1407       rCiph = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
1408       *ciphertext = malloc( *cipherLen + 1 );
1409       if( *ciphertext ) {
1410         if( *cipherLen ) {
1411           bOk = true;
1412           strncpy((char*)*ciphertext, rCiph, *cipherLen );
1413         }
1414         ((char*)(*ciphertext))[*cipherLen] = 0;
1415       }
1416       free( rCiph );
1417     }
1418   }
1419   else {
1420     gpgme_data_release ( gCiphertext );
1421     *ciphertext = 0;
1422     /* error handling is missing: if only one untrusted key was found
1423       (or none at all), gpg won't sign the message.  (hier fehlt eine
1424       Fehlerbehandlung: fuer einen Recipient nur ein untrusted key
1425       (oder gar keiner) gefunden wurde, verweigert gpg das signieren.)
1426     */
1427   }
1428
1429   gpgme_release (ctx);
1430
1431   fflush( stderr );
1432
1433   if( bOk && structuring ) {
1434     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1435     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1436     if( structuring->makeMimeObject ) {
1437       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1438       storeNewCharPtr( &structuring->contentTypeMain,
1439                        GPGMEPLUG_ENC_CTYPE_MAIN );
1440       storeNewCharPtr( &structuring->contentDispMain,
1441                        GPGMEPLUG_ENC_CDISP_MAIN );
1442       storeNewCharPtr( &structuring->contentTEncMain,
1443                        GPGMEPLUG_ENC_CTENC_MAIN );
1444       if( structuring->makeMultiMime ) {
1445         storeNewCharPtr( &structuring->contentTypeVersion,
1446                          GPGMEPLUG_ENC_CTYPE_VERSION );
1447         storeNewCharPtr( &structuring->contentDispVersion,
1448                          GPGMEPLUG_ENC_CDISP_VERSION );
1449         storeNewCharPtr( &structuring->contentTEncVersion,
1450                          GPGMEPLUG_ENC_CTENC_VERSION );
1451         storeNewCharPtr( &structuring->bodyTextVersion,
1452                          GPGMEPLUG_ENC_BTEXT_VERSION );
1453         storeNewCharPtr( &structuring->contentTypeCode,
1454                          GPGMEPLUG_ENC_CTYPE_CODE );
1455         storeNewCharPtr( &structuring->contentDispCode,
1456                          GPGMEPLUG_ENC_CDISP_CODE );
1457         storeNewCharPtr( &structuring->contentTEncCode,
1458                          GPGMEPLUG_ENC_CTENC_CODE );
1459       }
1460     } else {
1461       storeNewCharPtr( &structuring->flatTextPrefix,
1462                        GPGMEPLUG_ENC_FLAT_PREFIX );
1463       storeNewCharPtr( &structuring->flatTextSeparator,
1464                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1465       storeNewCharPtr( &structuring->flatTextPostfix,
1466                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1467     }
1468   }
1469   return bOk;
1470 }
1471
1472
1473 bool encryptAndSignMessage( const char* cleartext,
1474                             const char** ciphertext,
1475                             const char* certificate,
1476                             struct StructuringInfo* structuring )
1477 {
1478   bool bOk;
1479
1480   init_StructuringInfo( structuring );
1481
1482   bOk = false;
1483
1484   /* implementation of this function is still missing */
1485
1486   if( bOk && structuring ) {
1487     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1488     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1489     if( structuring->makeMimeObject ) {
1490       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1491       storeNewCharPtr( &structuring->contentTypeMain,
1492                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1493       storeNewCharPtr( &structuring->contentDispMain,
1494                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1495       storeNewCharPtr( &structuring->contentTEncMain,
1496                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1497       if( structuring->makeMultiMime ) {
1498         storeNewCharPtr( &structuring->contentTypeVersion,
1499                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1500         storeNewCharPtr( &structuring->contentDispVersion,
1501                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1502         storeNewCharPtr( &structuring->contentTEncVersion,
1503                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1504         storeNewCharPtr( &structuring->bodyTextVersion,
1505                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1506         storeNewCharPtr( &structuring->contentTypeCode,
1507                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1508         storeNewCharPtr( &structuring->contentDispCode,
1509                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1510         storeNewCharPtr( &structuring->contentTEncCode,
1511                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1512       }
1513     } else {
1514       storeNewCharPtr( &structuring->flatTextPrefix,
1515                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1516       storeNewCharPtr( &structuring->flatTextSeparator,
1517                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1518       storeNewCharPtr( &structuring->flatTextPostfix,
1519                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1520     }
1521   }
1522   return bOk;
1523 }
1524
1525
1526 bool decryptMessage( const char* ciphertext,
1527                      bool        cipherIsBinary,
1528                      int         cipherLen,
1529                      const char** cleartext,
1530                      const char* certificate )
1531 {
1532   GpgmeCtx ctx;
1533   GpgmeError err;
1534   GpgmeData gCiphertext, gPlaintext;
1535   size_t rCLen = 0;
1536   char*  rCiph = 0;
1537   bool bOk = false;
1538
1539   if( !ciphertext )
1540     return false;
1541
1542   err = gpgme_new (&ctx);
1543   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1544   
1545   gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
1546   /*  gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */
1547
1548   /*
1549   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1550                            1+strlen( ciphertext ), 1 ); */
1551   gpgme_data_new_from_mem( &gCiphertext,
1552                            ciphertext,
1553                            cipherIsBinary
1554                            ? cipherLen
1555                            : strlen( ciphertext ),
1556                            1 );
1557
1558   gpgme_data_new( &gPlaintext );
1559
1560   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1561   gpgme_data_release( gCiphertext );
1562
1563   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1564
1565   *cleartext = malloc( rCLen + 1 );
1566   if( *cleartext ) {
1567       if( rCLen ) {
1568           bOk = true;
1569           strncpy((char*)*cleartext, rCiph, rCLen );
1570       }
1571       ((char*)(*cleartext))[rCLen] = 0;
1572   }
1573
1574   free( rCiph );
1575   gpgme_release( ctx );
1576   return bOk;
1577 }
1578
1579 bool decryptAndCheckMessage( const char* ciphertext,
1580           const char** cleartext, const char* certificate,
1581           struct SignatureMetaData* sigmeta ){ return true; }
1582
1583
1584 const char* requestCertificateDialog(){ return 0; }
1585
1586 bool requestDecentralCertificate( const char* certparms, 
1587                                   char** generatedKey, int* length )
1588 {
1589     GpgmeError err;
1590     GpgmeCtx ctx;
1591     GpgmeData pub;
1592     int len;
1593
1594     err = gpgme_data_new (&pub);
1595     fprintf( stderr,  "1: gpgme returned %d\n", err );
1596     if( err != GPGME_No_Error )
1597         return false;
1598
1599     err = gpgme_new (&ctx);
1600     fprintf( stderr,  "2: gpgme returned %d\n", err );
1601     if( err != GPGME_No_Error ) {
1602         gpgme_data_release( pub );
1603         return false;
1604     }
1605
1606     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
1607     // Don't ASCII-armor, the MUA will use base64 encoding
1608     //    gpgme_set_armor (ctx, 1);
1609     err = gpgme_op_genkey (ctx, certparms, pub, NULL );
1610     fprintf( stderr,  "3: gpgme returned %d\n", err );
1611     if( err != GPGME_No_Error ) {
1612         gpgme_data_release( pub );
1613         gpgme_release( ctx );
1614         return false;
1615     }
1616
1617     gpgme_release (ctx);
1618     *generatedKey = gpgme_data_release_and_get_mem (pub, &len);
1619     *length = len;
1620
1621     /* The buffer generatedKey contains the LEN bytes you want */
1622     // Caller is responsible for freeing
1623     return true;
1624 }
1625
1626 bool requestCentralCertificateAndPSE( const char* name,
1627           const char* email, const char* organization, const char* department,
1628           const char* ca_address ){ return true; }
1629
1630 bool createPSE(){ return true; }
1631
1632 bool registerCertificate( const char* certificate ){ return true; }
1633
1634 bool requestCertificateProlongation( const char* certificate,
1635                                      const char* ca_address ){ return true; }
1636
1637 const char* certificateChain(){ return 0; }
1638
1639 bool deleteCertificate( const char* certificate ){ return true; }
1640
1641 bool archiveCertificate( const char* certificate ){ return true; }
1642
1643
1644 const char* displayCRL(){ return 0; }
1645
1646 void updateCRL(){}