Support for asking the for the PIN a certain number of times.
[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
686 bool encryptionUseCRLs()
687 {
688   return config.encryptionUseCRLs;
689 }
690
691 void setEncryptionCRLExpiryNearWarning( bool flag )
692 {
693   config.encryptionCRLExpiryNearWarning = flag;
694 }
695
696 bool encryptionCRLExpiryNearWarning()
697 {
698   return config.encryptionCRLExpiryNearWarning;
699 }
700
701 void setEncryptionCRLNearExpiryInterval( int interval )
702 {
703   config.encryptionCRLNearExpiryInterval = interval;
704 }
705
706 int encryptionCRLNearExpiryInterval()
707 {
708   return config.encryptionCRLNearExpiryInterval;
709 }
710
711
712 const char* directoryServiceConfigurationDialog(){ return 0; }
713
714 void appendDirectoryServer( const char* servername,
715                             int         port,
716                             const char* description )
717 {
718   struct DirectoryServer *newServers = NULL;
719   newServers = realloc( config.directoryServers,
720                         (1+config.numDirectoryServers) * sizeof *newServers );
721   if( newServers ) {
722     config.directoryServers = newServers;
723     newServers[ config.numDirectoryServers ].servername =
724       malloc( 1+strlen( servername ) );
725     if( newServers[ config.numDirectoryServers ].servername ) {
726       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
727         servername );
728       newServers[ config.numDirectoryServers ].description =
729         malloc( 1+strlen(  description ) );
730       if( newServers[ config.numDirectoryServers ].description ) {
731         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
732           description );
733         newServers[ config.numDirectoryServers ].port = port;
734         config.numDirectoryServers += 1;
735       }
736     }
737   }
738 }
739
740 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
741 {
742   unsigned int i;
743   int oldSize = config.numDirectoryServers;
744   struct DirectoryServer *newServers = NULL;
745   newServers = calloc ( size, sizeof *newServers );
746   if( newServers ) {
747     for( i=0; i < oldSize; ++i ) {
748       free( (char *)config.directoryServers[i].servername );
749       free( (char *)config.directoryServers[i].description );
750     }
751     free( config.directoryServers );
752     for( i=0; i < size; ++i ) {
753       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
754       if( newServers[ i ].servername ) {
755         strcpy( (char *)newServers[ i ].servername, server[i].servername );
756         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
757         if( newServers[ i ].description ) {
758           strcpy( (char *)newServers[ i ].description, server[i].description );
759           newServers[ i ].port = server[i].port;
760         }
761       }
762     }
763     config.directoryServers = newServers;
764     config.numDirectoryServers = size;
765   }
766 }
767
768 struct DirectoryServer * directoryServers( int* numServers )
769 {
770   if( numServers )
771     *numServers = config.numDirectoryServers;
772   return config.directoryServers;
773 };
774
775 void setCertificateSource( CertificateSource source )
776 {
777   config.certificateSource = source;
778 }
779
780 CertificateSource certificateSource()
781 {
782   return config.certificateSource;
783 }
784
785 void setCRLSource( CertificateSource source )
786 {
787   config.cRLSource = source;
788 }
789
790 CertificateSource crlSource()
791 {
792   return config.cRLSource;
793 }
794
795
796 bool certificateValidity( const char* certificate,
797                           int* level ){ return true; }
798
799
800 void storeNewCharPtr( char** dest, const char* src )
801 {
802   int sLen = strlen( src );
803   *dest = malloc( sLen + 1 );
804   strcpy( *dest, src );
805   (*dest)[sLen] = '\0';
806 }
807
808
809 bool signMessage( const char*  cleartext,
810                   const char** ciphertext,
811                   const char*  certificate,
812                   struct StructuringInfo* structuring )
813 {
814   GpgmeCtx ctx;
815   GpgmeError err;
816   GpgmeData data,  sig;
817   size_t rSLen = 0;
818   char*  rSig  = 0;
819   bool   bOk   = false;
820   int sendCerts = 1;
821
822   init_StructuringInfo( structuring );
823
824   if( !ciphertext )
825     return false;
826
827   err = gpgme_new (&ctx);
828   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
829
830   gpgme_set_armor (ctx, 1);
831   gpgme_set_textmode (ctx, 1);
832
833   switch ( config.sendCertificates ) {
834     case SendCert_undef:
835       break;
836     case SendCert_DontSend:
837       sendCerts = 0;
838       break;
839     case SendCert_SendOwn:
840       sendCerts = 1;
841       break;
842     case SendCert_SendChainWithoutRoot:
843       sendCerts = -2;
844       break;
845     case SendCert_SendChainWithRoot:
846       sendCerts = -1;
847       break;
848     default:
849       sendCerts = 0;
850       break;
851   }
852   gpgme_set_include_certs (ctx, sendCerts);
853   
854   // PENDING(g10) Implement this
855   //gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm );
856
857   gpgme_data_new_from_mem (&data, cleartext,
858                             1+strlen( cleartext ), 1 );
859   gpgme_data_new ( &sig );
860   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
861
862   if (!err) {
863     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
864     *ciphertext = malloc( rSLen + 1 );
865     if( *ciphertext ) {
866       if( rSLen ) {
867         bOk = true;
868         strncpy((char*)*ciphertext, rSig, rSLen );
869       }
870       ((char*)(*ciphertext))[rSLen] = '\0';
871     }
872     free( rSig );
873   }
874   else {
875     gpgme_data_release( sig );
876     *ciphertext = 0;
877     // hier fehlt eine Fehlerbehandlung, falls das
878     // Signieren schiefging
879   }
880   gpgme_data_release( data );
881   gpgme_release (ctx);
882
883   if( bOk && structuring ) {
884     structuring->includeCleartext = GPGMEPLUG_SIGN_INCLUDE_CLEARTEXT;
885     structuring->makeMimeObject   = GPGMEPLUG_SIGN_MAKE_MIME_OBJECT;
886     if( structuring->makeMimeObject ) {
887       structuring->makeMultiMime  = GPGMEPLUG_SIGN_MAKE_MULTI_MIME;
888       storeNewCharPtr( &structuring->contentTypeMain,
889                        GPGMEPLUG_SIGN_CTYPE_MAIN );
890       storeNewCharPtr( &structuring->contentDispMain,
891                        GPGMEPLUG_SIGN_CDISP_MAIN );
892       storeNewCharPtr( &structuring->contentTEncMain,
893                        GPGMEPLUG_SIGN_CTENC_MAIN );
894       if( structuring->makeMultiMime ) {
895         storeNewCharPtr( &structuring->contentTypeVersion,
896                          GPGMEPLUG_SIGN_CTYPE_VERSION );
897         storeNewCharPtr( &structuring->contentDispVersion,
898                          GPGMEPLUG_SIGN_CDISP_VERSION );
899         storeNewCharPtr( &structuring->contentTEncVersion,
900                          GPGMEPLUG_SIGN_CTENC_VERSION );
901         storeNewCharPtr( &structuring->bodyTextVersion,
902                          GPGMEPLUG_SIGN_BTEXT_VERSION );
903         storeNewCharPtr( &structuring->contentTypeCode,
904                          GPGMEPLUG_SIGN_CTYPE_CODE );
905         storeNewCharPtr( &structuring->contentDispCode,
906                          GPGMEPLUG_SIGN_CDISP_CODE );
907         storeNewCharPtr( &structuring->contentTEncCode,
908                          GPGMEPLUG_SIGN_CTENC_CODE );
909       }
910     } else {
911       storeNewCharPtr( &structuring->flatTextPrefix,
912                        GPGMEPLUG_SIGN_FLAT_PREFIX );
913       storeNewCharPtr( &structuring->flatTextSeparator,
914                        GPGMEPLUG_SIGN_FLAT_SEPARATOR );
915       storeNewCharPtr( &structuring->flatTextPostfix,
916                        GPGMEPLUG_SIGN_FLAT_POSTFIX );
917     }
918   }
919   return bOk;
920 }
921
922
923 static const char*
924 sig_status_to_string( GpgmeSigStat status )
925 {
926   const char *result;
927
928   switch (status) {
929     case GPGME_SIG_STAT_NONE:
930       result = "Oops: Signature not verified";
931       break;
932     case GPGME_SIG_STAT_NOSIG:
933       result = "No signature found";
934       break;
935     case GPGME_SIG_STAT_GOOD:
936       result = "Good signature";
937       break;
938     case GPGME_SIG_STAT_BAD:
939       result = "BAD signature";
940       break;
941     case GPGME_SIG_STAT_NOKEY:
942       result = "No public key to verify the signature";
943       break;
944     case GPGME_SIG_STAT_ERROR:
945       result = "Error verifying the signature";
946       break;
947     case GPGME_SIG_STAT_DIFF:
948       result = "Different results for signatures";
949       break;
950     default:
951       result = "Error: Unknown status";
952       break;
953   }
954
955   return result;
956 }
957
958
959 bool checkMessageSignature( const char* ciphertext,
960                             const char* signaturetext,
961                             struct SignatureMetaData* sigmeta )
962 {
963   GpgmeCtx ctx;
964   GpgmeSigStat status;
965   GpgmeData datapart, sigpart;
966   GpgmeError err;
967   GpgmeKey key;
968   time_t created;
969   int sig_idx = 0;
970   const char* statusStr;
971   const char* fpr;
972
973   gpgme_new( &ctx );
974   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
975   gpgme_data_new_from_mem( &datapart, ciphertext,
976                           1+strlen( ciphertext ), 1 );
977   gpgme_data_new_from_mem( &sigpart, signaturetext,
978                           1+strlen( signaturetext ), 1 );
979
980   gpgme_op_verify( ctx, sigpart, datapart, &status );
981   gpgme_data_release( datapart );
982   gpgme_data_release( sigpart );
983
984   /* Provide information in the sigmeta struct */
985   /* the status string */
986   statusStr = sig_status_to_string( status );
987   sigmeta->status = malloc( strlen( statusStr ) + 1 );
988   if( sigmeta->status ) {
989     strcpy( sigmeta->status, statusStr );
990     sigmeta->status[strlen( statusStr )] = '\0';
991   } else
992     ; // nothing to do, is already 0
993
994   // Extended information for any number of signatures.
995   fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
996   sigmeta->extended_info = 0;
997   while( fpr != NULL ) {
998     struct tm* ctime_val;
999     const char* sig_status;
1000
1001     void* realloc_return = realloc( sigmeta->extended_info,
1002                                     sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
1003     if( realloc_return ) {
1004       sigmeta->extended_info = realloc_return;
1005       // the creation time
1006       sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
1007       if( sigmeta->extended_info[sig_idx].creation_time ) {
1008         ctime_val = localtime( &created );
1009         memcpy( sigmeta->extended_info[sig_idx].creation_time,
1010                 ctime_val, sizeof( struct tm ) );
1011       }
1012
1013       err = gpgme_get_sig_key (ctx, sig_idx, &key);
1014       sig_status = sig_status_to_string( status );
1015       sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
1016       if( sigmeta->extended_info[sig_idx].status_text ) {
1017         strcpy( sigmeta->extended_info[sig_idx].status_text,
1018                 sig_status );
1019         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
1020       }
1021
1022       sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
1023       if( sigmeta->extended_info[sig_idx].fingerprint ) {
1024         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
1025         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
1026       }
1027     } else
1028       break; // if allocation fails once, it isn't likely to
1029               // succeed the next time either
1030
1031     fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
1032   }
1033   sigmeta->extended_info_count = sig_idx;
1034   sigmeta->nota_xml = gpgme_get_notation( ctx );
1035   sigmeta->status_code = status;
1036
1037   gpgme_release( ctx );
1038   return ( status == GPGME_SIG_STAT_GOOD );
1039 }
1040
1041 bool storeCertificatesFromMessage(
1042         const char* ciphertext ){ return true; }
1043
1044
1045 bool encryptMessage( const char* cleartext,
1046                      const char** ciphertext,
1047                      const char* addressee,
1048                      struct StructuringInfo* structuring )
1049 {
1050   GpgmeCtx ctx;
1051   GpgmeError err;
1052   GpgmeData gCiphertext, gPlaintext;
1053   GpgmeRecipients rset;
1054   size_t rCLen = 0;
1055   char*  rCiph = 0;
1056   bool   bOk   = false;
1057
1058   init_StructuringInfo( structuring );
1059
1060   gpgme_new (&ctx);
1061   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1062
1063   gpgme_set_armor (ctx, 1);
1064   gpgme_set_textmode (ctx, 1);
1065
1066   gpgme_data_new_from_mem (&gPlaintext, cleartext,
1067                             1+strlen( cleartext ), 1 );
1068   err = gpgme_data_new ( &gCiphertext );
1069
1070   gpgme_recipients_new (&rset);
1071
1072
1073   if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
1074   {
1075     gpgme_recipients_add_name_with_validity (rset,
1076       "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=DĂĽsseldorf,C=DE",
1077       GPGME_VALIDITY_FULL );
1078     fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
1079   }
1080   else
1081   {
1082     gpgme_recipients_add_name (rset, addressee);
1083     fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", addressee );
1084   }
1085
1086
1087   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
1088   if( err )
1089     fprintf( stderr, "gpgme_op_encrypt() returned this error code:  %i\n\n", err );
1090
1091   gpgme_recipients_release (rset);
1092   gpgme_data_release (gPlaintext);
1093
1094   if( !err ) {
1095     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
1096     *ciphertext = malloc( rCLen + 1 );
1097     if( *ciphertext ) {
1098       if( rCLen ) {
1099         bOk = true;
1100         strncpy((char*)*ciphertext, rCiph, rCLen );
1101       }
1102       ((char*)(*ciphertext))[rCLen] = 0;
1103     }
1104     free( rCiph );
1105   }
1106   else {
1107     gpgme_data_release ( gCiphertext );
1108     *ciphertext = 0;
1109     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
1110     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
1111     // das signieren.
1112   }
1113
1114   gpgme_release (ctx);
1115
1116   fflush( stderr );
1117
1118   if( bOk && structuring ) {
1119     structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
1120     structuring->makeMimeObject   = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
1121     if( structuring->makeMimeObject ) {
1122       structuring->makeMultiMime  = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
1123       storeNewCharPtr( &structuring->contentTypeMain,
1124                        GPGMEPLUG_ENC_CTYPE_MAIN );
1125       storeNewCharPtr( &structuring->contentDispMain,
1126                        GPGMEPLUG_ENC_CDISP_MAIN );
1127       storeNewCharPtr( &structuring->contentTEncMain,
1128                        GPGMEPLUG_ENC_CTENC_MAIN );
1129       if( structuring->makeMultiMime ) {
1130         storeNewCharPtr( &structuring->contentTypeVersion,
1131                          GPGMEPLUG_ENC_CTYPE_VERSION );
1132         storeNewCharPtr( &structuring->contentDispVersion,
1133                          GPGMEPLUG_ENC_CDISP_VERSION );
1134         storeNewCharPtr( &structuring->contentTEncVersion,
1135                          GPGMEPLUG_ENC_CTENC_VERSION );
1136         storeNewCharPtr( &structuring->bodyTextVersion,
1137                          GPGMEPLUG_ENC_BTEXT_VERSION );
1138         storeNewCharPtr( &structuring->contentTypeCode,
1139                          GPGMEPLUG_ENC_CTYPE_CODE );
1140         storeNewCharPtr( &structuring->contentDispCode,
1141                          GPGMEPLUG_ENC_CDISP_CODE );
1142         storeNewCharPtr( &structuring->contentTEncCode,
1143                          GPGMEPLUG_ENC_CTENC_CODE );
1144       }
1145     } else {
1146       storeNewCharPtr( &structuring->flatTextPrefix,
1147                        GPGMEPLUG_ENC_FLAT_PREFIX );
1148       storeNewCharPtr( &structuring->flatTextSeparator,
1149                        GPGMEPLUG_ENC_FLAT_SEPARATOR );
1150       storeNewCharPtr( &structuring->flatTextPostfix,
1151                        GPGMEPLUG_ENC_FLAT_POSTFIX );
1152     }
1153   }
1154   return bOk;
1155 }
1156
1157
1158 bool encryptAndSignMessage( const char* cleartext,
1159                             const char** ciphertext,
1160                             const char* certificate,
1161                             struct StructuringInfo* structuring )
1162 {
1163   bool bOk;
1164
1165   init_StructuringInfo( structuring );
1166
1167   bOk = false;
1168
1169   // implementation of this function is still missing
1170
1171   if( bOk && structuring ) {
1172     structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
1173     structuring->makeMimeObject   = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
1174     if( structuring->makeMimeObject ) {
1175       structuring->makeMultiMime  = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
1176       storeNewCharPtr( &structuring->contentTypeMain,
1177                        GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
1178       storeNewCharPtr( &structuring->contentDispMain,
1179                        GPGMEPLUG_ENCSIGN_CDISP_MAIN );
1180       storeNewCharPtr( &structuring->contentTEncMain,
1181                        GPGMEPLUG_ENCSIGN_CTENC_MAIN );
1182       if( structuring->makeMultiMime ) {
1183         storeNewCharPtr( &structuring->contentTypeVersion,
1184                          GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
1185         storeNewCharPtr( &structuring->contentDispVersion,
1186                          GPGMEPLUG_ENCSIGN_CDISP_VERSION );
1187         storeNewCharPtr( &structuring->contentTEncVersion,
1188                          GPGMEPLUG_ENCSIGN_CTENC_VERSION );
1189         storeNewCharPtr( &structuring->bodyTextVersion,
1190                          GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
1191         storeNewCharPtr( &structuring->contentTypeCode,
1192                          GPGMEPLUG_ENCSIGN_CTYPE_CODE );
1193         storeNewCharPtr( &structuring->contentDispCode,
1194                          GPGMEPLUG_ENCSIGN_CDISP_CODE );
1195         storeNewCharPtr( &structuring->contentTEncCode,
1196                          GPGMEPLUG_ENCSIGN_CTENC_CODE );
1197       }
1198     } else {
1199       storeNewCharPtr( &structuring->flatTextPrefix,
1200                        GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
1201       storeNewCharPtr( &structuring->flatTextSeparator,
1202                        GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
1203       storeNewCharPtr( &structuring->flatTextPostfix,
1204                        GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
1205     }
1206   }
1207   return bOk;
1208 }
1209
1210 bool decryptMessage( const char* ciphertext,
1211                      const char** cleartext,
1212                      const char* certificate )
1213 {
1214   GpgmeCtx ctx;
1215   GpgmeError err;
1216   GpgmeData gCiphertext, gPlaintext;
1217   size_t rCLen = 0;
1218   char*  rCiph = 0;
1219   bool bOk = false;
1220
1221   if( !ciphertext )
1222     return false;
1223
1224   err = gpgme_new (&ctx);
1225   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
1226
1227   gpgme_data_new_from_mem( &gCiphertext, ciphertext,
1228                            1+strlen( ciphertext ), 1 );
1229   gpgme_data_new( &gPlaintext );
1230
1231   gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
1232   gpgme_data_release( gCiphertext );
1233
1234   rCiph = gpgme_data_release_and_get_mem( gPlaintext,  &rCLen );
1235
1236   *cleartext = malloc( rCLen + 1 );
1237   if( *cleartext ) {
1238       if( rCLen ) {
1239           bOk = true;
1240           strncpy((char*)*cleartext, rCiph, rCLen );
1241       }
1242       ((char*)(*cleartext))[rCLen] = 0;
1243   }
1244
1245   free( rCiph );
1246   gpgme_release( ctx );
1247   return bOk;
1248 }
1249
1250 bool decryptAndCheckMessage( const char* ciphertext,
1251           const char** cleartext, const char* certificate,
1252           struct SignatureMetaData* sigmeta ){ return true; }
1253
1254
1255 const char* requestCertificateDialog(){ return 0; }
1256
1257 bool requestDecentralCertificate( const char* name, const char*
1258           email, const char* organization, const char* department,
1259           const char* ca_address ){ return true; }
1260
1261 bool requestCentralCertificateAndPSE( const char* name,
1262           const char* email, const char* organization, const char* department,
1263           const char* ca_address ){ return true; }
1264
1265 bool createPSE(){ return true; }
1266
1267 bool registerCertificate( const char* certificate ){ return true; }
1268
1269 bool requestCertificateProlongation( const char* certificate,
1270                                      const char* ca_address ){ return true; }
1271
1272 const char* certificateChain(){ return 0; }
1273
1274 bool deleteCertificate( const char* certificate ){ return true; }
1275
1276 bool archiveCertificate( const char* certificate ){ return true; }
1277
1278
1279 const char* displayCRL(){ return 0; }
1280
1281 void updateCRL(){}