6231523c3d4d194f82970927daeebd6e31478b81
[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   GpgmeKey rKey;
899   GpgmeData data,  sig;
900   char* rSig  = 0;
901   bool  bOk   = false;
902   int sendCerts = 1;
903
904   init_StructuringInfo( structuring );
905
906   if( !ciphertext )
907     return false;
908
909   err = gpgme_new (&ctx);
910   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
911
912   gpgme_set_armor (ctx, __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ? 0 : 1);
913   /*  gpgme_set_textmode (ctx, 1); */
914
915   switch ( config.sendCertificates ) {
916     case SendCert_undef:
917       break;
918     case SendCert_DontSend:
919       sendCerts = 0;
920       break;
921     case SendCert_SendOwn:
922       sendCerts = 1;
923       break;
924     case SendCert_SendChainWithoutRoot:
925       sendCerts = -2;
926       break;
927     case SendCert_SendChainWithRoot:
928       sendCerts = -1;
929       break;
930     default:
931       sendCerts = 0;
932       break;
933   }
934   gpgme_set_include_certs (ctx, sendCerts);
935
936   /* select the signer's key if provided */
937   if (certificate != 0) {
938       err = gpgme_op_keylist_start(ctx, certificate, 0);
939       if (err == GPGME_No_Error) {
940           /* we only support one signer for now */
941           err = gpgme_op_keylist_next(ctx, &rKey);
942           if (err == GPGME_No_Error) {
943               /* clear existing signers */
944               gpgme_signers_clear(ctx);
945               /* set the signing key */
946               gpgme_signers_add(ctx, rKey);
947           }
948           gpgme_op_keylist_end(ctx);
949       }
950   }
951
952   /* PENDING(g10) Implement this
953
954      gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm )
955      --> This does not make sense.  The algorithm is a property of
956      the certificate used [wk 2002-03-23] */
957
958   gpgme_data_new_from_mem (&data, cleartext,
959                             strlen( cleartext ), 1 );
960   gpgme_data_new ( &sig );
961   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
962
963   if ( err == GPGME_No_Error ) {
964     if( __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ) {
965       *ciphertext = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
966       bOk = true;
967     }
968     else {
969       rSig = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
970       *ciphertext = malloc( *cipherLen + 1 );
971       if( *ciphertext ) {
972         if( *cipherLen ) {
973           bOk = true;
974           strncpy((char*)*ciphertext, rSig, *cipherLen );
975         }
976         (*ciphertext)[*cipherLen] = '\0';
977       }
978       free( rSig );
979     }
980   }
981   else {
982     gpgme_data_release( sig );
983 /*
984 *ciphertext = malloc( 70 );
985 strcpy((char*)*ciphertext, "xyz\nsig-dummy\nzyx" );
986 (*ciphertext)[17] = '\0';
987 err = 0;
988 {
989 */
990     *ciphertext = 0;
991     fprintf( stderr, "\n\n    gpgme_op_sign() returned this error code:  %i\n\n", err );
992     if( errId )
993       *errId = err;
994     if( errTxt ) {
995       const char* _errTxt = gpgme_strerror( err );
996       *errTxt = malloc( strlen( _errTxt ) + 1 );
997       if( *errTxt )
998         strcpy(*errTxt, _errTxt );
999     }
1000 /*
1001 }
1002 */
1003   }
1004   gpgme_data_release( data );
1005   gpgme_release (ctx);
1006
1007   if( bOk && structuring ) {
1008     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
1009     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
1010     if( structuring->makeMimeObject ) {
1011       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
1012       storeNewCharPtr( &structuring->contentTypeMain,
1013                        GPGMEPLUG_SIGN_CTYPE_MAIN );
1014       storeNewCharPtr( &structuring->contentDispMain,
1015                        GPGMEPLUG_SIGN_CDISP_MAIN );
1016       storeNewCharPtr( &structuring->contentTEncMain,
1017                        GPGMEPLUG_SIGN_CTENC_MAIN );
1018       if( structuring->makeMultiMime ) {
1019         storeNewCharPtr( &structuring->contentTypeVersion,
1020                          GPGMEPLUG_SIGN_CTYPE_VERSION );
1021         storeNewCharPtr( &structuring->contentDispVersion,
1022                          GPGMEPLUG_SIGN_CDISP_VERSION );
1023         storeNewCharPtr( &structuring->contentTEncVersion,
1024                          GPGMEPLUG_SIGN_CTENC_VERSION );
1025         storeNewCharPtr( &structuring->bodyTextVersion,
1026                          GPGMEPLUG_SIGN_BTEXT_VERSION );
1027         storeNewCharPtr( &structuring->contentTypeCode,
1028                          GPGMEPLUG_SIGN_CTYPE_CODE );
1029         storeNewCharPtr( &structuring->contentDispCode,
1030                          GPGMEPLUG_SIGN_CDISP_CODE );
1031         storeNewCharPtr( &structuring->contentTEncCode,
1032                          GPGMEPLUG_SIGN_CTENC_CODE );
1033       }
1034     } else {
1035       storeNewCharPtr( &structuring->flatTextPrefix,
1036                        GPGMEPLUG_SIGN_FLAT_PREFIX );
1037       storeNewCharPtr( &structuring->flatTextSeparator,
1038                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
1039       storeNewCharPtr( &structuring->flatTextPostfix,
1040                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
1041     }
1042   }
1043   return bOk;
1044 }
1045
1046
1047 static const char*
1048 sig_status_to_string( GpgmeSigStat status )
1049 {
1050   const char *result;
1051
1052   switch (status) {
1053     case GPGME_SIG_STAT_NONE:
1054       result = "Oops: Signature not verified";
1055       break;
1056     case GPGME_SIG_STAT_NOSIG:
1057       result = "No signature found";
1058       break;
1059     case GPGME_SIG_STAT_GOOD:
1060       result = "Good signature";
1061       break;
1062     case GPGME_SIG_STAT_BAD:
1063       result = "BAD signature";
1064       break;
1065     case GPGME_SIG_STAT_NOKEY:
1066       result = "No public key to verify the signature";
1067       break;
1068     case GPGME_SIG_STAT_ERROR:
1069       result = "Error verifying the signature";
1070       break;
1071     case GPGME_SIG_STAT_DIFF:
1072       result = "Different results for signatures";
1073       break;
1074     default:
1075       result = "Error: Unknown status";
1076       break;
1077   }
1078
1079   return result;
1080 }
1081
1082
1083 bool checkMessageSignature( char** cleartext,
1084                             const char* signaturetext,
1085                             bool signatureIsBinary,
1086                             int signatureLen,
1087                             struct SignatureMetaData* sigmeta )
1088 {
1089   GpgmeCtx ctx;
1090   GpgmeSigStat status;
1091   GpgmeData datapart, sigpart;
1092   char* rClear = 0;
1093   size_t clearLen;
1094   GpgmeError err;
1095   GpgmeKey key;
1096   time_t created;
1097   int sig_idx = 0;
1098   const char* statusStr;
1099   const char* fpr;
1100   bool isOpaqueSigned;
1101
1102   if( !cleartext ) {
1103     if( sigmeta )
1104       storeNewCharPtr( &sigmeta->status,
1105                         __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
1106
1107     return false;
1108   }
1109
1110   isOpaqueSigned = !*cleartext;
1111
1112   gpgme_new( &ctx );
1113   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1114   gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
1115   /*  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */
1116
1117   if( isOpaqueSigned )
1118     gpgme_data_new( &datapart );
1119   else
1120     gpgme_data_new_from_mem( &datapart, *cleartext,
1121                              strlen( *cleartext ), 1 );
1122
1123   gpgme_data_new_from_mem( &sigpart,
1124                            signaturetext,
1125                            signatureIsBinary
1126                            ? signatureLen
1127                            : strlen( signaturetext ),
1128                            1 );
1129
1130   gpgme_op_verify( ctx, sigpart, datapart, &status );
1131
1132   if( isOpaqueSigned ) {
1133     rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
1134     *cleartext = malloc( clearLen + 1 );
1135     if( *cleartext ) {
1136       if( clearLen )
1137         strncpy(*cleartext, rClear, clearLen );
1138       (*cleartext)[clearLen] = '\0';
1139     }
1140     free( rClear );
1141   }
1142   else
1143     gpgme_data_release( datapart );
1144
1145   gpgme_data_release( sigpart );
1146
1147   /* Provide information in the sigmeta struct */
1148   /* the status string */
1149   statusStr = sig_status_to_string( status );
1150   sigmeta->status = malloc( strlen( statusStr ) + 1 );
1151   if( sigmeta->status ) {
1152     strcpy( sigmeta->status, statusStr );
1153     sigmeta->status[strlen( statusStr )] = '\0';
1154   } else
1155     ; /* nothing to do, is already 0 */
1156
1157   /* Extended information for any number of signatures. */
1158   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
1159   sigmeta->extended_info = 0;
1160   while( fpr != NULL ) {
1161     struct tm* ctime_val;
1162     const char* sig_status;
1163
1164     void* realloc_return = realloc( sigmeta->extended_info,
1165                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1166     if( realloc_return ) {
1167       sigmeta->extended_info = realloc_return;
1168
1169       /* clear the data area */
1170       memset( &sigmeta->extended_info[sig_idx], 0, sizeof (struct SignatureMetaDataExtendedInfo) );
1171
1172       /* the creation time */
1173       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1174       if( sigmeta->extended_info[sig_idx].creation_time ) {
1175         ctime_val = localtime( &created );
1176         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1177                 ctime_val, sizeof( struct tm ) );
1178       }
1179
1180       sigmeta->extended_info[sig_idx].validity = GPGME_VALIDITY_UNKNOWN;
1181
1182       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1183
1184       
1185       
1186
1187       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1188       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1189         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1190         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1191       }
1192
1193
1194
1195       if ( false && err == GPGME_No_Error) {
1196         const char* attr_string;
1197         unsigned long attr_ulong;
1198
1199         /* extract key identidy */
1200         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_KEYID, 0, 0);
1201         if (attr_string != 0)
1202             storeNewCharPtr( &sigmeta->extended_info[sig_idx].keyid, attr_string );
1203
1204         /* extract finger print */
1205         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_FPR, 0, 0);
1206         if (attr_string != 0)
1207             storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint,
1208                             attr_string );
1209
1210         /* algorithms useable with this key */
1211         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_ALGO, 0, 0);
1212         if (attr_string != 0)
1213             storeNewCharPtr( &sigmeta->extended_info[sig_idx].algo,
1214                             attr_string );
1215         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_ALGO, 0, 0);
1216         sigmeta->extended_info[sig_idx].algo_num = attr_ulong;
1217
1218         /* extract key validity */
1219         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_VALIDITY, 0, 0);
1220         sigmeta->extended_info[sig_idx].validity = attr_ulong;
1221
1222         /* extract user id, according to the documentation it's representable
1223         * as a number, but it seems that it also has a string representation
1224         */
1225         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, 0, 0);
1226         if (attr_string != 0)
1227             storeNewCharPtr( &sigmeta->extended_info[sig_idx].userid,
1228                             attr_string );
1229         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_USERID, 0, 0);
1230         sigmeta->extended_info[sig_idx].userid_num = attr_ulong;
1231
1232         /* extract the length */
1233         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_LEN, 0, 0);
1234         sigmeta->extended_info[sig_idx].keylen = attr_ulong;
1235
1236         /* extract the creation time of the key */
1237         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_CREATED, 0, 0);
1238         sigmeta->extended_info[sig_idx].key_created = attr_ulong;
1239
1240         /* extract the expiration time of the key */
1241         attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_EXPIRE, 0, 0);
1242         sigmeta->extended_info[sig_idx].key_expires = attr_ulong;
1243
1244         /* extract user name */
1245         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, 0, 0);
1246         if (attr_string != 0)
1247             storeNewCharPtr( &sigmeta->extended_info[sig_idx].name,
1248                             attr_string );
1249
1250         /* extract email */
1251         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_EMAIL, 0, 0);
1252         if (attr_string != 0)
1253             storeNewCharPtr( &sigmeta->extended_info[sig_idx].email,
1254                             attr_string );
1255
1256         /* extract the comment */
1257         attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_COMMENT, 0, 0);
1258         if (attr_string != 0)
1259             storeNewCharPtr( &sigmeta->extended_info[sig_idx].comment,
1260                             attr_string );
1261       }
1262
1263       sig_status = sig_status_to_string( status );
1264       storeNewCharPtr( &sigmeta->extended_info[sig_idx].status_text,
1265                        sig_status );
1266
1267     } else
1268       break; /* if allocation fails once, it isn't likely to
1269                 succeed the next time either */
1270
1271     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1272   }
1273   sigmeta->extended_info_count = sig_idx;
1274   sigmeta->nota_xml = gpgme_get_notation( ctx );
1275   sigmeta->status_code = status;
1276
1277   gpgme_release( ctx );
1278   return ( status == GPGME_SIG_STAT_GOOD );
1279 }
1280
1281 bool storeCertificatesFromMessage(
1282         const char* ciphertext ){ return true; }
1283
1284
1285 /* returns address if address doesn't contain a <xxx> part
1286  * else it returns a new string xxx and frees address
1287  */
1288 static char* parseAddress( char* address )
1289 {
1290   char* result = address;
1291   char* i;
1292   char* j;
1293   if( !result ) return result;
1294   i = index( address, '<' );
1295   if( i ) {
1296     j = index( i+1, '>' );
1297     if( j == NULL ) j = address+strlen(address);
1298     result = malloc( j-i );
1299     strncpy( result, i+1, j-i-1 );
1300     result[j-i-1] = '\0';
1301     free( address );
1302   } else {
1303     i = address;
1304     j = i+strlen(address);
1305   }
1306   {
1307     /* remove surrounding whitespace */
1308     char* k = result+(j-i-1);
1309     char* l = result;
1310     while( isspace( *l ) ) ++l;
1311     while( isspace( *k ) ) --k;
1312     if( l != result || k != result+(j-i-1) ) {
1313       char* result2 = malloc( k-l+2 );
1314       strncpy( result2, l, k-l+1 );
1315       result2[k-l+1] = '\0';
1316       free(result);
1317       result = result2;
1318     }
1319   }
1320   return result;
1321 }
1322
1323 static char* nextAddress( const char** address )
1324 {
1325   const char *start = *address;
1326   char* result = NULL;
1327   int quote = 0;
1328   int comment = 0;
1329   int found = 0;
1330   if( *address == NULL ) return NULL;
1331   while( **address ) {
1332
1333     switch( **address ) {
1334     case '\\': /* escaped character */
1335       ++(*address);
1336       break;
1337     case '"':
1338       if( comment == 0 ) {
1339         if( quote > 0 ) --quote;
1340         else ++quote;
1341       }
1342       break;
1343     case '(': /* comment start */
1344       if( quote == 0 ) ++comment;
1345       break;
1346     case ')': /* comment end */
1347       if( quote == 0 ) --comment;
1348       break;
1349     case '\0':
1350     case '\1': /* delimiter */
1351       if( quote == 0 && comment == 0 ) {
1352         found = 1;
1353       }
1354       break;
1355     }
1356     ++(*address);
1357     if( found ) break;
1358   }
1359   if( found || **address == 0 ) {
1360     size_t len;
1361     len = *address - start;
1362     if( len > 0 ) {
1363       if( **address != 0 ) --len;
1364       result = malloc( len*sizeof(char)+1 );
1365       strncpy( result, start, len );
1366       result[len] = '\0';
1367     }
1368   }
1369   return parseAddress(result);
1370 }
1371
1372 /*
1373   Find all certificate for a given addressee and return them in a
1374   '\1' separated list.
1375   NOTE: The certificate parameter must point to an allready allocated
1376   block of memory which is large enough to hold the complete list.
1377 */
1378 bool findCertificates( const char* addressee, char** certificates )
1379 {
1380   GpgmeCtx ctx;
1381   GpgmeError err;
1382   GpgmeKey rKey;
1383   const char *s;
1384   const char *s2;
1385   int nFound = 0;
1386
1387   strcpy( *certificates, "" );
1388
1389   gpgme_new (&ctx);
1390   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1391
1392   err = gpgme_op_keylist_start(ctx, addressee, 0);
1393   while( GPGME_No_Error == err ) {
1394     err = gpgme_op_keylist_next(ctx, &rKey);
1395     if( GPGME_No_Error == err ) {
1396       s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
1397       if( s ) {
1398         s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
1399         if( s2 ) {
1400           if( nFound )
1401             strcat(*certificates,"\1" );
1402           strcat( *certificates, s );
1403           strcat( *certificates, "    (" );
1404           strcat( *certificates, s2 );
1405           strcat( *certificates, ")" );
1406           ++nFound;
1407         }
1408       }
1409     }
1410   }
1411   gpgme_op_keylist_end( ctx );
1412   gpgme_release (ctx);
1413
1414   return ( 0 < nFound );
1415 }
1416
1417 bool encryptMessage( const char*  cleartext,
1418                      const char** ciphertext,
1419                      const size_t* cipherLen,
1420                      const char*  certificate,
1421                      struct StructuringInfo* structuring,
1422                      int* errId,
1423                      char** errTxt )
1424 {
1425   GpgmeCtx ctx;
1426   GpgmeError err;
1427   GpgmeData gCiphertext, gPlaintext;
1428   GpgmeRecipients rset;
1429   char*  rCiph = 0;
1430   bool   bOk   = false;
1431
1432   init_StructuringInfo( structuring );
1433
1434   gpgme_new (&ctx);
1435   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1436
1437   gpgme_set_armor (ctx, __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ? 0 : 1);
1438   /*  gpgme_set_textmode (ctx, 1); */
1439
1440   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1441                             1+strlen( cleartext ), 1 );
1442   err = gpgme_data_new ( &gCiphertext );
1443
1444   gpgme_recipients_new (&rset);
1445
1446   /*
1447   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1448   {
1449     gpgme_recipients_add_name (rset,
1450       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE" );
1451
1452     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1453   }
1454   else
1455   */
1456   {
1457     const char* p = certificate;
1458     char* tok;
1459     while( (tok = nextAddress( &p ) ) != 0 ) {
1460       gpgme_recipients_add_name (rset, tok );
1461       fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
1462       free(tok);
1463     }
1464   }
1465
1466   /* PENDING(g10) Implement this
1467      Possible values: RSA = 1, SHA1 = 2, TripleDES = 3
1468      gpgme_set_encryption_algorithm( ctx, config.encryptionAlgorithm );
1469
1470      -> Your are mixing public key and symmetric algorithms.  The
1471      latter may be configured but the sphix specifications do opnly
1472      allow 3-DES so this is not nothing we need to do.  The proper way
1473      to select the symmetric algorithm is anyway by looking at the
1474      capabilities of the certificate because this is the only way to
1475      know what the recipient can accept. [wk 2002-03-23]
1476
1477      PENDING(g10) Implement this
1478      gpgme_set_encryption_check_certificate_path(
1479      config.checkCertificatePath )
1480
1481      PENDING(g10) Implement this
1482      gpgme_set_encryption_check_certificate_path_to_root(
1483      config.checkEncryptionCertificatePathToRoot )
1484
1485      -> Not checking a certificate up to the ROOT CA is dangerous and
1486      stupid. There is no need for those options.  [wk 2002-03-23] */
1487
1488
1489
1490   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1491   if( err ) {
1492     fprintf( stderr, "\ngpgme_op_encrypt() returned this error code:  %i\n\n", err );
1493     if( errId )
1494       *errId = err;
1495     if( errTxt ) {
1496       const char* _errTxt = gpgme_strerror( err );
1497       *errTxt = malloc( strlen( _errTxt ) + 1 );
1498       if( *errTxt )
1499         strcpy(*errTxt, _errTxt );
1500     }
1501   }
1502
1503   gpgme_recipients_release (rset);
1504   gpgme_data_release (gPlaintext);
1505
1506   if( err == GPGME_No_Error ) {
1507     if( __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ) {
1508       *ciphertext = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
1509       bOk = true;
1510     }
1511     else {
1512       rCiph = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
1513       *ciphertext = malloc( *cipherLen + 1 );
1514       if( *ciphertext ) {
1515         if( *cipherLen ) {
1516           bOk = true;
1517           strncpy((char*)*ciphertext, rCiph, *cipherLen );
1518         }
1519         ((char*)(*ciphertext))[*cipherLen] = 0;
1520       }
1521       free( rCiph );
1522     }
1523   }
1524   else {
1525     gpgme_data_release ( gCiphertext );
1526     *ciphertext = 0;
1527     /* error handling is missing: if only one untrusted key was found
1528       (or none at all), gpg won't sign the message.  (hier fehlt eine
1529       Fehlerbehandlung: fuer einen Recipient nur ein untrusted key
1530       (oder gar keiner) gefunden wurde, verweigert gpg das signieren.)
1531     */
1532   }
1533
1534   gpgme_release (ctx);
1535
1536   fflush( stderr );
1537
1538   if( bOk && structuring ) {
1539     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1540     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1541     if( structuring->makeMimeObject ) {
1542       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1543       storeNewCharPtr( &structuring->contentTypeMain,
1544                        GPGMEPLUG_ENC_CTYPE_MAIN );
1545       storeNewCharPtr( &structuring->contentDispMain,
1546                        GPGMEPLUG_ENC_CDISP_MAIN );
1547       storeNewCharPtr( &structuring->contentTEncMain,
1548                        GPGMEPLUG_ENC_CTENC_MAIN );
1549       if( structuring->makeMultiMime ) {
1550         storeNewCharPtr( &structuring->contentTypeVersion,
1551                          GPGMEPLUG_ENC_CTYPE_VERSION );
1552         storeNewCharPtr( &structuring->contentDispVersion,
1553                          GPGMEPLUG_ENC_CDISP_VERSION );
1554         storeNewCharPtr( &structuring->contentTEncVersion,
1555                          GPGMEPLUG_ENC_CTENC_VERSION );
1556         storeNewCharPtr( &structuring->bodyTextVersion,
1557                          GPGMEPLUG_ENC_BTEXT_VERSION );
1558         storeNewCharPtr( &structuring->contentTypeCode,
1559                          GPGMEPLUG_ENC_CTYPE_CODE );
1560         storeNewCharPtr( &structuring->contentDispCode,
1561                          GPGMEPLUG_ENC_CDISP_CODE );
1562         storeNewCharPtr( &structuring->contentTEncCode,
1563                          GPGMEPLUG_ENC_CTENC_CODE );
1564       }
1565     } else {
1566       storeNewCharPtr( &structuring->flatTextPrefix,
1567                        GPGMEPLUG_ENC_FLAT_PREFIX );
1568       storeNewCharPtr( &structuring->flatTextSeparator,
1569                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1570       storeNewCharPtr( &structuring->flatTextPostfix,
1571                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1572     }
1573   }
1574   return bOk;
1575 }
1576
1577
1578 bool encryptAndSignMessage( const char* cleartext,
1579                             const char** ciphertext,
1580                             const char* certificate,
1581                             struct StructuringInfo* structuring )
1582 {
1583   bool bOk;
1584
1585   init_StructuringInfo( structuring );
1586
1587   bOk = false;
1588
1589   /* implementation of this function is still missing */
1590
1591   if( bOk && structuring ) {
1592     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1593     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1594     if( structuring->makeMimeObject ) {
1595       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1596       storeNewCharPtr( &structuring->contentTypeMain,
1597                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1598       storeNewCharPtr( &structuring->contentDispMain,
1599                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1600       storeNewCharPtr( &structuring->contentTEncMain,
1601                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1602       if( structuring->makeMultiMime ) {
1603         storeNewCharPtr( &structuring->contentTypeVersion,
1604                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1605         storeNewCharPtr( &structuring->contentDispVersion,
1606                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1607         storeNewCharPtr( &structuring->contentTEncVersion,
1608                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1609         storeNewCharPtr( &structuring->bodyTextVersion,
1610                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1611         storeNewCharPtr( &structuring->contentTypeCode,
1612                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1613         storeNewCharPtr( &structuring->contentDispCode,
1614                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1615         storeNewCharPtr( &structuring->contentTEncCode,
1616                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1617       }
1618     } else {
1619       storeNewCharPtr( &structuring->flatTextPrefix,
1620                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1621       storeNewCharPtr( &structuring->flatTextSeparator,
1622                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1623       storeNewCharPtr( &structuring->flatTextPostfix,
1624                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1625     }
1626   }
1627   return bOk;
1628 }
1629
1630
1631 bool decryptMessage( const char* ciphertext,
1632                      bool        cipherIsBinary,
1633                      int         cipherLen,
1634                      const char** cleartext,
1635                      const char* certificate )
1636 {
1637   GpgmeCtx ctx;
1638   GpgmeError err;
1639   GpgmeData gCiphertext, gPlaintext;
1640   size_t rCLen = 0;
1641   char*  rCiph = 0;
1642   bool bOk = false;
1643
1644   if( !ciphertext )
1645     return false;
1646
1647   err = gpgme_new (&ctx);
1648   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1649   
1650   gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
1651   /*  gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */
1652
1653   /*
1654   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1655                            1+strlen( ciphertext ), 1 ); */
1656   gpgme_data_new_from_mem( &gCiphertext,
1657                            ciphertext,
1658                            cipherIsBinary
1659                            ? cipherLen
1660                            : strlen( ciphertext ),
1661                            1 );
1662
1663   gpgme_data_new( &gPlaintext );
1664
1665   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1666   gpgme_data_release( gCiphertext );
1667
1668   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1669
1670   *cleartext = malloc( rCLen + 1 );
1671   if( *cleartext ) {
1672       if( rCLen ) {
1673           bOk = true;
1674           strncpy((char*)*cleartext, rCiph, rCLen );
1675       }
1676       ((char*)(*cleartext))[rCLen] = 0;
1677   }
1678
1679   free( rCiph );
1680   gpgme_release( ctx );
1681   return bOk;
1682 }
1683
1684 bool decryptAndCheckMessage( const char* ciphertext,
1685           const char** cleartext, const char* certificate,
1686           struct SignatureMetaData* sigmeta ){ return true; }
1687
1688
1689 const char* requestCertificateDialog(){ return 0; }
1690
1691 bool requestDecentralCertificate( const char* certparms, 
1692                                   char** generatedKey, int* length )
1693 {
1694     GpgmeError err;
1695     GpgmeCtx ctx;
1696     GpgmeData pub;
1697     int len;
1698
1699     err = gpgme_data_new (&pub);
1700     fprintf( stderr,  "1: gpgme returned %d\n", err );
1701     if( err != GPGME_No_Error )
1702         return false;
1703
1704     err = gpgme_new (&ctx);
1705     fprintf( stderr,  "2: gpgme returned %d\n", err );
1706     if( err != GPGME_No_Error ) {
1707         gpgme_data_release( pub );
1708         return false;
1709     }
1710
1711     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
1712     // Don't ASCII-armor, the MUA will use base64 encoding
1713     //    gpgme_set_armor (ctx, 1);
1714     err = gpgme_op_genkey (ctx, certparms, pub, NULL );
1715     fprintf( stderr,  "3: gpgme returned %d\n", err );
1716     if( err != GPGME_No_Error ) {
1717         gpgme_data_release( pub );
1718         gpgme_release( ctx );
1719         return false;
1720     }
1721
1722     gpgme_release (ctx);
1723     *generatedKey = gpgme_data_release_and_get_mem (pub, &len);
1724     *length = len;
1725
1726     /* The buffer generatedKey contains the LEN bytes you want */
1727     // Caller is responsible for freeing
1728     return true;
1729 }
1730
1731 bool requestCentralCertificateAndPSE( const char* name,
1732           const char* email, const char* organization, const char* department,
1733           const char* ca_address ){ return true; }
1734
1735 bool createPSE(){ return true; }
1736
1737 bool registerCertificate( const char* certificate ){ return true; }
1738
1739 bool requestCertificateProlongation( const char* certificate,
1740                                      const char* ca_address ){ return true; }
1741
1742 const char* certificateChain(){ return 0; }
1743
1744 bool deleteCertificate( const char* certificate ){ return true; }
1745
1746 bool archiveCertificate( const char* certificate ){ return true; }
1747
1748
1749 const char* displayCRL(){ return 0; }
1750
1751 void updateCRL(){}