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