00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031 #include "kleo/oidmap.h"
00032
00033 #include <gpgmepp/context.h>
00034 #include <gpgmepp/data.h>
00035 #include <gpgmepp/importresult.h>
00036
00054 #include <qstring.h>
00055
00056 #include <string>
00057 #include <vector>
00058 #include <algorithm>
00059 #include <iostream>
00060 #include <memory>
00061
00062 #include <stdio.h>
00063 #include <string.h>
00064 #include <strings.h>
00065 #include <assert.h>
00066 #include <errno.h>
00067 #include <time.h>
00068 #include <ctype.h>
00069 #include <locale.h>
00070
00071 #define __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO "Error: Cannot run checkMessageSignature() with cleartext == 0"
00072
00073
00074
00075
00076
00077
00078 #ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
00079 #define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
00080 #define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT false
00081 #define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME false
00082 #define GPGMEPLUG_ENCSIGN_CTYPE_MAIN ""
00083 #define GPGMEPLUG_ENCSIGN_CDISP_MAIN ""
00084 #define GPGMEPLUG_ENCSIGN_CTENC_MAIN ""
00085 #define GPGMEPLUG_ENCSIGN_CTYPE_VERSION ""
00086 #define GPGMEPLUG_ENCSIGN_CDISP_VERSION ""
00087 #define GPGMEPLUG_ENCSIGN_CTENC_VERSION ""
00088 #define GPGMEPLUG_ENCSIGN_BTEXT_VERSION ""
00089 #define GPGMEPLUG_ENCSIGN_CTYPE_CODE ""
00090 #define GPGMEPLUG_ENCSIGN_CDISP_CODE ""
00091 #define GPGMEPLUG_ENCSIGN_CTENC_CODE ""
00092 #define GPGMEPLUG_ENCSIGN_FLAT_PREFIX ""
00093 #define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR ""
00094 #define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX ""
00095 #endif
00096
00097 #include "cryptplug.h"
00098 #include <kdebug.h>
00099
00100 SMIMECryptPlug::SMIMECryptPlug() : CryptPlug() {
00101 GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_CMS;
00102 mProtocol = GpgME::Context::CMS;
00103
00104
00105
00106 GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false;
00107 GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = true;
00108 GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false;
00109 GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = "application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\"";
00110 GPGMEPLUG_OPA_SIGN_CDISP_MAIN = "attachment; filename=\"smime.p7m\"";
00111 GPGMEPLUG_OPA_SIGN_CTENC_MAIN = "base64";
00112 GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = "";
00113 GPGMEPLUG_OPA_SIGN_CDISP_VERSION = "";
00114 GPGMEPLUG_OPA_SIGN_CTENC_VERSION = "";
00115 GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = "";
00116 GPGMEPLUG_OPA_SIGN_CTYPE_CODE = "";
00117 GPGMEPLUG_OPA_SIGN_CDISP_CODE = "";
00118 GPGMEPLUG_OPA_SIGN_CTENC_CODE = "";
00119 GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = "";
00120 GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = "";
00121 GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = "";
00122
00123 GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true;
00124 GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true;
00125 GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true;
00126 GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1";
00127 GPGMEPLUG_DET_SIGN_CDISP_MAIN = "";
00128 GPGMEPLUG_DET_SIGN_CTENC_MAIN = "";
00129 GPGMEPLUG_DET_SIGN_CTYPE_VERSION = "";
00130 GPGMEPLUG_DET_SIGN_CDISP_VERSION = "";
00131 GPGMEPLUG_DET_SIGN_CTENC_VERSION = "";
00132 GPGMEPLUG_DET_SIGN_BTEXT_VERSION = "";
00133 GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pkcs7-signature; name=\"smime.p7s\"";
00134 GPGMEPLUG_DET_SIGN_CDISP_CODE = "attachment; filename=\"smime.p7s\"";
00135 GPGMEPLUG_DET_SIGN_CTENC_CODE = "base64";
00136 GPGMEPLUG_DET_SIGN_FLAT_PREFIX = "";
00137 GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = "";
00138 GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = "";
00139
00140 __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = true;
00141
00142
00143 GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false;
00144 GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true;
00145 GPGMEPLUG_ENC_MAKE_MULTI_MIME = false;
00146 GPGMEPLUG_ENC_CTYPE_MAIN = "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"";
00147 GPGMEPLUG_ENC_CDISP_MAIN = "attachment; filename=\"smime.p7m\"";
00148 GPGMEPLUG_ENC_CTENC_MAIN = "base64";
00149 GPGMEPLUG_ENC_CTYPE_VERSION = "";
00150 GPGMEPLUG_ENC_CDISP_VERSION = "";
00151 GPGMEPLUG_ENC_CTENC_VERSION = "";
00152 GPGMEPLUG_ENC_BTEXT_VERSION = "";
00153 GPGMEPLUG_ENC_CTYPE_CODE = "";
00154 GPGMEPLUG_ENC_CDISP_CODE = "";
00155 GPGMEPLUG_ENC_CTENC_CODE = "";
00156 GPGMEPLUG_ENC_FLAT_PREFIX = "";
00157 GPGMEPLUG_ENC_FLAT_SEPARATOR = "";
00158 GPGMEPLUG_ENC_FLAT_POSTFIX = "";
00159 __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = true;
00160 }
00161
00162 OpenPGPCryptPlug::OpenPGPCryptPlug() : CryptPlug() {
00163 GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_OpenPGP;
00164 mProtocol = GpgME::Context::OpenPGP;
00165
00166
00167
00168 GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false;
00169 GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = false;
00170 GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false;
00171 GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = "";
00172 GPGMEPLUG_OPA_SIGN_CDISP_MAIN = "";
00173 GPGMEPLUG_OPA_SIGN_CTENC_MAIN = "";
00174 GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = "";
00175 GPGMEPLUG_OPA_SIGN_CDISP_VERSION = "";
00176 GPGMEPLUG_OPA_SIGN_CTENC_VERSION = "";
00177 GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = "";
00178 GPGMEPLUG_OPA_SIGN_CTYPE_CODE = "";
00179 GPGMEPLUG_OPA_SIGN_CDISP_CODE = "";
00180 GPGMEPLUG_OPA_SIGN_CTENC_CODE = "";
00181 GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = "";
00182 GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = "";
00183 GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = "";
00184
00185 GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true;
00186 GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true;
00187 GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true;
00188 GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pgp-signature\"; micalg=pgp-sha1";
00189 GPGMEPLUG_DET_SIGN_CDISP_MAIN = "";
00190 GPGMEPLUG_DET_SIGN_CTENC_MAIN = "";
00191 GPGMEPLUG_DET_SIGN_CTYPE_VERSION = "";
00192 GPGMEPLUG_DET_SIGN_CDISP_VERSION = "";
00193 GPGMEPLUG_DET_SIGN_CTENC_VERSION = "";
00194 GPGMEPLUG_DET_SIGN_BTEXT_VERSION = "";
00195 GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pgp-signature";
00196 GPGMEPLUG_DET_SIGN_CDISP_CODE = "";
00197 GPGMEPLUG_DET_SIGN_CTENC_CODE = "";
00198 GPGMEPLUG_DET_SIGN_FLAT_PREFIX = "";
00199 GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = "";
00200 GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = "";
00201
00202 __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = false;
00203
00204
00205 GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false;
00206 GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true;
00207 GPGMEPLUG_ENC_MAKE_MULTI_MIME = true;
00208 GPGMEPLUG_ENC_CTYPE_MAIN = "multipart/encrypted; protocol=\"application/pgp-encrypted\"";
00209 GPGMEPLUG_ENC_CDISP_MAIN = "";
00210 GPGMEPLUG_ENC_CTENC_MAIN = "";
00211 GPGMEPLUG_ENC_CTYPE_VERSION = "application/pgp-encrypted";
00212 GPGMEPLUG_ENC_CDISP_VERSION = "attachment";
00213 GPGMEPLUG_ENC_CTENC_VERSION = "";
00214 GPGMEPLUG_ENC_BTEXT_VERSION = "Version: 1";
00215 GPGMEPLUG_ENC_CTYPE_CODE = "application/octet-stream";
00216 GPGMEPLUG_ENC_CDISP_CODE = "inline; filename=\"msg.asc\"";
00217 GPGMEPLUG_ENC_CTENC_CODE = "";
00218 GPGMEPLUG_ENC_FLAT_PREFIX = "";
00219 GPGMEPLUG_ENC_FLAT_SEPARATOR = "";
00220 GPGMEPLUG_ENC_FLAT_POSTFIX = "";
00221 __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = false;
00222 }
00223
00224 #define days_from_seconds(x) ((x)/86400)
00225
00226
00227 #define MAX_GPGME_IDX 20
00228
00229
00230 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
00231 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
00232 #define hexdigitp(a) (digitp (a) \
00233 || (*(a) >= 'A' && *(a) <= 'F') \
00234 || (*(a) >= 'a' && *(a) <= 'f'))
00235
00236 #define atoi_1(p) (*(p) - '0' )
00237 #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
00238 #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
00239 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
00240 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
00241 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
00242
00243 static void *
00244 xmalloc (size_t n)
00245 {
00246 void *p = malloc (n);
00247 if (!p)
00248 {
00249 fputs ("\nfatal: out of core\n", stderr);
00250 exit (4);
00251 }
00252 return p;
00253 }
00254
00255
00256
00257
00258 static char *
00259 xstrdup (const char *string)
00260 {
00261 char *p = (char*)xmalloc (strlen (string)+1);
00262 strcpy (p, string);
00263 return p;
00264 }
00265
00266
00267
00268 static void
00269 my_gpgme_key_release (gpgme_key_t key)
00270 {
00271 if (key)
00272 gpgme_key_release (key);
00273 }
00274
00275
00276 CryptPlug::CryptPlug() {
00277 }
00278
00279 CryptPlug::~CryptPlug() {
00280 }
00281
00282 bool CryptPlug::initialize() {
00283 GpgME::setDefaultLocale( LC_CTYPE, setlocale( LC_CTYPE, 0 ) );
00284 GpgME::setDefaultLocale( LC_MESSAGES, setlocale( LC_MESSAGES, 0 ) );
00285 return (gpgme_engine_check_version (GPGMEPLUG_PROTOCOL) == GPG_ERR_NO_ERROR);
00286 }
00287
00288
00289 bool CryptPlug::hasFeature( Feature flag )
00290 {
00291
00292 switch ( flag ) {
00293 case Feature_SignMessages:
00294 case Feature_VerifySignatures:
00295 case Feature_EncryptMessages:
00296 case Feature_DecryptMessages:
00297 case Feature_SendCertificates:
00298 case Feature_PinEntrySettings:
00299 case Feature_StoreMessagesWithSigs:
00300 case Feature_EncryptionCRLs:
00301 case Feature_StoreMessagesEncrypted:
00302 case Feature_CheckCertificatePath:
00303 return true;
00304 case Feature_WarnSignCertificateExpiry:
00305 case Feature_WarnSignEmailNotInCertificate:
00306 case Feature_WarnEncryptCertificateExpiry:
00307 case Feature_WarnEncryptEmailNotInCertificate:
00308 return GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS;
00309
00310 case Feature_CRLDirectoryService:
00311 case Feature_CertificateDirectoryService:
00312 case Feature_undef:
00313 default:
00314 return false;
00315 }
00316 }
00317
00318
00319
00320
00321
00322
00323 int CryptPlug::interfaceVersion (int *min_version)
00324 {
00325 if (min_version)
00326 *min_version = 0;
00327 return 1;
00328 }
00329
00330 static
00331 int getAttrExpireFormKey( gpgme_key_t* rKey)
00332 {
00333 int daysLeft = CRYPTPLUG_CERT_DOES_NEVER_EXPIRE;
00334 if ( rKey && *rKey && (*rKey)->subkeys && (*rKey)->subkeys->expires >= 0 ) {
00335 time_t expire_time = (*rKey)->subkeys->expires;
00336 time_t cur_time = time (NULL);
00337 if( cur_time > expire_time ) {
00338 daysLeft = days_from_seconds(cur_time - expire_time);
00339 daysLeft *= -1;
00340 }
00341 else
00342 daysLeft = days_from_seconds(expire_time - cur_time);
00343 }
00344 return daysLeft;
00345 }
00346
00347
00348 static
00349 void storeNewCharPtr( char** dest, const char* src )
00350 {
00351 int sLen = strlen( src );
00352 *dest = (char*)xmalloc( sLen + 1 );
00353 strcpy( *dest, src );
00354 }
00355
00356
00357 bool CryptPlug::signMessage( const char* cleartext,
00358 char** ciphertext,
00359 const size_t* cipherLen,
00360 const char* certificate,
00361 struct StructuringInfo* structuring,
00362 int* errId,
00363 char** errTxt,
00364 SendCertificates sendCertificates,
00365 SignatureCompoundMode signatureCompoundMode )
00366 {
00367 bool bIsOpaque;
00368 gpgme_ctx_t ctx;
00369 gpgme_error_t err;
00370 gpgme_key_t rKey;
00371 gpgme_data_t data, sig;
00372 char* rSig = 0;
00373 bool bOk = false;
00374 int sendCerts = 1;
00375
00376 init_StructuringInfo( structuring );
00377
00378 if( !ciphertext )
00379 return false;
00380
00381 err = gpgme_new (&ctx);
00382 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00383
00384 gpgme_set_armor (ctx, __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ? 0 : 1);
00385
00386
00387 switch ( sendCertificates ) {
00388 case SendCert_undef:
00389 break;
00390 case SendCert_DontSend:
00391 sendCerts = 0;
00392 break;
00393 case SendCert_SendOwn:
00394 sendCerts = 1;
00395 break;
00396 case SendCert_SendChainWithoutRoot:
00397 sendCerts = -2;
00398 break;
00399 case SendCert_SendChainWithRoot:
00400 sendCerts = -1;
00401 break;
00402 default:
00403 sendCerts = 0;
00404 break;
00405 }
00406 gpgme_set_include_certs (ctx, sendCerts);
00407
00408
00409 if (certificate != 0) {
00410 err = gpgme_op_keylist_start(ctx, certificate, 0);
00411 while (!err) {
00412 err = gpgme_op_keylist_next(ctx, &rKey);
00413 if (!err) {
00414 if ( rKey && rKey->can_sign ) {
00415
00416 gpgme_signers_clear(ctx);
00417
00418 gpgme_signers_add(ctx, rKey);
00419
00420 break;
00421 }
00422 }
00423 }
00424 gpgme_op_keylist_end(ctx);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 gpgme_data_new_from_mem (&data, cleartext,
00434 strlen( cleartext ), 1 );
00435 gpgme_data_new ( &sig );
00436
00437
00438
00439 if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
00440 bIsOpaque = (signatureCompoundMode == SignatureCompoundMode_Opaque);
00441 else
00442 bIsOpaque = false;
00443
00444 err = gpgme_op_sign ( ctx,
00445 data,
00446 sig,
00447 bIsOpaque
00448 ? GPGME_SIG_MODE_NORMAL
00449 : GPGME_SIG_MODE_DETACH );
00450
00451 if ( !err ) {
00452 if( __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ) {
00453 *ciphertext = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
00454 bOk = true;
00455 }
00456 else {
00457 rSig = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
00458 *ciphertext = (char*)malloc( *cipherLen + 1 );
00459 if( *ciphertext ) {
00460 if( *cipherLen ) {
00461 bOk = true;
00462 strncpy((char*)*ciphertext, rSig, *cipherLen );
00463 }
00464 (*ciphertext)[*cipherLen] = '\0';
00465 }
00466 free( rSig );
00467 }
00468 }
00469 else {
00470 gpgme_data_release( sig );
00471
00472
00473
00474
00475
00476
00477
00478 *ciphertext = 0;
00479 fprintf( stderr, "\n\n gpgme_op_sign() returned this error code: %i\n\n", err );
00480 if( errId )
00481 *errId = err;
00482 if( errTxt ) {
00483 const char* _errTxt = gpgme_strerror( err );
00484 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
00485 if( *errTxt )
00486 strcpy(*errTxt, _errTxt );
00487 }
00488
00489
00490
00491 }
00492 gpgme_data_release( data );
00493 gpgme_release (ctx);
00494
00495 if( bOk && structuring ) {
00496 if( bIsOpaque ) {
00497 structuring->includeCleartext = GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT;
00498 structuring->makeMimeObject = GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT;
00499 if( structuring->makeMimeObject ) {
00500 structuring->makeMultiMime = GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME;
00501 storeNewCharPtr( &structuring->contentTypeMain,
00502 GPGMEPLUG_OPA_SIGN_CTYPE_MAIN );
00503 storeNewCharPtr( &structuring->contentDispMain,
00504 GPGMEPLUG_OPA_SIGN_CDISP_MAIN );
00505 storeNewCharPtr( &structuring->contentTEncMain,
00506 GPGMEPLUG_OPA_SIGN_CTENC_MAIN );
00507 if( structuring->makeMultiMime ) {
00508 storeNewCharPtr( &structuring->contentTypeVersion,
00509 GPGMEPLUG_OPA_SIGN_CTYPE_VERSION );
00510 storeNewCharPtr( &structuring->contentDispVersion,
00511 GPGMEPLUG_OPA_SIGN_CDISP_VERSION );
00512 storeNewCharPtr( &structuring->contentTEncVersion,
00513 GPGMEPLUG_OPA_SIGN_CTENC_VERSION );
00514 storeNewCharPtr( &structuring->bodyTextVersion,
00515 GPGMEPLUG_OPA_SIGN_BTEXT_VERSION );
00516 storeNewCharPtr( &structuring->contentTypeCode,
00517 GPGMEPLUG_OPA_SIGN_CTYPE_CODE );
00518 storeNewCharPtr( &structuring->contentDispCode,
00519 GPGMEPLUG_OPA_SIGN_CDISP_CODE );
00520 storeNewCharPtr( &structuring->contentTEncCode,
00521 GPGMEPLUG_OPA_SIGN_CTENC_CODE );
00522 }
00523 } else {
00524 storeNewCharPtr( &structuring->flatTextPrefix,
00525 GPGMEPLUG_OPA_SIGN_FLAT_PREFIX );
00526 storeNewCharPtr( &structuring->flatTextSeparator,
00527 GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR );
00528 storeNewCharPtr( &structuring->flatTextPostfix,
00529 GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX );
00530 }
00531 } else {
00532 structuring->includeCleartext = GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT;
00533 structuring->makeMimeObject = GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT;
00534 if( structuring->makeMimeObject ) {
00535 structuring->makeMultiMime = GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME;
00536 storeNewCharPtr( &structuring->contentTypeMain,
00537 GPGMEPLUG_DET_SIGN_CTYPE_MAIN );
00538 storeNewCharPtr( &structuring->contentDispMain,
00539 GPGMEPLUG_DET_SIGN_CDISP_MAIN );
00540 storeNewCharPtr( &structuring->contentTEncMain,
00541 GPGMEPLUG_DET_SIGN_CTENC_MAIN );
00542 if( structuring->makeMultiMime ) {
00543 storeNewCharPtr( &structuring->contentTypeVersion,
00544 GPGMEPLUG_DET_SIGN_CTYPE_VERSION );
00545 storeNewCharPtr( &structuring->contentDispVersion,
00546 GPGMEPLUG_DET_SIGN_CDISP_VERSION );
00547 storeNewCharPtr( &structuring->contentTEncVersion,
00548 GPGMEPLUG_DET_SIGN_CTENC_VERSION );
00549 storeNewCharPtr( &structuring->bodyTextVersion,
00550 GPGMEPLUG_DET_SIGN_BTEXT_VERSION );
00551 storeNewCharPtr( &structuring->contentTypeCode,
00552 GPGMEPLUG_DET_SIGN_CTYPE_CODE );
00553 storeNewCharPtr( &structuring->contentDispCode,
00554 GPGMEPLUG_DET_SIGN_CDISP_CODE );
00555 storeNewCharPtr( &structuring->contentTEncCode,
00556 GPGMEPLUG_DET_SIGN_CTENC_CODE );
00557 }
00558 } else {
00559 storeNewCharPtr( &structuring->flatTextPrefix,
00560 GPGMEPLUG_DET_SIGN_FLAT_PREFIX );
00561 storeNewCharPtr( &structuring->flatTextSeparator,
00562 GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR );
00563 storeNewCharPtr( &structuring->flatTextPostfix,
00564 GPGMEPLUG_DET_SIGN_FLAT_POSTFIX );
00565 }
00566 }
00567 }
00568 return bOk;
00569 }
00570
00571
00572
00573 bool CryptPlug::storeCertificatesFromMessage( const char* ){ return true; }
00574
00575
00576
00577
00578
00579 static char* parseAddress( char* address )
00580 {
00581 char* result = address;
00582 char* i;
00583 char* j;
00584 if( !result ) return result;
00585 i = index( address, '<' );
00586 if( i ) {
00587 j = index( i+1, '>' );
00588 if( j == NULL ) j = address+strlen(address);
00589 result = (char*)xmalloc( j-i );
00590 strncpy( result, i+1, j-i-1 );
00591 result[j-i-1] = '\0';
00592 free( address );
00593 } else {
00594 i = address;
00595 j = i+strlen(address);
00596 }
00597 {
00598
00599 char* k = result+(j-i-1);
00600 char* l = result;
00601 while( isspace( *l ) ) ++l;
00602 while( isspace( *k ) ) --k;
00603 if( l != result || k != result+(j-i-1) ) {
00604 char* result2 = (char*)xmalloc( k-l+2 );
00605 strncpy( result2, l, k-l+1 );
00606 result2[k-l+1] = '\0';
00607 free(result);
00608 result = result2;
00609 }
00610 }
00611 return result;
00612 }
00613
00614 static char* nextAddress( const char** address )
00615 {
00616 const char *start = *address;
00617 char* result = NULL;
00618 int quote = 0;
00619 int comment = 0;
00620 int found = 0;
00621 if( *address == NULL ) return NULL;
00622 while( **address ) {
00623
00624 switch( **address ) {
00625 case '\\':
00626 ++(*address);
00627 break;
00628 case '"':
00629 if( comment == 0 ) {
00630 if( quote > 0 ) --quote;
00631 else ++quote;
00632 }
00633 break;
00634 case '(':
00635 if( quote == 0 ) ++comment;
00636 break;
00637 case ')':
00638 if( quote == 0 ) --comment;
00639 break;
00640 case '\0':
00641 case '\1':
00642 if( quote == 0 && comment == 0 ) {
00643 found = 1;
00644 }
00645 break;
00646 }
00647 ++(*address);
00648 if( found ) break;
00649 }
00650 if( found || **address == 0 ) {
00651 size_t len;
00652 len = *address - start;
00653 if( len > 0 ) {
00654 if( **address != 0 ) --len;
00655 result = (char*)xmalloc( len*sizeof(char)+1 );
00656 strncpy( result, start, len );
00657 result[len] = '\0';
00658 }
00659 }
00660 return parseAddress(result);
00661 }
00662
00663 bool CryptPlug::encryptMessage( const char* cleartext,
00664 const char** ciphertext,
00665 const size_t* cipherLen,
00666 const char* certificate,
00667 struct StructuringInfo* structuring,
00668 int* errId,
00669 char** errTxt )
00670 {
00671 gpgme_ctx_t ctx;
00672 gpgme_error_t err;
00673 gpgme_data_t gCiphertext, gPlaintext;
00674 char* rCiph = 0;
00675 bool bOk = false;
00676
00677 init_StructuringInfo( structuring );
00678
00679 gpgme_new (&ctx);
00680 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00681
00682 gpgme_set_armor (ctx, __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ? 0 : 1);
00683
00684
00685 gpgme_data_new_from_mem (&gPlaintext, cleartext,
00686 1+strlen( cleartext ), 1 );
00687 err = gpgme_data_new ( &gCiphertext );
00688
00689
00690 std::vector<char*> recips;
00691
00692 {
00693 const char* p = certificate;
00694 char* tok;
00695 while( (tok = nextAddress( &p ) ) != 0 ) {
00696 fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
00697 recips.push_back( tok );
00698 }
00699 }
00700
00701 recips.push_back( 0 );
00702 const char ** patterns = new const char*[ recips.size() ];
00703 const char ** patterns_it = patterns;
00704 std::copy( recips.begin(), recips.end(), patterns_it );
00705 recips.pop_back();
00706
00707 std::vector<gpgme_key_t> keys;
00708 #if 0 // BROKEN FOR FINGERPRINTS
00709 err = gpgme_op_keylist_ext_start( ctx, patterns, 0, 0 );
00710 while ( !err ) {
00711 gpgme_key_t key = 0;
00712 err = gpgme_op_keylist_next( ctx, &key );
00713 keys.push_back( key );
00714 }
00715 if ( gpg_err_code( err ) == GPG_ERR_EOF )
00716 err = GPG_ERR_NO_ERROR;
00717 gpgme_op_keylist_end( ctx );
00718 #else
00719 for ( const char ** pit = patterns ; *pit && !err ; ++pit ) {
00720 gpgme_key_t key = 0;
00721 err = gpgme_get_key( ctx, *pit, &key, false );
00722 if ( key )
00723 keys.push_back( key );
00724 }
00725 #endif
00726
00727 keys.push_back( 0 );
00728 gpgme_key_t * rset = new gpgme_key_t[ keys.size() ];
00729 gpgme_key_t * rset_it = rset;
00730 std::copy( keys.begin(), keys.end(), rset_it );
00731 keys.pop_back();
00732
00733 std::for_each( recips.begin(), recips.end(), &free );
00734 delete[] patterns;
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 if ( !err )
00760 err = gpgme_op_encrypt (ctx, rset, (gpgme_encrypt_flags_t)0, gPlaintext, gCiphertext );
00761 if( err ) {
00762 fprintf( stderr, "\ngpgme_op_encrypt() returned this error code: %i\n", err );
00763 if( errId )
00764 *errId = err;
00765 if( errTxt ) {
00766 const char* _errTxt = gpgme_strerror( err );
00767 const size_t errTxtLen = strlen( _errTxt ) + 100;
00768 *errTxt = (char*)malloc( errTxtLen + 1 );
00769 if( *errTxt ) {
00770 std::string str = _errTxt;
00771 gpgme_encrypt_result_t opInfo = gpgme_op_encrypt_result( ctx );
00772 if ( opInfo && opInfo->invalid_recipients ) {
00773 str += " - ";
00774 str += gpgme_strerror( opInfo->invalid_recipients->reason );
00775
00776 }
00777 strncmp( *errTxt, str.c_str(), errTxtLen );
00778 (*errTxt)[errTxtLen] = '\0';
00779 }
00780 }
00781 }
00782
00783 std::for_each( keys.begin(), keys.end(), &my_gpgme_key_release );
00784 delete[] rset;
00785 gpgme_data_release (gPlaintext);
00786
00787 if( !err ) {
00788 if( __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ) {
00789 *ciphertext = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
00790 bOk = true;
00791 }
00792 else {
00793 rCiph = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
00794 *ciphertext = (char*)malloc( *cipherLen + 1 );
00795 if( *ciphertext ) {
00796 if( *cipherLen ) {
00797 bOk = true;
00798 strncpy((char*)*ciphertext, rCiph, *cipherLen );
00799 }
00800 ((char*)(*ciphertext))[*cipherLen] = 0;
00801 }
00802 free( rCiph );
00803 }
00804 }
00805 else {
00806 gpgme_data_release ( gCiphertext );
00807 *ciphertext = 0;
00808
00809
00810
00811
00812
00813 }
00814
00815 gpgme_release (ctx);
00816
00817 fflush( stderr );
00818
00819 if( bOk && structuring ) {
00820 structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
00821 structuring->makeMimeObject = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
00822 if( structuring->makeMimeObject ) {
00823 structuring->makeMultiMime = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
00824 storeNewCharPtr( &structuring->contentTypeMain,
00825 GPGMEPLUG_ENC_CTYPE_MAIN );
00826 storeNewCharPtr( &structuring->contentDispMain,
00827 GPGMEPLUG_ENC_CDISP_MAIN );
00828 storeNewCharPtr( &structuring->contentTEncMain,
00829 GPGMEPLUG_ENC_CTENC_MAIN );
00830 if( structuring->makeMultiMime ) {
00831 storeNewCharPtr( &structuring->contentTypeVersion,
00832 GPGMEPLUG_ENC_CTYPE_VERSION );
00833 storeNewCharPtr( &structuring->contentDispVersion,
00834 GPGMEPLUG_ENC_CDISP_VERSION );
00835 storeNewCharPtr( &structuring->contentTEncVersion,
00836 GPGMEPLUG_ENC_CTENC_VERSION );
00837 storeNewCharPtr( &structuring->bodyTextVersion,
00838 GPGMEPLUG_ENC_BTEXT_VERSION );
00839 storeNewCharPtr( &structuring->contentTypeCode,
00840 GPGMEPLUG_ENC_CTYPE_CODE );
00841 storeNewCharPtr( &structuring->contentDispCode,
00842 GPGMEPLUG_ENC_CDISP_CODE );
00843 storeNewCharPtr( &structuring->contentTEncCode,
00844 GPGMEPLUG_ENC_CTENC_CODE );
00845 }
00846 } else {
00847 storeNewCharPtr( &structuring->flatTextPrefix,
00848 GPGMEPLUG_ENC_FLAT_PREFIX );
00849 storeNewCharPtr( &structuring->flatTextSeparator,
00850 GPGMEPLUG_ENC_FLAT_SEPARATOR );
00851 storeNewCharPtr( &structuring->flatTextPostfix,
00852 GPGMEPLUG_ENC_FLAT_POSTFIX );
00853 }
00854 }
00855 return bOk;
00856 }
00857
00858
00859 bool CryptPlug::encryptAndSignMessage( const char* ,
00860 const char** ,
00861 const char* ,
00862 struct StructuringInfo* structuring )
00863 {
00864 bool bOk;
00865
00866 init_StructuringInfo( structuring );
00867
00868 bOk = false;
00869
00870
00871
00872 if( bOk && structuring ) {
00873 structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
00874 structuring->makeMimeObject = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
00875 if( structuring->makeMimeObject ) {
00876 structuring->makeMultiMime = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
00877 storeNewCharPtr( &structuring->contentTypeMain,
00878 GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
00879 storeNewCharPtr( &structuring->contentDispMain,
00880 GPGMEPLUG_ENCSIGN_CDISP_MAIN );
00881 storeNewCharPtr( &structuring->contentTEncMain,
00882 GPGMEPLUG_ENCSIGN_CTENC_MAIN );
00883 if( structuring->makeMultiMime ) {
00884 storeNewCharPtr( &structuring->contentTypeVersion,
00885 GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
00886 storeNewCharPtr( &structuring->contentDispVersion,
00887 GPGMEPLUG_ENCSIGN_CDISP_VERSION );
00888 storeNewCharPtr( &structuring->contentTEncVersion,
00889 GPGMEPLUG_ENCSIGN_CTENC_VERSION );
00890 storeNewCharPtr( &structuring->bodyTextVersion,
00891 GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
00892 storeNewCharPtr( &structuring->contentTypeCode,
00893 GPGMEPLUG_ENCSIGN_CTYPE_CODE );
00894 storeNewCharPtr( &structuring->contentDispCode,
00895 GPGMEPLUG_ENCSIGN_CDISP_CODE );
00896 storeNewCharPtr( &structuring->contentTEncCode,
00897 GPGMEPLUG_ENCSIGN_CTENC_CODE );
00898 }
00899 } else {
00900 storeNewCharPtr( &structuring->flatTextPrefix,
00901 GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
00902 storeNewCharPtr( &structuring->flatTextSeparator,
00903 GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
00904 storeNewCharPtr( &structuring->flatTextPostfix,
00905 GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
00906 }
00907 }
00908 return bOk;
00909 }
00910
00911
00912 bool CryptPlug::decryptMessage( const char* ciphertext,
00913 bool cipherIsBinary,
00914 int cipherLen,
00915 const char** cleartext,
00916 const char* ,
00917 int* errId,
00918 char** errTxt )
00919 {
00920 gpgme_ctx_t ctx;
00921 gpgme_error_t err;
00922 gpgme_data_t gCiphertext, gPlaintext;
00923 size_t rCLen = 0;
00924 char* rCiph = 0;
00925 bool bOk = false;
00926
00927 if( !ciphertext )
00928 return false;
00929
00930 err = gpgme_new (&ctx);
00931 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00932
00933 gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
00934
00935
00936
00937
00938
00939 gpgme_data_new_from_mem( &gCiphertext,
00940 ciphertext,
00941 cipherIsBinary
00942 ? cipherLen
00943 : strlen( ciphertext ),
00944 1 );
00945
00946 gpgme_data_new( &gPlaintext );
00947
00948 err = gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
00949 if( err ) {
00950 fprintf( stderr, "\ngpgme_op_decrypt() returned this error code: %i\n\n", err );
00951 if( errId )
00952 *errId = err;
00953 if( errTxt ) {
00954 const char* _errTxt = gpgme_strerror( err );
00955 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
00956 if( *errTxt )
00957 strcpy(*errTxt, _errTxt );
00958 }
00959 }
00960
00961 gpgme_data_release( gCiphertext );
00962
00963 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
00964
00965 *cleartext = (char*)malloc( rCLen + 1 );
00966 if( *cleartext ) {
00967 if( rCLen ) {
00968 bOk = true;
00969 strncpy((char*)*cleartext, rCiph, rCLen );
00970 }
00971 ((char*)(*cleartext))[rCLen] = 0;
00972 }
00973
00974 free( rCiph );
00975 gpgme_release( ctx );
00976 return bOk;
00977 }
00978
00979
00980 static char *
00981 trim_trailing_spaces( char *string )
00982 {
00983 char *p, *mark;
00984
00985 for( mark = NULL, p = string; *p; p++ ) {
00986 if( isspace( *p ) ) {
00987 if( !mark )
00988 mark = p;
00989 }
00990 else
00991 mark = NULL;
00992 }
00993 if( mark )
00994 *mark = '\0' ;
00995
00996 return string ;
00997 }
00998
00999
01000
01001
01002 static const unsigned char *
01003 parse_dn_part (CryptPlug::DnPair *array, const unsigned char *string)
01004 {
01005 const unsigned char *s, *s1;
01006 size_t n;
01007 char *p;
01008
01009
01010 for (s = string+1; *s && *s != '='; s++)
01011 ;
01012 if (!*s)
01013 return NULL;
01014 n = s - string;
01015 if (!n)
01016 return NULL;
01017 p = (char*)xmalloc (n+1);
01018
01019
01020 memcpy (p, string, n);
01021 p[n] = 0;
01022 trim_trailing_spaces ((char*)p);
01023
01024 for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
01025 if ( !strcasecmp ((char*)p, oidmap[i].oid) ) {
01026 free( p );
01027 p = xstrdup (oidmap[i].name);
01028 break;
01029 }
01030 array->key = p;
01031 string = s + 1;
01032
01033 if (*string == '#')
01034 {
01035 string++;
01036 for (s=string; hexdigitp (s); s++)
01037 s++;
01038 n = s - string;
01039 if (!n || (n & 1))
01040 return NULL;
01041 n /= 2;
01042 array->value = p = (char*)xmalloc (n+1);
01043
01044
01045 for (s1=string; n; s1 += 2, n--)
01046 *p++ = xtoi_2 (s1);
01047 *p = 0;
01048 }
01049 else
01050 {
01051 for (n=0, s=string; *s; s++)
01052 {
01053 if (*s == '\\')
01054 {
01055 s++;
01056 if (*s == ',' || *s == '=' || *s == '+'
01057 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
01058 || *s == '\\' || *s == '\"' || *s == ' ')
01059 n++;
01060 else if (hexdigitp (s) && hexdigitp (s+1))
01061 {
01062 s++;
01063 n++;
01064 }
01065 else
01066 return NULL;
01067 }
01068 else if (*s == '\"')
01069 return NULL;
01070 else if (*s == ',' || *s == '=' || *s == '+'
01071 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
01072 break;
01073 else
01074 n++;
01075 }
01076
01077 array->value = p = (char*)xmalloc (n+1);
01078
01079
01080 for (s=string; n; s++, n--)
01081 {
01082 if (*s == '\\')
01083 {
01084 s++;
01085 if (hexdigitp (s))
01086 {
01087 *p++ = xtoi_2 (s);
01088 s++;
01089 }
01090 else
01091 *p++ = *s;
01092 }
01093 else
01094 *p++ = *s;
01095 }
01096 *p = 0;
01097 }
01098 return s;
01099 }
01100
01101
01102
01103
01104
01105 static CryptPlug::DnPair *
01106 parse_dn (const unsigned char *string)
01107 {
01108 struct CryptPlug::DnPair *array;
01109 size_t arrayidx, arraysize;
01110
01111 if( !string )
01112 return NULL;
01113
01114 arraysize = 7;
01115 arrayidx = 0;
01116 array = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
01117
01118
01119 while (*string)
01120 {
01121 while (*string == ' ')
01122 string++;
01123 if (!*string)
01124 break;
01125 if (arrayidx >= arraysize)
01126 {
01127 struct CryptPlug::DnPair *a2;
01128
01129 arraysize += 5;
01130 a2 = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
01131 for (unsigned int i=0; i < arrayidx; i++)
01132 {
01133 a2[i].key = array[i].key;
01134 a2[i].value = array[i].value;
01135 }
01136 free (array);
01137 array = a2;
01138 }
01139 array[arrayidx].key = NULL;
01140 array[arrayidx].value = NULL;
01141 string = parse_dn_part (array+arrayidx, string);
01142 arrayidx++;
01143 if (!string)
01144 goto failure;
01145 while (*string == ' ')
01146 string++;
01147 if (*string && *string != ',' && *string != ';' && *string != '+')
01148 goto failure;
01149 if (*string)
01150 string++;
01151 }
01152 array[arrayidx].key = NULL;
01153 array[arrayidx].value = NULL;
01154 return array;
01155
01156 failure:
01157 for (unsigned i=0; i < arrayidx; i++)
01158 {
01159 free (array[i].key);
01160 free (array[i].value);
01161 }
01162 free (array);
01163 return NULL;
01164 }
01165
01166 static void
01167 add_dn_part( QCString& result, struct CryptPlug::DnPair& dnPair )
01168 {
01169
01170 QCString mappedPart( dnPair.key );
01171 for ( unsigned int i = 0 ; i < numOidMaps ; ++i ){
01172 if( !strcasecmp( dnPair.key, oidmap[i].oid ) ) {
01173 mappedPart = oidmap[i].name;
01174 break;
01175 }
01176 }
01177 result.append( mappedPart );
01178 result.append( "=" );
01179 result.append( dnPair.value );
01180 }
01181
01182 static int
01183 add_dn_parts( QCString& result, struct CryptPlug::DnPair* dn, const char* part )
01184 {
01185 int any = 0;
01186
01187 if( dn ) {
01188 for(; dn->key; ++dn ) {
01189 if( !strcmp( dn->key, part ) ) {
01190 if( any )
01191 result.append( "," );
01192 add_dn_part( result, *dn );
01193 any = 1;
01194 }
01195 }
01196 }
01197 return any;
01198 }
01199
01200 static char*
01201 reorder_dn( struct CryptPlug::DnPair *dn,
01202 char** attrOrder = 0,
01203 const char* unknownAttrsHandling = 0 )
01204 {
01205 struct CryptPlug::DnPair *dnOrg = dn;
01206
01207
01208 const char* defaultpart[] = {
01209 "CN", "S", "SN", "GN", "T", "UID",
01210 "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET",
01211 "L", "PC", "SP", "ST",
01212 "OU",
01213 "O",
01214 "C",
01215 NULL
01216 };
01217 const char** stdpart = attrOrder ? ((const char**)attrOrder) : defaultpart;
01218 int any=0, any2=0, found_X_=0, i;
01219 QCString result;
01220 QCString resultUnknowns;
01221
01222
01223 if( dn ){
01224 for(; dn->key; ++dn ) {
01225 for( i = 0; stdpart[i]; ++i ) {
01226 if( !strcmp( dn->key, stdpart[i] ) ) {
01227 break;
01228 }
01229 }
01230 if( !stdpart[i] ) {
01231 if( any2 )
01232 resultUnknowns.append( "," );
01233 add_dn_part( resultUnknowns, *dn );
01234 any2 = 1;
01235 }
01236 }
01237 dn = dnOrg;
01238 }
01239
01240
01241 if( unknownAttrsHandling &&
01242 !strcmp(unknownAttrsHandling, "PREFIX")
01243 && *resultUnknowns ){
01244 result.append( resultUnknowns );
01245 any = 1;
01246 }else{
01247 any = 0;
01248 }
01249
01250
01251 for( i = 0; stdpart[i]; ++i ) {
01252 dn = dnOrg;
01253 if( any ) {
01254 result.append( "," );
01255 }
01256 if( any2 &&
01257 !strcmp(stdpart[i], "_X_") &&
01258 unknownAttrsHandling &&
01259 !strcmp(unknownAttrsHandling, "INFIX") ){
01260 if ( !resultUnknowns.isEmpty() ) {
01261 result.append( resultUnknowns );
01262 any = 1;
01263 }
01264 found_X_ = 1;
01265 }else{
01266 any = add_dn_parts( result, dn, stdpart[i] );
01267 }
01268 }
01269
01270
01271 if( !unknownAttrsHandling ||
01272 !strcmp(unknownAttrsHandling, "POSTFIX") ||
01273 ( !strcmp(unknownAttrsHandling, "INFIX") && !found_X_ ) ){
01274 if( !resultUnknowns.isEmpty() ) {
01275 if( any ){
01276 result.append( "," );
01277 }
01278 result.append( resultUnknowns );
01279 }
01280 }
01281
01282 char* cResult = (char*)xmalloc( (result.length()+1)*sizeof(char) );
01283 if( result.isEmpty() )
01284 *cResult = 0;
01285 else
01286 strcpy( cResult, result );
01287 return cResult;
01288 }
01289
01290 struct CryptPlug::CertIterator {
01291 gpgme_ctx_t ctx;
01292 struct CertificateInfo info;
01293 };
01294
01295 CryptPlug::CertIterator*
01296 CryptPlug::startListCertificates( const char* pattern, int remote )
01297 {
01298 gpgme_error_t err;
01299 struct CertIterator* it;
01300 const char* patterns[] = { pattern, NULL };
01301 fprintf( stderr, "startListCertificates( \"%s\", %d )\n", pattern, remote );
01302
01303 it = (CertIterator*)xmalloc( sizeof( struct CertIterator ) );
01304
01305 err = gpgme_new (&(it->ctx));
01306
01307 if( err ) {
01308 free( it );
01309 return NULL;
01310 }
01311
01312 gpgme_set_protocol (it->ctx, GPGME_PROTOCOL_CMS);
01313 if( remote ) gpgme_set_keylist_mode ( it->ctx, GPGME_KEYLIST_MODE_EXTERN );
01314 else gpgme_set_keylist_mode ( it->ctx, GPGME_KEYLIST_MODE_LOCAL );
01315 err = gpgme_op_keylist_ext_start ( it->ctx, patterns, 0, 0);
01316 memset( &(it->info), 0, sizeof( struct CertificateInfo ) );
01317 if( err ) {
01318 fprintf( stderr, "gpgme_op_keylist_ext_start returned %d", err );
01319 endListCertificates( it );
01320 return NULL;
01321 }
01322 return it;
01323 }
01324
01325
01326 static void
01327 freeStringArray( char** c )
01328 {
01329 char** _c = c;
01330
01331 while( c && *c ) {
01332
01333 free( *c );
01334 ++c;
01335 }
01336 free( _c );
01337 }
01338
01339
01340 static void
01341 freeInfo( struct CryptPlug::CertificateInfo* info )
01342 {
01343 struct CryptPlug::DnPair* a = info->dnarray;
01344 assert( info );
01345 freeStringArray( info->userid );
01346 free( info->serial);
01347 free( info->fingerprint );
01348 free( info->issuer_org );
01349 free( info->issuer_reord );
01350 free( info->chainid );
01351 free( info->caps );
01352 while( a && a->key && a->value ) {
01353 free (a->key);
01354 free (a->value);
01355 ++a;
01356 }
01357 free (info->dnarray);
01358 memset( info, 0, sizeof( *info ) );
01359 }
01360
01361
01362
01363 static char* make_fingerprint( const char* fpr )
01364 {
01365 int len = strlen(fpr);
01366 int i = 0;
01367 char* result = (char*)xmalloc( (len + len/2 + 1)*sizeof(char) );
01368
01369 for(; *fpr; ++fpr, ++i ) {
01370 if( i%3 == 2) {
01371 result[i] = ':'; ++i;
01372 }
01373 result[i] = *fpr;
01374 }
01375 result[i] = 0;
01376 return result;
01377 }
01378
01379
01380 static const char *
01381 capabilities_to_string (gpgme_subkey_t subkey)
01382 {
01383 static const char *const strings[8] =
01384 {
01385 "",
01386 "c",
01387 "s",
01388 "sc",
01389 "e",
01390 "ec",
01391 "es",
01392 "esc"
01393 };
01394 return strings[(!!subkey->can_encrypt << 2)
01395 | (!!subkey->can_sign << 1)
01396 | (!!subkey->can_certify)];
01397 }
01398
01399 int
01400 CryptPlug::nextCertificate( CryptPlug::CertIterator* it,
01401 CryptPlug::CertificateInfo** result,
01402 char** attrOrder,
01403 const char* unknownAttrsHandling )
01404 {
01405 gpgme_error_t err;
01406 gpgme_key_t key;
01407 int retval = GPG_ERR_NO_ERROR;
01408 assert( it );
01409 fprintf( stderr, "nextCertificates( %p, %p )\n", it, result );
01410 err = gpgme_op_keylist_next ( it->ctx, &key);
01411 if( !err ) {
01412 int idx;
01413 const char* s = 0;
01414 unsigned long u;
01415 char* names[MAX_GPGME_IDX+1];
01416 struct DnPair *issuer_dn, *tmp_dn;
01417 retval = err;
01418 memset( names, 0, sizeof( names ) );
01419 freeInfo( &(it->info) );
01420
01421 std::cerr << "nextCertificate..." << std::endl;
01422 if ( key ) {
01423 idx = 0;
01424 for ( gpgme_user_id_t uid = key->uids ; uid && idx < MAX_GPGME_IDX ; uid = uid->next, ++idx )
01425 names[idx] = xstrdup( uid->uid );
01426 }
01427 std::cerr << "DEBUG: " << s << ":" << names[0] << std::endl;
01428 it->info.userid = (char**)xmalloc( sizeof( char* ) * (idx+1) );
01429 memset( it->info.userid, 0, sizeof( char* ) * (idx+1) );
01430 it->info.dnarray = 0;
01431 for( idx = 0; names[idx] != 0; ++idx ) {
01432
01433 struct DnPair* a = parse_dn( (unsigned char*)names[idx] );
01434 it->info.userid[idx] = reorder_dn( a, attrOrder, unknownAttrsHandling );
01435
01436 if( idx == 0 ) {
01437 it->info.userid_0_org = names[idx];
01438 it->info.dnarray = a;
01439 }else{
01440 free (names[idx]);
01441 names[idx] = NULL;
01442 while( a && a->key && a->value ) {
01443 free( a->key );
01444 free( a->value );
01445 ++a;
01446 }
01447 }
01448 }
01449 it->info.userid[idx] = 0;
01450
01451 s = key->issuer_serial;
01452 it->info.serial = s? xstrdup(s) : NULL;
01453
01454 s = key->subkeys ? key->subkeys->fpr : 0 ;
01455 it->info.fingerprint = make_fingerprint( s );
01456
01457 s = key->issuer_name;
01458 it->info.issuer_org = s? xstrdup(s): NULL;
01459 if( s ) {
01460 issuer_dn = tmp_dn = parse_dn( (const unsigned char*)s );
01461
01462 it->info.issuer_reord = reorder_dn( issuer_dn, attrOrder, unknownAttrsHandling );
01463 while( tmp_dn && tmp_dn->key ) {
01464 free( tmp_dn->key );
01465 free( tmp_dn->value );
01466 ++tmp_dn;
01467 }
01468 free( issuer_dn );
01469 issuer_dn = tmp_dn = NULL;
01470 } else {
01471 it->info.issuer_reord = NULL;
01472 }
01473 s = key->chain_id;
01474 it->info.chainid = s? xstrdup(s): NULL;
01475
01476 s = key->subkeys ? capabilities_to_string( key->subkeys ) : 0 ;
01477 it->info.caps = s? xstrdup(s) : NULL;
01478
01479 u = key->subkeys && key->subkeys->timestamp >= 0 ? key->subkeys->timestamp : 0 ;
01480 it->info.created = u;
01481
01482 u = key->subkeys && key->subkeys->expires >= 0 ? key->subkeys->expires : 0 ;
01483 it->info.expire = u;
01484
01485 u = key->secret;
01486 it->info.secret = u;
01487
01488 u = key->uids ? key->uids->invalid : 0 ;
01489 it->info.invalid = u;
01490
01491 u = key->subkeys ? key->subkeys->expired : 0 ;
01492 it->info.expired = u;
01493
01494 u = key->subkeys ? key->subkeys->disabled : 0 ;
01495 it->info.disabled = u;
01496
01497 my_gpgme_key_release (key);
01498
01499 *result = &(it->info);
01500 } else {
01501 *result = NULL;
01502 }
01503 return retval;
01504 }
01505
01506 int
01507 CryptPlug::endListCertificates( CryptPlug::CertIterator* it )
01508 {
01509 fprintf( stderr, "endListCertificates( %p )\n", it );
01510 assert(it);
01511 gpgme_keylist_result_t result = gpgme_op_keylist_result( it->ctx );
01512 int truncated = result && result->truncated;
01513 freeInfo( &(it->info) );
01514 gpgme_op_keylist_end(it->ctx);
01515 gpgme_release (it->ctx);
01516 free( it );
01517 return truncated;
01518 }
01519
01520 GpgME::ImportResult CryptPlug::importCertificateFromMem( const char* data, size_t length )
01521 {
01522 using namespace GpgME;
01523
01524 std::auto_ptr<Context> context( Context::createForProtocol( mProtocol ) );
01525 if ( !context.get() )
01526 return ImportResult();
01527
01528 Data keydata( data, length, false );
01529 if ( keydata.isNull() )
01530 return ImportResult();
01531
01532 return context->importKeys( keydata );
01533 }
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551 bool CryptPlug::findCertificates( const char* addressee,
01552 char** certificates,
01553 int* newSize,
01554 bool secretOnly,
01555 char** attrOrder,
01556 const char* unknownAttrsHandling )
01557 {
01558 #define MAXCERTS 1024
01559
01560 const char* delimiter = "\1";
01561 const char* openBracket = " (";
01562 const char* closeBracket = ")";
01563
01564 gpgme_ctx_t ctx;
01565 gpgme_error_t err;
01566 gpgme_key_t rKey;
01567 const char *s;
01568 const char *s2;
01569 char* dn;
01570 struct DnPair* a;
01571 int nFound = 0;
01572 int iFound = 0;
01573 int siz = 0;
01574 char* DNs[MAXCERTS];
01575 char* FPRs[MAXCERTS];
01576
01577 if( ! certificates ){
01578 fprintf( stderr, "gpgme: findCertificates called with invalid *certificates pointer\n" );
01579 return false;
01580 }
01581
01582 if( ! newSize ){
01583 fprintf( stderr, "gpgme: findCertificates called with invalid newSize pointer\n" );
01584 return false;
01585 }
01586
01587 *certificates = 0;
01588 *newSize = 0;
01589
01590
01591 gpgme_new (&ctx);
01592 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
01593 err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0);
01594 while( !err ) {
01595 err = gpgme_op_keylist_next(ctx, &rKey);
01596 if( !err ) {
01597 s = rKey && rKey->uids ? rKey->uids->uid : 0 ;
01598 if( s ) {
01599 dn = xstrdup( s );
01600 s2 = rKey && rKey->subkeys ? rKey->subkeys->fpr : 0 ;
01601 if( s2 ) {
01602 if( nFound )
01603 siz += strlen( delimiter );
01604
01605
01606
01607 a = parse_dn( (unsigned char*)dn );
01608 free( dn );
01609 dn = reorder_dn( a, attrOrder, unknownAttrsHandling );
01610
01611
01612
01613 siz += strlen( dn );
01614 siz += strlen( openBracket );
01615 siz += strlen( s2 );
01616 siz += strlen( closeBracket );
01617 DNs[ nFound ] = dn;
01618 dn = NULL;
01619 FPRs[nFound ] = xstrdup( s2 );
01620 ++nFound;
01621 if( nFound >= MAXCERTS ) {
01622 fprintf( stderr,
01623 "gpgme: findCertificates found too many certificates (%d)\n",
01624 MAXCERTS );
01625 break;
01626 }
01627 }
01628 free (dn);
01629 }
01630 }
01631 }
01632 gpgme_op_keylist_end( ctx );
01633 gpgme_release (ctx);
01634
01635
01636 if( 0 < siz ) {
01637
01638 ++siz;
01639 *newSize = siz;
01640
01641 *certificates = (char*)xmalloc( sizeof(char) * siz );
01642 memset( *certificates, 0, sizeof(char) * siz );
01643
01644 for (iFound=0; iFound < nFound; iFound++) {
01645 if( !iFound )
01646 strcpy(*certificates, DNs[iFound] );
01647 else {
01648 strcat(*certificates, delimiter );
01649 strcat(*certificates, DNs[iFound] );
01650 }
01651 strcat( *certificates, openBracket );
01652 strcat( *certificates, FPRs[iFound] );
01653 strcat( *certificates, closeBracket );
01654 free( DNs[ iFound ] );
01655 free( FPRs[iFound ] );
01656 }
01657 }
01658
01659 return ( 0 < nFound );
01660 }
01661
01662
01663 static gpgme_sig_stat_t
01664 sig_stat_from_status( gpgme_error_t err )
01665 {
01666 switch ( gpg_err_code(err) ) {
01667 case GPG_ERR_NO_ERROR:
01668 return GPGME_SIG_STAT_GOOD;
01669 case GPG_ERR_BAD_SIGNATURE:
01670 return GPGME_SIG_STAT_BAD;
01671 case GPG_ERR_NO_PUBKEY:
01672 return GPGME_SIG_STAT_NOKEY;
01673 case GPG_ERR_NO_DATA:
01674 return GPGME_SIG_STAT_NOSIG;
01675 case GPG_ERR_SIG_EXPIRED:
01676 return GPGME_SIG_STAT_GOOD_EXP;
01677 case GPG_ERR_KEY_EXPIRED:
01678 return GPGME_SIG_STAT_GOOD_EXPKEY;
01679 default:
01680 return GPGME_SIG_STAT_ERROR;
01681 }
01682 }
01683
01684
01685 static gpgme_sig_stat_t
01686 intersect_stati( gpgme_signature_t first )
01687 {
01688 if ( !first )
01689 return GPGME_SIG_STAT_NONE;
01690 gpgme_sig_stat_t result = sig_stat_from_status( first->status );
01691 for ( gpgme_signature_t sig = first->next ; sig ; sig = sig->next )
01692 if ( sig_stat_from_status( sig->status ) != result )
01693 return GPGME_SIG_STAT_DIFF;
01694 return result;
01695 }
01696
01697 static const char*
01698 sig_status_to_string( gpgme_sig_stat_t status )
01699 {
01700 const char *result;
01701
01702 switch (status) {
01703 case GPGME_SIG_STAT_NONE:
01704 result = "Oops: Signature not verified";
01705 break;
01706 case GPGME_SIG_STAT_NOSIG:
01707 result = "No signature found";
01708 break;
01709 case GPGME_SIG_STAT_GOOD:
01710 result = "Good signature";
01711 break;
01712 case GPGME_SIG_STAT_BAD:
01713 result = "BAD signature";
01714 break;
01715 case GPGME_SIG_STAT_NOKEY:
01716 result = "No public key to verify the signature";
01717 break;
01718 case GPGME_SIG_STAT_ERROR:
01719 result = "Error verifying the signature";
01720 break;
01721 case GPGME_SIG_STAT_DIFF:
01722 result = "Different results for signatures";
01723 break;
01724 default:
01725 result = "Error: Unknown status";
01726 break;
01727 }
01728
01729 return result;
01730 }
01731
01732
01733
01734 static
01735 void obtain_signature_information( gpgme_ctx_t ctx,
01736 gpgme_sig_stat_t & overallStatus,
01737 struct CryptPlug::SignatureMetaData* sigmeta,
01738 char** attrOrder,
01739 const char* unknownAttrsHandling,
01740 bool * signatureFound=0 )
01741 {
01742 gpgme_error_t err;
01743 unsigned long sumGPGME;
01744 SigStatusFlags sumPlug;
01745 struct CryptPlug::DnPair* a;
01746 int sig_idx=0;
01747
01748 assert( ctx );
01749 assert( sigmeta );
01750
01751 sigmeta->extended_info = 0;
01752 gpgme_verify_result_t result = gpgme_op_verify_result( ctx );
01753 if ( !result )
01754 return;
01755 for ( gpgme_signature_t signature = result->signatures ; signature ; signature = signature->next, ++sig_idx ) {
01756 void* alloc_return = realloc( sigmeta->extended_info,
01757 sizeof( CryptPlug::SignatureMetaDataExtendedInfo )
01758 * ( sig_idx + 1 ) );
01759 if ( !alloc_return )
01760 break;
01761 sigmeta->extended_info = (CryptPlug::SignatureMetaDataExtendedInfo*)alloc_return;
01762
01763
01764 CryptPlug::SignatureMetaDataExtendedInfo & this_info = sigmeta->extended_info[sig_idx];
01765
01766
01767 memset( &this_info, 0, sizeof (CryptPlug::SignatureMetaDataExtendedInfo) );
01768
01769
01770 if ( signature->timestamp ) {
01771 this_info.creation_time = (tm*)malloc( sizeof( struct tm ) );
01772 if ( this_info.creation_time ) {
01773 struct tm * ctime_val = localtime( (time_t*)&signature->timestamp );
01774 memcpy( this_info.creation_time,
01775 ctime_val, sizeof( struct tm ) );
01776 }
01777 }
01778
01779
01780 sumGPGME = signature->summary;
01781 fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
01782
01783 sumPlug = 0;
01784 #define convert(X) if ( sumGPGME & GPGME_SIGSUM_##X ) sumPlug |= SigStat_##X
01785 convert(VALID);
01786 convert(GREEN);
01787 convert(RED);
01788 convert(KEY_REVOKED);
01789 convert(KEY_EXPIRED);
01790 convert(SIG_EXPIRED);
01791 convert(KEY_MISSING);
01792 convert(CRL_MISSING);
01793 convert(CRL_TOO_OLD);
01794 convert(BAD_POLICY);
01795 convert(SYS_ERROR);
01796 #undef convert
01797 if( sumGPGME && !sumPlug )
01798 sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
01799 this_info.sigStatusFlags = sumPlug;
01800
01801
01802 if ( signature->fpr )
01803 storeNewCharPtr( &this_info.fingerprint, signature->fpr );
01804
01805
01806 this_info.validity = GPGME_VALIDITY_UNKNOWN;
01807
01808
01809 gpgme_key_t key = 0;
01810
01811
01812 err = gpgme_get_sig_key (ctx, sig_idx, &key);
01813
01814 if ( !err && key ) {
01815 const char* attr_string;
01816 unsigned long attr_ulong;
01817
01818
01819 attr_string = key->subkeys ? key->subkeys->keyid : 0 ;
01820 if ( attr_string )
01821 storeNewCharPtr( &this_info.keyid, attr_string );
01822
01823
01824 attr_string = key->subkeys ? gpgme_pubkey_algo_name( key->subkeys->pubkey_algo ) : 0 ;
01825 if (attr_string != 0)
01826 storeNewCharPtr( &this_info.algo, attr_string );
01827 attr_ulong = key->subkeys ? key->subkeys->pubkey_algo : 0 ;
01828 this_info.algo_num = attr_ulong;
01829
01830
01831 attr_ulong = key->uids ? key->uids->validity : 0 ;
01832 this_info.validity = attr_ulong;
01833
01834
01835
01836
01837 attr_string = key->uids ? key->uids->uid : 0 ;
01838 if (attr_string != 0) {
01839 a = parse_dn( (const unsigned char*)attr_string );
01840 this_info.userid = reorder_dn( a, attrOrder, unknownAttrsHandling );
01841 }
01842
01843 attr_ulong = 0;
01844 this_info.userid_num = attr_ulong;
01845
01846
01847 this_info.keylen = key->subkeys ? key->subkeys->length : 0 ;
01848
01849
01850 attr_ulong = key->subkeys ? key->subkeys->timestamp : 0 ;
01851 this_info.key_created = attr_ulong;
01852
01853
01854 attr_ulong = key->subkeys ? key->subkeys->expires : 0 ;
01855 this_info.key_expires = attr_ulong;
01856
01857
01858 attr_string = key->uids ? key->uids->name : 0 ;
01859 if (attr_string != 0) {
01860 a = parse_dn( (const unsigned char*)attr_string );
01861 this_info.name = reorder_dn( a, attrOrder, unknownAttrsHandling );
01862 }
01863
01864
01865 this_info.emailCount = 0;
01866 this_info.emailList = 0;
01867 for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) {
01868 attr_string = uid->email;
01869 if ( attr_string && *attr_string) {
01870 fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
01871 if( !this_info.emailCount )
01872 alloc_return = malloc( sizeof( char*) );
01873 else
01874 alloc_return = realloc( this_info.emailList,
01875 sizeof( char*)
01876 * (this_info.emailCount + 1) );
01877 if( alloc_return ) {
01878 this_info.emailList = (char**)alloc_return;
01879 storeNewCharPtr( &( this_info.emailList[ this_info.emailCount ] ),
01880 attr_string );
01881 ++this_info.emailCount;
01882 }
01883 }
01884 }
01885 if( !this_info.emailCount )
01886 fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" );
01887
01888
01889 attr_string = key->uids ? key->uids->comment : 0 ;
01890 if (attr_string != 0)
01891 storeNewCharPtr( &this_info.comment, attr_string );
01892 }
01893
01894 gpgme_sig_stat_t status = sig_stat_from_status( signature->status );
01895 const char* sig_status = sig_status_to_string( status );
01896 storeNewCharPtr( &this_info.status_text, sig_status );
01897 }
01898 sigmeta->extended_info_count = sig_idx;
01899 overallStatus = intersect_stati( result->signatures );
01900 sigmeta->status_code = overallStatus;
01901 storeNewCharPtr( &sigmeta->status, sig_status_to_string( overallStatus ) );
01902 if ( signatureFound )
01903 *signatureFound = ( overallStatus != GPGME_SIG_STAT_NONE );
01904 }
01905
01906
01907 bool CryptPlug::checkMessageSignature( char** cleartext,
01908 const char* signaturetext,
01909 bool signatureIsBinary,
01910 int signatureLen,
01911 struct CryptPlug::SignatureMetaData* sigmeta,
01912 char** attrOrder,
01913 const char* unknownAttrsHandling )
01914 {
01915 gpgme_ctx_t ctx;
01916 gpgme_sig_stat_t status = GPGME_SIG_STAT_NONE;
01917 gpgme_data_t datapart, sigpart;
01918 char* rClear = 0;
01919 size_t clearLen;
01920 bool isOpaqueSigned;
01921
01922 if( !cleartext ) {
01923 if( sigmeta )
01924 storeNewCharPtr( &sigmeta->status,
01925 __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
01926
01927 return false;
01928 }
01929
01930 isOpaqueSigned = !*cleartext;
01931
01932 gpgme_new( &ctx );
01933 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
01934 gpgme_set_armor (ctx, signatureIsBinary ? 0 : 1);
01935
01936
01937 if( isOpaqueSigned )
01938 gpgme_data_new( &datapart );
01939 else
01940 gpgme_data_new_from_mem( &datapart, *cleartext,
01941 strlen( *cleartext ), 1 );
01942
01943 gpgme_data_new_from_mem( &sigpart,
01944 signaturetext,
01945 signatureIsBinary
01946 ? signatureLen
01947 : strlen( signaturetext ),
01948 1 );
01949
01950 if ( isOpaqueSigned )
01951 gpgme_op_verify( ctx, sigpart, 0, datapart );
01952 else
01953 gpgme_op_verify( ctx, sigpart, datapart, 0 );
01954
01955 if( isOpaqueSigned ) {
01956 rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
01957 *cleartext = (char*)malloc( clearLen + 1 );
01958 if( *cleartext ) {
01959 if( clearLen )
01960 strncpy(*cleartext, rClear, clearLen );
01961 (*cleartext)[clearLen] = '\0';
01962 }
01963 free( rClear );
01964 }
01965 else
01966 gpgme_data_release( datapart );
01967
01968 gpgme_data_release( sigpart );
01969
01970 obtain_signature_information( ctx, status, sigmeta,
01971 attrOrder, unknownAttrsHandling );
01972
01973 gpgme_release( ctx );
01974 return ( status == GPGME_SIG_STAT_GOOD );
01975 }
01976
01977
01978 bool CryptPlug::decryptAndCheckMessage( const char* ciphertext,
01979 bool cipherIsBinary,
01980 int cipherLen,
01981 const char** cleartext,
01982 const char* ,
01983 bool* signatureFound,
01984 struct CryptPlug::SignatureMetaData* sigmeta,
01985 int* errId,
01986 char** errTxt,
01987 char** attrOrder,
01988 const char* unknownAttrsHandling )
01989 {
01990 gpgme_ctx_t ctx;
01991 gpgme_error_t err;
01992 gpgme_decrypt_result_t decryptresult;
01993 gpgme_data_t gCiphertext, gPlaintext;
01994 gpgme_sig_stat_t sigstatus = GPGME_SIG_STAT_NONE;
01995 size_t rCLen = 0;
01996 char* rCiph = 0;
01997 bool bOk = false;
01998 bool bWrongKeyUsage = false;
01999
02000 if( !ciphertext )
02001 return false;
02002
02003 err = gpgme_new (&ctx);
02004 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
02005
02006 gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
02007
02008
02009
02010
02011
02012 gpgme_data_new_from_mem( &gCiphertext,
02013 ciphertext,
02014 cipherIsBinary
02015 ? cipherLen
02016 : strlen( ciphertext ),
02017 1 );
02018
02019 gpgme_data_new( &gPlaintext );
02020
02021 err = gpgme_op_decrypt_verify( ctx, gCiphertext, gPlaintext );
02022 gpgme_data_release( gCiphertext );
02023
02024 decryptresult = gpgme_op_decrypt_result( ctx );
02025 #ifdef HAVE_GPGME_WRONG_KEY_USAGE
02026 if( decryptresult->wrong_key_usage )
02027 bWrongKeyUsage = true;
02028 #endif
02029
02030 if( err ) {
02031 fprintf( stderr, "\ngpgme_op_decrypt_verify() returned this error code: %i\n\n", err );
02032 if( errId )
02033 *errId = err;
02034 if( errTxt ) {
02035 const char* _errTxt = gpgme_strerror( err );
02036 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
02037 if( *errTxt )
02038 strcpy(*errTxt, _errTxt );
02039 }
02040 gpgme_data_release( gPlaintext );
02041 gpgme_release( ctx );
02042 return bOk;
02043 }
02044
02045 if( bWrongKeyUsage ) {
02046 if( errId )
02047 *errId = CRYPTPLUG_ERR_WRONG_KEY_USAGE;
02048 }
02049
02050 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
02051
02052 *cleartext = (char*)malloc( rCLen + 1 );
02053 if( *cleartext ) {
02054 if( rCLen ) {
02055 bOk = true;
02056 strncpy((char*)*cleartext, rCiph, rCLen );
02057 }
02058 ((char*)(*cleartext))[rCLen] = 0;
02059 }
02060 free( rCiph );
02061
02062 obtain_signature_information( ctx, sigstatus, sigmeta,
02063 attrOrder, unknownAttrsHandling,
02064 signatureFound );
02065
02066 gpgme_release( ctx );
02067 return bOk;
02068 }
02069