Support for warning when a CRL expires
[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        Another note: OK, OK, we'll handle that in the MUA. You can
358        assume that you only get the email address.
359     */
360     return false; // dummy
361 }
362
363
364 void setNumPINRequests( PinRequests reqMode )
365 {
366   config.numPINRequests = reqMode;
367
368   /* PENDING(g10) Put this value into gpg and make it ask for the pin
369      according to this. Note that there is also
370      setNumPINRequestsInterval() which is only used if reqMode ==
371      PinRequest_AfterMinutes.
372   */
373 }
374
375 PinRequests numPINRequests()
376 {
377   return config.numPINRequests;
378 }
379
380
381
382 void setNumPINRequestsInterval( int interval )
383 {
384   config.numPINRequestsInterval = interval;
385
386   /* PENDING(g10) Put this value into gpg and make it ask for the pin
387      according to this. Note that this should only be used if
388      config.numPINRequests (set with setNumPINRequests()) has the
389      value PinRequest_AfterMinutes.
390   */
391 }
392
393 int numPINRequestsInterval()
394 {
395   return config.numPINRequestsInterval;
396 }
397
398
399
400 void setCheckSignatureCertificatePathToRoot( bool flag )
401 {
402   config.checkSignatureCertificatePathToRoot = flag;
403 }
404
405 bool checkSignatureCertificatePathToRoot()
406 {
407   return config.checkSignatureCertificatePathToRoot;
408 }
409
410 void setSignatureUseCRLs( bool flag )
411 {
412   config.signatureUseCRLs = flag;
413 }
414
415 bool signatureUseCRLs()
416 {
417   return config.signatureUseCRLs;
418 }
419
420
421
422
423
424
425 void setSignatureCertificateExpiryNearWarning( bool flag )
426 {
427   config.signatureCertificateExpiryNearWarning = flag;
428 }
429
430 bool signatureCertificateExpiryNearWarning( void )
431 {
432   return config.signatureCertificateExpiryNearWarning;
433 }
434
435
436 int signatureCertificateDaysLeftToExpiry( const char* certificate )
437 {
438     /* PENDING(g10)
439        Please return the number of days that are left until the
440        certificate specified in the parameter certificate expires.
441     */
442     return 10; // dummy that triggers a warning in the MUA
443 }
444
445
446 void setSignatureCertificateExpiryNearInterval( int interval )
447 {
448   config.signatureCertificateExpiryNearInterval = interval;
449 }
450
451 int signatureCertificateExpiryNearInterval( void )
452 {
453   return config.signatureCertificateExpiryNearInterval;
454 }
455
456 void setCACertificateExpiryNearWarning( bool flag )
457 {
458   config.cACertificateExpiryNearWarning = flag;
459 }
460
461 bool caCertificateExpiryNearWarning( void )
462 {
463   return config.cACertificateExpiryNearWarning;
464 }
465
466 int caCertificateDaysLeftToExpiry( const char* certificate )
467 {
468     /* PENDING(g10)
469        Please return the number of days that are left until the
470        CA certificate for the certificate specified in the parameter
471        certificate expires.
472     */
473     return 10; // dummy that triggers a warning in the MUA
474 }
475
476 void setCACertificateExpiryNearInterval( int interval )
477 {
478   config.cACertificateExpiryNearInterval = interval;
479 }
480
481 int caCertificateExpiryNearInterval( void )
482 {
483   return config.cACertificateExpiryNearInterval;
484 }
485
486 void setRootCertificateExpiryNearWarning( bool flag )
487 {
488   config.rootCertificateExpiryNearWarning = flag;
489 }
490
491 bool rootCertificateExpiryNearWarning( void )
492 {
493   return config.rootCertificateExpiryNearWarning;
494 }
495
496 int rootCertificateDaysLeftToExpiry( const char* certificate )
497 {
498     /* PENDING(g10)
499        Please return the number of days that are left until the
500        root certificate for the certificate specified in the parameter
501        certificate expires.
502     */
503     return 10; // dummy that triggers a warning in the MUA
504 }
505
506
507 void setRootCertificateExpiryNearInterval( int interval )
508 {
509   config.rootCertificateExpiryNearInterval = interval;
510 }
511
512 int rootCertificateExpiryNearInterval( void )
513 {
514   return config.rootCertificateExpiryNearInterval;
515 }
516
517
518
519
520
521
522
523
524 const char* encryptionConfigurationDialog(){ return 0; }
525
526 const char* encryptionAlgorithmDialog(){ return 0; }
527
528 const char* encryptionHandlingDialog(){ return 0; }
529
530 const char* encryptionReceiverDialog(){ return 0; }
531
532 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
533 {
534   config.encryptionAlgorithm = cryptAlg;
535 }
536
537 EncryptionAlgorithm encryptionAlgorithm()
538 {
539   return config.encryptionAlgorithm;
540 }
541
542 void setEncryptEmail( EncryptEmail cryptMode )
543 {
544   config.encryptEmail = cryptMode;
545 }
546
547 EncryptEmail encryptEmail()
548 {
549   return config.encryptEmail;
550 }
551
552
553
554
555
556
557 void setWarnSendUnencrypted( bool flag )
558 {
559   config.warnSendUnencrypted = flag;
560 }
561
562 bool warnSendUnencrypted()
563 {
564   return config.warnSendUnencrypted;
565 }
566
567
568
569
570
571
572
573
574
575 void setSaveMessagesEncrypted( bool flag )
576 {
577   config.saveMessagesEncrypted = flag;
578 }
579
580 bool saveMessagesEncrypted()
581 {
582   return config.saveMessagesEncrypted;
583 }
584
585
586
587
588
589
590
591 void setCheckCertificatePath( bool flag )
592 {
593   config.checkCertificatePath = flag;
594 }
595
596 bool checkCertificatePath()
597 {
598   return config.checkCertificatePath;
599 }
600
601
602
603
604
605
606
607
608 void setCheckEncryptionCertificatePathToRoot( bool flag )
609 {
610   config.checkEncryptionCertificatePathToRoot = flag;
611 }
612
613 bool checkEncryptionCertificatePathToRoot()
614 {
615   return config.checkEncryptionCertificatePathToRoot;
616 }
617
618
619
620
621
622
623
624 void setReceiverCertificateExpiryNearWarning( bool flag )
625 {
626   config.receiverCertificateExpiryNearWarning = flag;
627 }
628
629 bool receiverCertificateExpiryNearWarning()
630 {
631   return config.receiverCertificateExpiryNearWarning;
632 }
633
634 void setReceiverCertificateExpiryNearWarningInterval( int interval )
635 {
636   config.receiverCertificateExpiryNearWarningInterval = interval;
637 }
638
639 int receiverCertificateExpiryNearWarningInterval()
640 {
641   return config.receiverCertificateExpiryNearWarningInterval;
642 }
643
644 void setCertificateInChainExpiryNearWarning( bool flag )
645 {
646   config.certificateInChainExpiryNearWarning = flag;
647 }
648
649 bool certificateInChainExpiryNearWarning()
650 {
651   return config.certificateInChainExpiryNearWarning;
652 }
653
654 void setCertificateInChainExpiryNearWarningInterval( int interval )
655 {
656   config.certificateInChainExpiryNearWarningInterval = interval;
657 }
658
659 int certificateInChainExpiryNearWarningInterval()
660 {
661   return config.certificateInChainExpiryNearWarningInterval;
662 }
663
664 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
665 {
666   config.receiverEmailAddressNotInCertificateWarning = flag;
667 }
668
669 bool receiverEmailAddressNotInCertificateWarning()
670 {
671   return config.receiverEmailAddressNotInCertificateWarning;
672 }
673
674
675
676
677
678
679
680
681 void setEncryptionUseCRLs( bool flag )
682 {
683   config.encryptionUseCRLs = flag;
684
685   /* PENDING(g10) Store this setting in gpgme and use it. If true,
686      every certificate used for encryption should be checked against
687      applicable CRLs.
688   */
689 }
690
691 bool encryptionUseCRLs()
692 {
693   return config.encryptionUseCRLs;
694 }
695
696
697 int encryptionCRLsDaysLeftToExpiry()
698 {
699     /* PENDING(g10)
700        Please return the number of days that are left until the
701        CRL used for encryption expires.
702     */
703     return 10; // dummy that triggers a warning in the MUA
704 }
705
706 void setEncryptionCRLExpiryNearWarning( bool flag )
707 {
708   config.encryptionCRLExpiryNearWarning = flag;
709 }
710
711 bool encryptionCRLExpiryNearWarning()
712 {
713   return config.encryptionCRLExpiryNearWarning;
714 }
715
716 void setEncryptionCRLNearExpiryInterval( int interval )
717 {
718   config.encryptionCRLNearExpiryInterval = interval;
719 }
720
721 int encryptionCRLNearExpiryInterval()
722 {
723   return config.encryptionCRLNearExpiryInterval;
724 }
725
726
727 const char* directoryServiceConfigurationDialog(){ return 0; }
728
729 void appendDirectoryServer( const char* servername,
730                             int         port,
731                             const char* description )
732 {
733   struct DirectoryServer *newServers = NULL;
734   newServers = realloc( config.directoryServers,
735                         (1+config.numDirectoryServers) * sizeof *newServers );
736   if( newServers ) {
737     config.directoryServers = newServers;
738     newServers[ config.numDirectoryServers ].servername =
739       malloc( 1+strlen( servername ) );
740     if( newServers[ config.numDirectoryServers ].servername ) {
741       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
742         servername );
743       newServers[ config.numDirectoryServers ].description =
744         malloc( 1+strlen(  description ) );
745       if( newServers[ config.numDirectoryServers ].description ) {
746         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
747           description );
748         newServers[ config.numDirectoryServers ].port = port;
749         config.numDirectoryServers += 1;
750       }
751     }
752   }
753 }
754
755 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
756 {
757   unsigned int i;
758   int oldSize = config.numDirectoryServers;
759   struct DirectoryServer *newServers = NULL;
760   newServers = calloc ( size, sizeof *newServers );
761   if( newServers ) {
762     for( i=0; i < oldSize; ++i ) {
763       free( (char *)config.directoryServers[i].servername );
764       free( (char *)config.directoryServers[i].description );
765     }
766     free( config.directoryServers );
767     for( i=0; i < size; ++i ) {
768       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
769       if( newServers[ i ].servername ) {
770         strcpy( (char *)newServers[ i ].servername, server[i].servername );
771         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
772         if( newServers[ i ].description ) {
773           strcpy( (char *)newServers[ i ].description, server[i].description );
774           newServers[ i ].port = server[i].port;
775         }
776       }
777     }
778     config.directoryServers = newServers;
779     config.numDirectoryServers = size;
780   }
781 }
782
783 struct DirectoryServer * directoryServers( int* numServers )
784 {
785   if( numServers )
786     *numServers = config.numDirectoryServers;
787   return config.directoryServers;
788 };
789
790 void setCertificateSource( CertificateSource source )
791 {
792   config.certificateSource = source;
793 }
794
795 CertificateSource certificateSource()
796 {
797   return config.certificateSource;
798 }
799
800 void setCRLSource( CertificateSource source )
801 {
802   config.cRLSource = source;
803 }
804
805 CertificateSource crlSource()
806 {
807   return config.cRLSource;
808 }
809
810
811 bool certificateValidity( const char* certificate,
812                           int* level ){ return true; }
813
814
815 void storeNewCharPtr( char** dest, const char* src )
816 {
817   int sLen = strlen( src );
818   *dest = malloc( sLen + 1 );
819   strcpy( *dest, src );
820   (*dest)[sLen] = '\0';
821 }
822
823
824 bool signMessage( const char*  cleartext,
825                   const char** ciphertext,
826                   const char*  certificate,
827                   struct StructuringInfo* structuring )
828 {
829   GpgmeCtx ctx;
830   GpgmeError err;
831   GpgmeData data,  sig;
832   size_t rSLen = 0;
833   char*  rSig  = 0;
834   bool   bOk   = false;
835   int sendCerts = 1;
836
837   init_StructuringInfo( structuring );
838
839   if( !ciphertext )
840     return false;
841
842   err = gpgme_new (&ctx);
843   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
844
845   gpgme_set_armor (ctx, 1);
846   gpgme_set_textmode (ctx, 1);
847
848   switch ( config.sendCertificates ) {
849     case SendCert_undef:
850       break;
851     case SendCert_DontSend:
852       sendCerts = 0;
853       break;
854     case SendCert_SendOwn:
855       sendCerts = 1;
856       break;
857     case SendCert_SendChainWithoutRoot:
858       sendCerts = -2;
859       break;
860     case SendCert_SendChainWithRoot:
861       sendCerts = -1;
862       break;
863     default:
864       sendCerts = 0;
865       break;
866   }
867   gpgme_set_include_certs (ctx, sendCerts);
868   
869   // PENDING(g10) Implement this
870   //gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm );
871
872   gpgme_data_new_from_mem (&data, cleartext,
873                             1+strlen( cleartext ), 1 );
874   gpgme_data_new ( &sig );
875   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
876
877   if (!err) {
878     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
879     *ciphertext = malloc( rSLen + 1 );
880     if( *ciphertext ) {
881       if( rSLen ) {
882         bOk = true;
883         strncpy((char*)*ciphertext, rSig, rSLen );
884       }
885       ((char*)(*ciphertext))[rSLen] = '\0';
886     }
887     free( rSig );
888   }
889   else {
890     gpgme_data_release( sig );
891     *ciphertext = 0;
892     // hier fehlt eine Fehlerbehandlung, falls das
893     // Signieren schiefging
894   }
895   gpgme_data_release( data );
896   gpgme_release (ctx);
897
898   if( bOk && structuring ) {
899     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
900     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
901     if( structuring->makeMimeObject ) {
902       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
903       storeNewCharPtr( &structuring->contentTypeMain,
904                        GPGMEPLUG_SIGN_CTYPE_MAIN );
905       storeNewCharPtr( &structuring->contentDispMain,
906                        GPGMEPLUG_SIGN_CDISP_MAIN );
907       storeNewCharPtr( &structuring->contentTEncMain,
908                        GPGMEPLUG_SIGN_CTENC_MAIN );
909       if( structuring->makeMultiMime ) {
910         storeNewCharPtr( &structuring->contentTypeVersion,
911                          GPGMEPLUG_SIGN_CTYPE_VERSION );
912         storeNewCharPtr( &structuring->contentDispVersion,
913                          GPGMEPLUG_SIGN_CDISP_VERSION );
914         storeNewCharPtr( &structuring->contentTEncVersion,
915                          GPGMEPLUG_SIGN_CTENC_VERSION );
916         storeNewCharPtr( &structuring->bodyTextVersion,
917                          GPGMEPLUG_SIGN_BTEXT_VERSION );
918         storeNewCharPtr( &structuring->contentTypeCode,
919                          GPGMEPLUG_SIGN_CTYPE_CODE );
920         storeNewCharPtr( &structuring->contentDispCode,
921                          GPGMEPLUG_SIGN_CDISP_CODE );
922         storeNewCharPtr( &structuring->contentTEncCode,
923                          GPGMEPLUG_SIGN_CTENC_CODE );
924       }
925     } else {
926       storeNewCharPtr( &structuring->flatTextPrefix,
927                        GPGMEPLUG_SIGN_FLAT_PREFIX );
928       storeNewCharPtr( &structuring->flatTextSeparator,
929                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
930       storeNewCharPtr( &structuring->flatTextPostfix,
931                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
932     }
933   }
934   return bOk;
935 }
936
937
938 static const char*
939 sig_status_to_string( GpgmeSigStat status )
940 {
941   const char *result;
942
943   switch (status) {
944     case GPGME_SIG_STAT_NONE:
945       result = "Oops: Signature not verified";
946       break;
947     case GPGME_SIG_STAT_NOSIG:
948       result = "No signature found";
949       break;
950     case GPGME_SIG_STAT_GOOD:
951       result = "Good signature";
952       break;
953     case GPGME_SIG_STAT_BAD:
954       result = "BAD signature";
955       break;
956     case GPGME_SIG_STAT_NOKEY:
957       result = "No public key to verify the signature";
958       break;
959     case GPGME_SIG_STAT_ERROR:
960       result = "Error verifying the signature";
961       break;
962     case GPGME_SIG_STAT_DIFF:
963       result = "Different results for signatures";
964       break;
965     default:
966       result = "Error: Unknown status";
967       break;
968   }
969
970   return result;
971 }
972
973
974 bool checkMessageSignature( const char* ciphertext,
975                             const char* signaturetext,
976                             struct SignatureMetaData* sigmeta )
977 {
978   GpgmeCtx ctx;
979   GpgmeSigStat status;
980   GpgmeData datapart, sigpart;
981   GpgmeError err;
982   GpgmeKey key;
983   time_t created;
984   int sig_idx = 0;
985   const char* statusStr;
986   const char* fpr;
987
988   gpgme_new( &ctx );
989   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
990   gpgme_data_new_from_mem( &datapart, ciphertext,
991                           1+strlen( ciphertext ), 1 );
992   gpgme_data_new_from_mem( &sigpart, signaturetext,
993                           1+strlen( signaturetext ), 1 );
994
995   gpgme_op_verify( ctx, sigpart, datapart, &status );
996   gpgme_data_release( datapart );
997   gpgme_data_release( sigpart );
998
999   /* Provide information in the sigmeta struct */
1000   /* the status string */
1001   statusStr = sig_status_to_string( status );
1002   sigmeta->status = malloc( strlen( statusStr ) + 1 );
1003   if( sigmeta->status ) {
1004     strcpy( sigmeta->status, statusStr );
1005     sigmeta->status[strlen( statusStr )] = '\0';
1006   } else
1007     ; // nothing to do, is already 0
1008
1009   // Extended information for any number of signatures.
1010   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
1011   sigmeta->extended_info = 0;
1012   while( fpr != NULL ) {
1013     struct tm* ctime_val;
1014     const char* sig_status;
1015
1016     void* realloc_return = realloc( sigmeta->extended_info,
1017                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1018     if( realloc_return ) {
1019       sigmeta->extended_info = realloc_return;
1020       // the creation time
1021       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1022       if( sigmeta->extended_info[sig_idx].creation_time ) {
1023         ctime_val = localtime( &created );
1024         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1025                 ctime_val, sizeof( struct tm ) );
1026       }
1027
1028       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1029       sig_status = sig_status_to_string( status );
1030       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
1031       if( sigmeta->extended_info[sig_idx].status_text ) {
1032         strcpy( sigmeta->extended_info[sig_idx].status_text,
1033                 sig_status );
1034         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
1035       }
1036
1037       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1038       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1039         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1040         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1041       }
1042     } else
1043       break; // if allocation fails once, it isn't likely to
1044               // succeed the next time either
1045
1046     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1047   }
1048   sigmeta->extended_info_count = sig_idx;
1049   sigmeta->nota_xml = gpgme_get_notation( ctx );
1050   sigmeta->status_code = status;
1051
1052   gpgme_release( ctx );
1053   return ( status == GPGME_SIG_STAT_GOOD );
1054 }
1055
1056 bool storeCertificatesFromMessage(
1057         const char* ciphertext ){ return true; }
1058
1059
1060 bool encryptMessage( const char* cleartext,
1061                      const char** ciphertext,
1062                      const char* addressee,
1063                      struct StructuringInfo* structuring )
1064 {
1065   GpgmeCtx ctx;
1066   GpgmeError err;
1067   GpgmeData gCiphertext, gPlaintext;
1068   GpgmeRecipients rset;
1069   size_t rCLen = 0;
1070   char*  rCiph = 0;
1071   bool   bOk   = false;
1072
1073   init_StructuringInfo( structuring );
1074
1075   gpgme_new (&ctx);
1076   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1077
1078   gpgme_set_armor (ctx, 1);
1079   gpgme_set_textmode (ctx, 1);
1080
1081   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1082                             1+strlen( cleartext ), 1 );
1083   err = gpgme_data_new ( &gCiphertext );
1084
1085   gpgme_recipients_new (&rset);
1086
1087
1088   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1089   {
1090     gpgme_recipients_add_name_with_validity (rset,
1091       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
1092       GPGME_VALIDITY_FULL );
1093     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1094   }
1095   else
1096   {
1097     gpgme_recipients_add_name (rset, addressee);
1098     fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", addressee );
1099   }
1100
1101
1102   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1103   if( err )
1104     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1105
1106   gpgme_recipients_release (rset);
1107   gpgme_data_release (gPlaintext);
1108
1109   if( !err ) {
1110     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1111     *ciphertext = malloc( rCLen + 1 );
1112     if( *ciphertext ) {
1113       if( rCLen ) {
1114         bOk = true;
1115         strncpy((char*)*ciphertext, rCiph, rCLen );
1116       }
1117       ((char*)(*ciphertext))[rCLen] = 0;
1118     }
1119     free( rCiph );
1120   }
1121   else {
1122     gpgme_data_release ( gCiphertext );
1123     *ciphertext = 0;
1124     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1125     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1126     // das signieren.
1127   }
1128
1129   gpgme_release (ctx);
1130
1131   fflush( stderr );
1132
1133   if( bOk && structuring ) {
1134     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1135     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1136     if( structuring->makeMimeObject ) {
1137       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1138       storeNewCharPtr( &structuring->contentTypeMain,
1139                        GPGMEPLUG_ENC_CTYPE_MAIN );
1140       storeNewCharPtr( &structuring->contentDispMain,
1141                        GPGMEPLUG_ENC_CDISP_MAIN );
1142       storeNewCharPtr( &structuring->contentTEncMain,
1143                        GPGMEPLUG_ENC_CTENC_MAIN );
1144       if( structuring->makeMultiMime ) {
1145         storeNewCharPtr( &structuring->contentTypeVersion,
1146                          GPGMEPLUG_ENC_CTYPE_VERSION );
1147         storeNewCharPtr( &structuring->contentDispVersion,
1148                          GPGMEPLUG_ENC_CDISP_VERSION );
1149         storeNewCharPtr( &structuring->contentTEncVersion,
1150                          GPGMEPLUG_ENC_CTENC_VERSION );
1151         storeNewCharPtr( &structuring->bodyTextVersion,
1152                          GPGMEPLUG_ENC_BTEXT_VERSION );
1153         storeNewCharPtr( &structuring->contentTypeCode,
1154                          GPGMEPLUG_ENC_CTYPE_CODE );
1155         storeNewCharPtr( &structuring->contentDispCode,
1156                          GPGMEPLUG_ENC_CDISP_CODE );
1157         storeNewCharPtr( &structuring->contentTEncCode,
1158                          GPGMEPLUG_ENC_CTENC_CODE );
1159       }
1160     } else {
1161       storeNewCharPtr( &structuring->flatTextPrefix,
1162                        GPGMEPLUG_ENC_FLAT_PREFIX );
1163       storeNewCharPtr( &structuring->flatTextSeparator,
1164                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1165       storeNewCharPtr( &structuring->flatTextPostfix,
1166                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1167     }
1168   }
1169   return bOk;
1170 }
1171
1172
1173 bool encryptAndSignMessage( const char* cleartext,
1174                             const char** ciphertext,
1175                             const char* certificate,
1176                             struct StructuringInfo* structuring )
1177 {
1178   bool bOk;
1179
1180   init_StructuringInfo( structuring );
1181
1182   bOk = false;
1183
1184   // implementation of this function is still missing
1185
1186   if( bOk && structuring ) {
1187     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1188     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1189     if( structuring->makeMimeObject ) {
1190       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1191       storeNewCharPtr( &structuring->contentTypeMain,
1192                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1193       storeNewCharPtr( &structuring->contentDispMain,
1194                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1195       storeNewCharPtr( &structuring->contentTEncMain,
1196                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1197       if( structuring->makeMultiMime ) {
1198         storeNewCharPtr( &structuring->contentTypeVersion,
1199                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1200         storeNewCharPtr( &structuring->contentDispVersion,
1201                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1202         storeNewCharPtr( &structuring->contentTEncVersion,
1203                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1204         storeNewCharPtr( &structuring->bodyTextVersion,
1205                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1206         storeNewCharPtr( &structuring->contentTypeCode,
1207                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1208         storeNewCharPtr( &structuring->contentDispCode,
1209                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1210         storeNewCharPtr( &structuring->contentTEncCode,
1211                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1212       }
1213     } else {
1214       storeNewCharPtr( &structuring->flatTextPrefix,
1215                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1216       storeNewCharPtr( &structuring->flatTextSeparator,
1217                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1218       storeNewCharPtr( &structuring->flatTextPostfix,
1219                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1220     }
1221   }
1222   return bOk;
1223 }
1224
1225 bool decryptMessage( const char* ciphertext,
1226                      const char** cleartext,
1227                      const char* certificate )
1228 {
1229   GpgmeCtx ctx;
1230   GpgmeError err;
1231   GpgmeData gCiphertext, gPlaintext;
1232   size_t rCLen = 0;
1233   char*  rCiph = 0;
1234   bool bOk = false;
1235
1236   if( !ciphertext )
1237     return false;
1238
1239   err = gpgme_new (&ctx);
1240   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1241
1242   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1243                            1+strlen( ciphertext ), 1 );
1244   gpgme_data_new( &gPlaintext );
1245
1246   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1247   gpgme_data_release( gCiphertext );
1248
1249   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1250
1251   *cleartext = malloc( rCLen + 1 );
1252   if( *cleartext ) {
1253       if( rCLen ) {
1254           bOk = true;
1255           strncpy((char*)*cleartext, rCiph, rCLen );
1256       }
1257       ((char*)(*cleartext))[rCLen] = 0;
1258   }
1259
1260   free( rCiph );
1261   gpgme_release( ctx );
1262   return bOk;
1263 }
1264
1265 bool decryptAndCheckMessage( const char* ciphertext,
1266           const char** cleartext, const char* certificate,
1267           struct SignatureMetaData* sigmeta ){ return true; }
1268
1269
1270 const char* requestCertificateDialog(){ return 0; }
1271
1272 bool requestDecentralCertificate( const char* name, const char*
1273           email, const char* organization, const char* department,
1274           const char* ca_address ){ return true; }
1275
1276 bool requestCentralCertificateAndPSE( const char* name,
1277           const char* email, const char* organization, const char* department,
1278           const char* ca_address ){ return true; }
1279
1280 bool createPSE(){ return true; }
1281
1282 bool registerCertificate( const char* certificate ){ return true; }
1283
1284 bool requestCertificateProlongation( const char* certificate,
1285                                      const char* ca_address ){ return true; }
1286
1287 const char* certificateChain(){ return 0; }
1288
1289 bool deleteCertificate( const char* certificate ){ return true; }
1290
1291 bool archiveCertificate( const char* certificate ){ return true; }
1292
1293
1294 const char* displayCRL(){ return 0; }
1295
1296 void updateCRL(){}