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