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