added error detection to signing and encrypting methodes: this has to be improved...
[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 <stdlib.h>
50 #include <string.h>
51 #include <assert.h>
52 #include <errno.h>
53 #include <time.h>
54
55 #include "gpgme.h"
56 #ifndef GPGMEPLUG_PROTOCOL
57 #define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
58 #endif
59
60 #include "cryptplug.h"
61
62
63 typedef struct {
64   const char*             signatureKeyCertificate;
65   SignatureAlgorithm      signatureAlgorithm;
66   SendCertificates        sendCertificates;
67   SignEmail               signEmail;
68   bool                    saveSentSignatures;
69   bool                    warnNoCertificate;
70   PinRequests             numPINRequests;
71   bool                    checkSignatureCertificatePathToRoot;
72   bool                    signatureUseCRLs;
73   EncryptionAlgorithm     encryptionAlgorithm;
74   EncryptEmail            encryptEmail;
75   bool                    saveMessagesEncrypted;
76   bool                    checkEncryptionCertificatePathToRoot;
77   bool                    encryptionUseCRLs;
78   bool                    encryptionCRLExpiryNearWarning;
79   int                     encryptionCRLNearExpiryInterval;
80   struct DirectoryServer *directoryServers;
81   unsigned int            numDirectoryServers;
82   CertificateSource       certificateSource;
83   CertificateSource       cRLSource;
84   bool                    warnSendUnsigned;
85   int                     numPINRequestsInterval;
86   bool                    signatureCertificateExpiryNearWarning;
87   int                     signatureCertificateExpiryNearInterval;
88   bool                    cACertificateExpiryNearWarning;
89   int                     cACertificateExpiryNearInterval;
90   bool                    rootCertificateExpiryNearWarning;
91   int                     rootCertificateExpiryNearInterval;
92   bool                    warnSendUnencrypted;
93   bool                    checkCertificatePath;
94   bool                    receiverCertificateExpiryNearWarning;
95   int                     receiverCertificateExpiryNearWarningInterval;
96   bool                    certificateInChainExpiryNearWarning;
97   int                     certificateInChainExpiryNearWarningInterval;
98   bool                    receiverEmailAddressNotInCertificateWarning;
99 } Config;
100
101
102 Config config;
103
104
105
106
107 /*
108   temporary code!!
109
110   will be removed!!
111
112   asking for passphrase will be handeked via gpg-agent!!
113 */
114 static char tmpPassphrase[1024];
115 struct passphrase_cb_info_s {
116     GpgmeCtx c;
117     int did_it;
118 };
119 static const char *
120 passphrase_cb (void *opaque, const char *desc, void *r_hd)
121 {
122     return tmpPassphrase;
123 }
124
125
126
127
128
129 #define NEAR_EXPIRY 14
130
131 bool initialize()
132 {
133   config.signatureKeyCertificate              = "";
134   config.signatureAlgorithm                   = SignAlg_SHA1;
135   config.sendCertificates                     = SendCert_SendChainWithRoot;
136   config.signEmail                            = SignEmail_SignAll;
137   config.saveSentSignatures                   = true;
138   config.warnNoCertificate                    = true;
139   config.numPINRequests                       = PinRequest_Always;
140   config.checkSignatureCertificatePathToRoot  = true;
141   config.signatureUseCRLs                     = true;
142   config.encryptionAlgorithm                  = EncryptAlg_RSA;
143   config.encryptEmail                         = EncryptEmail_Ask;
144   config.saveMessagesEncrypted                = true;
145   config.checkEncryptionCertificatePathToRoot = true;
146   config.encryptionUseCRLs                    = true;
147   config.encryptionCRLExpiryNearWarning       = true;
148   config.encryptionCRLNearExpiryInterval      = NEAR_EXPIRY;
149   config.directoryServers                     = NULL;
150   config.numDirectoryServers                  = 0;
151   config.certificateSource                    = CertSrc_Server;
152   config.cRLSource                            = CertSrc_Server;
153   config.warnSendUnsigned                             = true;
154   config.numPINRequestsInterval                       = NEAR_EXPIRY;
155   config.signatureCertificateExpiryNearWarning        = true;
156   config.signatureCertificateExpiryNearInterval       = NEAR_EXPIRY;
157   config.cACertificateExpiryNearWarning               = true;
158   config.cACertificateExpiryNearInterval              = NEAR_EXPIRY;
159   config.rootCertificateExpiryNearWarning             = true;
160   config.rootCertificateExpiryNearInterval            = NEAR_EXPIRY;
161   config.warnSendUnencrypted                          = false;
162   config.checkCertificatePath                         = true;
163   config.receiverCertificateExpiryNearWarning         = true;
164   config.receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY;
165   config.certificateInChainExpiryNearWarning          = true;
166   config.certificateInChainExpiryNearWarningInterval  = NEAR_EXPIRY;
167   config.receiverEmailAddressNotInCertificateWarning  = true;
168
169   return true;
170 };
171
172
173 void deinitialize()
174 {
175   unsigned int i;
176   for( i = 0; i < config.numDirectoryServers; ++i ) {
177     free( (char *)config.directoryServers[i].servername );
178     free( (char *)config.directoryServers[i].description );
179   }
180   free( config.directoryServers );
181 }
182
183
184 bool hasFeature( Feature flag )
185 {
186   switch ( flag ) {
187     case CryptPlugFeat_SignMessages:              return true;
188     case CryptPlugFeat_VerifySignatures:          return true;
189     case CryptPlugFeat_EncryptMessages:           return true;
190     case CryptPlugFeat_DecryptMessages:           return true;
191     // undefined or not yet implemented:
192     case CryptPlugFeat_undef:                     return false;
193     default:                                      return false;
194   }
195 }
196
197
198 void unsafeStationery( void** pixmap, const char** menutext, char* accel,
199           const char** tooltip, const char** statusbartext ){}
200
201 void signedStationery( void** pixmap, const char** menutext, char* accel,
202           const char** tooltip, const char** statusbartext ){}
203
204 void encryptedStationery( void** pixmap, const char**
205           menutext, char* accel,
206           const char** tooltip, const char** statusbartext ){}
207
208 void signedEncryptedStationery( void** pixmap, const char**
209           menutext, char* accel,
210           const char** tooltip, const char** statusbartext ){}
211
212 const char* signatureConfigurationDialog(){ return 0; }
213
214 const char* signatureKeySelectionDialog(){ return 0; }
215
216 const char* signatureAlgorithmDialog(){ return 0; }
217
218 const char* signatureHandlingDialog(){ return 0; }
219
220 void setSignatureKeyCertificate( const char* certificate )
221 {
222   config.signatureKeyCertificate = certificate;
223 }
224
225 const char* signatureKeyCertificate()
226 {
227   return config.signatureKeyCertificate;
228 }
229
230 void setSignatureAlgorithm( SignatureAlgorithm sigAlg )
231 {
232   config.signatureAlgorithm = sigAlg;
233 }
234
235 SignatureAlgorithm signatureAlgorithm()
236 {
237   return config.signatureAlgorithm;
238 }
239
240 void setSendCertificates( SendCertificates sendCert )
241 {
242   config.sendCertificates = sendCert;
243 }
244
245 SendCertificates sendCertificates()
246 {
247   return config.sendCertificates;
248 }
249
250 void setSignEmail( SignEmail signMail )
251 {
252   config.signEmail = signMail;
253 }
254
255 SignEmail signEmail()
256 {
257   return config.signEmail;
258 }
259
260
261
262
263
264 void setWarnSendUnsigned( bool flag )
265 {
266   config.warnSendUnsigned = flag;
267 }
268
269 bool warnSendUnsigned()
270 {
271   return config.warnSendUnsigned;
272 }
273
274
275
276
277
278
279 void setSaveSentSignatures( bool flag )
280 {
281   config.saveSentSignatures = flag;
282 }
283
284 bool saveSentSignatures()
285 {
286   return config.saveSentSignatures;
287 }
288
289 void setWarnNoCertificate( bool flag )
290 {
291   config.warnNoCertificate = flag;
292 }
293
294 bool warnNoCertificate()
295 {
296   return config.warnNoCertificate;
297 }
298
299 void setNumPINRequests( PinRequests reqMode )
300 {
301   config.numPINRequests = reqMode;
302 }
303
304 PinRequests numPINRequests()
305 {
306   return config.numPINRequests;
307 }
308
309
310
311
312
313 void setNumPINRequestsInterval( int interval )
314 {
315   config.numPINRequestsInterval = interval;
316 }
317
318 int numPINRequestsInterval()
319 {
320   return config.numPINRequestsInterval;
321 }
322
323
324
325
326
327
328
329 void setCheckSignatureCertificatePathToRoot( bool flag )
330 {
331   config.checkSignatureCertificatePathToRoot = flag;
332 }
333
334 bool checkSignatureCertificatePathToRoot()
335 {
336   return config.checkSignatureCertificatePathToRoot;
337 }
338
339 void setSignatureUseCRLs( bool flag )
340 {
341   config.signatureUseCRLs = flag;
342 }
343
344 bool signatureUseCRLs()
345 {
346   return config.signatureUseCRLs;
347 }
348
349
350
351
352
353
354 void setSignatureCertificateExpiryNearWarning( bool flag )
355 {
356   config.signatureCertificateExpiryNearWarning = flag;
357 }
358
359 bool signatureCertificateExpiryNearWarning( void )
360 {
361   return config.signatureCertificateExpiryNearWarning;
362 }
363
364 void setSignatureCertificateExpiryNearInterval( int interval )
365 {
366   config.signatureCertificateExpiryNearInterval = interval;
367 }
368
369 int signatureCertificateExpiryNearInterval( void )
370 {
371   return config.signatureCertificateExpiryNearInterval;
372 }
373
374 void setCACertificateExpiryNearWarning( bool flag )
375 {
376   config.cACertificateExpiryNearWarning = flag;
377 }
378
379 bool caCertificateExpiryNearWarning( void )
380 {
381   return config.cACertificateExpiryNearWarning;
382 }
383
384 void setCACertificateExpiryNearInterval( int interval )
385 {
386   config.cACertificateExpiryNearInterval = interval;
387 }
388
389 int caCertificateExpiryNearInterval( void )
390 {
391   return config.cACertificateExpiryNearInterval;
392 }
393
394 void setRootCertificateExpiryNearWarning( bool flag )
395 {
396   config.rootCertificateExpiryNearWarning = flag;
397 }
398
399 bool rootCertificateExpiryNearWarning( void )
400 {
401   return config.rootCertificateExpiryNearWarning;
402 }
403
404 void setRootCertificateExpiryNearInterval( int interval )
405 {
406   config.rootCertificateExpiryNearInterval = interval;
407 }
408
409 int rootCertificateExpiryNearInterval( void )
410 {
411   return config.rootCertificateExpiryNearInterval;
412 }
413
414
415
416
417
418
419
420
421 const char* encryptionConfigurationDialog(){ return 0; }
422
423 const char* encryptionAlgorithmDialog(){ return 0; }
424
425 const char* encryptionHandlingDialog(){ return 0; }
426
427 const char* encryptionReceiverDialog(){ return 0; }
428
429 void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
430 {
431   config.encryptionAlgorithm = cryptAlg;
432 }
433
434 EncryptionAlgorithm encryptionAlgorithm()
435 {
436   return config.encryptionAlgorithm;
437 }
438
439 void setEncryptEmail( EncryptEmail cryptMode )
440 {
441   config.encryptEmail = cryptMode;
442 }
443
444 EncryptEmail encryptEmail()
445 {
446   return config.encryptEmail;
447 }
448
449
450
451
452
453
454 void setWarnSendUnencrypted( bool flag )
455 {
456   config.warnSendUnencrypted = flag;
457 }
458
459 bool warnSendUnencrypted()
460 {
461   return config.warnSendUnencrypted;
462 }
463
464
465
466
467
468
469
470
471
472 void setSaveMessagesEncrypted( bool flag )
473 {
474   config.saveMessagesEncrypted = flag;
475 }
476
477 bool saveMessagesEncrypted()
478 {
479   return config.saveMessagesEncrypted;
480 }
481
482
483
484
485
486
487
488 void setCheckCertificatePath( bool flag )
489 {
490   config.checkCertificatePath = flag;
491 }
492
493 bool checkCertificatePath()
494 {
495   return config.checkCertificatePath;
496 }
497
498
499
500
501
502
503
504
505 void setCheckEncryptionCertificatePathToRoot( bool flag )
506 {
507   config.checkEncryptionCertificatePathToRoot = flag;
508 }
509
510 bool checkEncryptionCertificatePathToRoot()
511 {
512   return config.checkEncryptionCertificatePathToRoot;
513 }
514
515
516
517
518
519
520
521 void setReceiverCertificateExpiryNearWarning( bool flag )
522 {
523   config.receiverCertificateExpiryNearWarning = flag;
524 }
525
526 bool receiverCertificateExpiryNearWarning()
527 {
528   return config.receiverCertificateExpiryNearWarning;
529 }
530
531 void setReceiverCertificateExpiryNearWarningInterval( int interval )
532 {
533   config.receiverCertificateExpiryNearWarningInterval = interval;
534 }
535
536 int receiverCertificateExpiryNearWarningInterval()
537 {
538   return config.receiverCertificateExpiryNearWarningInterval;
539 }
540
541 void setCertificateInChainExpiryNearWarning( bool flag )
542 {
543   config.certificateInChainExpiryNearWarning = flag;
544 }
545
546 bool certificateInChainExpiryNearWarning()
547 {
548   return config.certificateInChainExpiryNearWarning;
549 }
550
551 void setCertificateInChainExpiryNearWarningInterval( int interval )
552 {
553   config.certificateInChainExpiryNearWarningInterval = interval;
554 }
555
556 int certificateInChainExpiryNearWarningInterval()
557 {
558   return config.certificateInChainExpiryNearWarningInterval;
559 }
560
561 void setReceiverEmailAddressNotInCertificateWarning( bool flag )
562 {
563   config.receiverEmailAddressNotInCertificateWarning = flag;
564 }
565
566 bool receiverEmailAddressNotInCertificateWarning()
567 {
568   return config.receiverEmailAddressNotInCertificateWarning;
569 }
570
571
572
573
574
575
576
577
578 void setEncryptionUseCRLs( bool flag )
579 {
580   config.encryptionUseCRLs = flag;
581 }
582
583 bool encryptionUseCRLs()
584 {
585   return config.encryptionUseCRLs;
586 }
587
588 void setEncryptionCRLExpiryNearWarning( bool flag )
589 {
590   config.encryptionCRLExpiryNearWarning = flag;
591 }
592
593 bool encryptionCRLExpiryNearWarning()
594 {
595   return config.encryptionCRLExpiryNearWarning;
596 }
597
598 void setEncryptionCRLNearExpiryInterval( int interval )
599 {
600   config.encryptionCRLNearExpiryInterval = interval;
601 }
602
603 int encryptionCRLNearExpiryInterval()
604 {
605   return config.encryptionCRLNearExpiryInterval;
606 }
607
608
609 const char* directoryServiceConfigurationDialog(){ return 0; }
610
611 void appendDirectoryServer( const char* servername,
612                             int         port,
613                             const char* description )
614 {
615   struct DirectoryServer *newServers = NULL;
616   newServers = realloc( config.directoryServers,
617                         (1+config.numDirectoryServers) * sizeof *newServers );
618   if( newServers ) {
619     config.directoryServers = newServers;
620     newServers[ config.numDirectoryServers ].servername =
621       malloc( 1+strlen( servername ) );
622     if( newServers[ config.numDirectoryServers ].servername ) {
623       strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
624         servername );
625       newServers[ config.numDirectoryServers ].description =
626         malloc( 1+strlen(  description ) );
627       if( newServers[ config.numDirectoryServers ].description ) {
628         strcpy( (char *)newServers[ config.numDirectoryServers ].description,
629           description );
630         newServers[ config.numDirectoryServers ].port = port;
631         config.numDirectoryServers += 1;
632       }
633     }
634   }
635 }
636
637 void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
638 {
639   unsigned int i;
640   int oldSize = config.numDirectoryServers;
641   struct DirectoryServer *newServers = NULL;
642   newServers = calloc ( size, sizeof *newServers );
643   if( newServers ) {
644     for( i=0; i < oldSize; ++i ) {
645       free( (char *)config.directoryServers[i].servername );
646       free( (char *)config.directoryServers[i].description );
647     }
648     free( config.directoryServers );
649     for( i=0; i < size; ++i ) {
650       newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
651       if( newServers[ i ].servername ) {
652         strcpy( (char *)newServers[ i ].servername, server[i].servername );
653         newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
654         if( newServers[ i ].description ) {
655           strcpy( (char *)newServers[ i ].description, server[i].description );
656           newServers[ i ].port = server[i].port;
657         }
658       }
659     }
660     config.directoryServers = newServers;
661     config.numDirectoryServers = size;
662   }
663 }
664
665 struct DirectoryServer * directoryServers( int* numServers )
666 {
667   if( numServers )
668     *numServers = config.numDirectoryServers;
669   return config.directoryServers;
670 };
671
672 void setCertificateSource( CertificateSource source )
673 {
674   config.certificateSource = source;
675 }
676
677 CertificateSource certificateSource()
678 {
679   return config.certificateSource;
680 }
681
682 void setCRLSource( CertificateSource source )
683 {
684   config.cRLSource = source;
685 }
686
687 CertificateSource crlSource()
688 {
689   return config.cRLSource;
690 }
691
692
693 bool certificateValidity( const char* certificate,
694                           int* level ){ return true; }
695
696
697 bool signMessage( const char*  cleartext,
698                   const char** ciphertext,
699                   const char*  certificate )
700 {
701   GpgmeCtx ctx;
702   GpgmeError err;
703   GpgmeData data,  sig;
704   size_t rSLen = 0;
705   char*  rSig  = 0;
706   bool   bOk   = false;
707
708
709
710 /*
711   temporary code!!
712
713   will be removed!!
714
715   asking for passphrase will be handeked via gpg-agent!!
716 */
717   struct passphrase_cb_info_s info;
718
719
720
721
722
723   if( !ciphertext )
724     return false;
725
726   err = gpgme_new (&ctx);
727   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
728
729
730
731
732
733
734 /*
735   temporary code!!
736
737   will be removed!!
738
739   asking for passphrase will be handeked via gpg-agent!!
740 */
741   if (!getenv("GPG_AGENT_INFO")) {
742       info.c = ctx;
743       gpgme_set_passphrase_cb (ctx, passphrase_cb, &info);
744   }
745   strcpy( tmpPassphrase, certificate );
746
747
748
749
750
751   gpgme_set_armor (ctx, 1);
752   gpgme_set_textmode (ctx, 1);
753
754   gpgme_data_new_from_mem (&data, cleartext,
755                             1+strlen( cleartext ), 1 );
756   gpgme_data_new ( &sig );
757   err = gpgme_op_sign (ctx, data, sig, GPGME_SIG_MODE_DETACH );
758
759   if (!err) {
760     rSig  = gpgme_data_release_and_get_mem( sig,  &rSLen );
761     *ciphertext = malloc( rSLen + 1 );
762     if( *ciphertext ) {
763       if( rSLen ) {
764         bOk = true;
765         strncpy((char*)*ciphertext, rSig, rSLen );
766       }
767       ((char*)(*ciphertext))[rSLen] = '\0';
768     }
769     free( rSig );
770   }
771   else {
772     gpgme_data_release( sig );
773     *ciphertext = 0;
774     // hier fehlt eine Fehlerbehandlung, falls das
775     // Signieren schiefging
776   }
777   gpgme_data_release( data );
778   gpgme_release (ctx);
779
780   return bOk;
781 }
782
783
784 static const char*
785 sig_status_to_string( GpgmeSigStat status )
786 {
787     const char *result;
788
789     switch (status) {
790       case GPGME_SIG_STAT_NONE:
791         result = "Oops: Signature not verified";
792         break;
793       case GPGME_SIG_STAT_NOSIG:
794         result = "No signature found";
795         break;
796       case GPGME_SIG_STAT_GOOD:
797         result = "Good signature";
798         break;
799       case GPGME_SIG_STAT_BAD:
800         result = "BAD signature";
801         break;
802       case GPGME_SIG_STAT_NOKEY:
803         result = "No public key to verify the signature";
804         break;
805       case GPGME_SIG_STAT_ERROR:
806         result = "Error verifying the signature";
807         break;
808       case GPGME_SIG_STAT_DIFF:
809         result = "Different results for signatures";
810         break;
811       default:
812         result = "Error: Unknown status";
813         break;
814     }
815
816     return result;
817 }
818
819
820 bool checkMessageSignature( const char* ciphertext,
821                             const char* signaturetext,
822                             struct SignatureMetaData* sigmeta )
823 {
824     GpgmeCtx ctx;
825     GpgmeSigStat status;
826     GpgmeData datapart, sigpart;
827     GpgmeError err;
828     GpgmeKey key;
829     time_t created;
830     int sig_idx = 0;
831     const char* statusStr;
832     const char* fpr;
833
834     gpgme_new( &ctx );
835     gpgme_data_new_from_mem( &datapart, ciphertext,
836                              1+strlen( ciphertext ), 1 );
837     gpgme_data_new_from_mem( &sigpart, signaturetext,
838                              1+strlen( signaturetext ), 1 );
839
840     gpgme_op_verify( ctx, sigpart, datapart, &status );
841     gpgme_data_release( datapart );
842     gpgme_data_release( sigpart );
843
844     /* Provide information in the sigmeta struct */
845     /* the status string */
846     statusStr = sig_status_to_string( status );
847     // PENDING(kalle) Handle out of memory
848     sigmeta->status = malloc( strlen( statusStr ) + 1 );
849     strcpy( sigmeta->status, statusStr );
850     sigmeta->status[strlen( statusStr )] = '\0';
851
852     // Extended information for any number of signatures.
853     fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
854     sigmeta->extended_info = 0;
855     while( fpr != NULL ) {
856         struct tm* ctime_val;
857         const char* sig_status;
858
859         // PENDING(kalle) Handle out of memory
860         sigmeta->extended_info = realloc( sigmeta->extended_info,
861                                           sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
862         // the creation time
863         // PENDING(kalle) Handle out of memory
864         sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
865         ctime_val = localtime( &created );
866         memcpy( sigmeta->extended_info[sig_idx].creation_time,
867                 ctime_val, sizeof( struct tm ) );
868
869         err = gpgme_get_sig_key (ctx, sig_idx, &key);
870         sig_status = sig_status_to_string( status );
871         // PENDING(kalle) Handle out of memory
872         sigmeta->extended_info[sig_idx].status_text = malloc( strlen( sig_status ) + 1 );
873         strcpy( sigmeta->extended_info[sig_idx].status_text,
874                 sig_status );
875         sigmeta->extended_info[sig_idx].status_text[strlen( sig_status )] = '\0';
876         // PENDING(kalle) Handle out of memory
877         sigmeta->extended_info[sig_idx].fingerprint = malloc( strlen( fpr ) + 1 );
878         strcpy( sigmeta->extended_info[sig_idx].fingerprint, fpr );
879         sigmeta->extended_info[sig_idx].fingerprint[strlen( fpr )] = '\0';
880
881         fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
882     }
883     sigmeta->extended_info_count = sig_idx;
884     sigmeta->nota_xml = gpgme_get_notation( ctx );
885     sigmeta->status_code = status;
886
887     gpgme_release( ctx );
888     return ( status == GPGME_SIG_STAT_GOOD );
889 }
890
891 bool storeCertificatesFromMessage(
892         const char* ciphertext ){ return true; }
893
894
895 bool encryptMessage( const char* cleartext,
896                      const char** ciphertext,
897                      const char* addressee )
898 {
899   GpgmeCtx ctx;
900   GpgmeError err;
901   GpgmeData gCiphertext, gPlaintext;
902   GpgmeRecipients rset;
903   size_t rCLen = 0;
904   char*  rCiph = 0;
905   bool   bOk   = false;
906
907   gpgme_new (&ctx);
908   gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
909
910   gpgme_set_armor (ctx, 1);
911   gpgme_set_textmode (ctx, 1);
912
913   gpgme_data_new_from_mem (&gPlaintext, cleartext,
914                             1+strlen( cleartext ), 1 );
915   err = gpgme_data_new ( &gCiphertext );
916
917   gpgme_recipients_new (&rset);
918   gpgme_recipients_add_name (rset, addressee);
919
920   err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
921   gpgme_recipients_release (rset);
922   gpgme_data_release (gPlaintext);
923
924   if( !err ) {
925     rCiph = gpgme_data_release_and_get_mem( gCiphertext,  &rCLen );
926     *ciphertext = malloc( rCLen + 1 );
927     if( *ciphertext ) {
928       if( rCLen ) {
929         bOk = true;
930         strncpy((char*)*ciphertext, rCiph, rCLen );
931       }
932       ((char*)(*ciphertext))[rCLen] = 0;
933     }
934     free( rCiph );
935   }
936   else {
937     gpgme_data_release ( gCiphertext );
938     *ciphertext = 0;
939     // hier fehlt eine Fehlerbehandlung: fuer einen Recipient nur ein
940     // untrusted key (oder gar keiner) gefunden wurde, verweigert gpg
941     // das signieren.
942   }
943
944   gpgme_release (ctx);
945
946   return bOk;
947 }
948
949
950 bool encryptAndSignMessage( const char* cleartext,
951           const char** ciphertext, const char* certificate,
952           struct SignatureMetaData* sigmeta ){ return true; }
953
954 bool decryptMessage( const char* ciphertext, const
955           char** cleartext, const char* certificate ){ return true; }
956
957 bool decryptAndCheckMessage( const char* ciphertext,
958           const char** cleartext, const char* certificate,
959           struct SignatureMetaData* sigmeta ){ return true; }
960
961
962 const char* requestCertificateDialog(){ return 0; }
963
964 bool requestDecentralCertificate( const char* name, const char*
965           email, const char* organization, const char* department,
966           const char* ca_address ){ return true; }
967
968 bool requestCentralCertificateAndPSE( const char* name,
969           const char* email, const char* organization, const char* department,
970           const char* ca_address ){ return true; }
971
972 bool createPSE(){ return true; }
973
974 bool registerCertificate( const char* certificate ){ return true; }
975
976 bool requestCertificateProlongation( const char* certificate,
977                                      const char* ca_address ){ return true; }
978
979 const char* certificateChain(){ return 0; }
980
981 bool deleteCertificate( const char* certificate ){ return true; }
982
983 bool archiveCertificate( const char* certificate ){ return true; }
984
985
986 const char* displayCRL(){ return 0; }
987
988 void updateCRL(){}