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 CryptPlug::CryptPlug() {
00268 }
00269
00270 CryptPlug::~CryptPlug() {
00271 }
00272
00273 bool CryptPlug::initialize() {
00274 GpgME::setDefaultLocale( LC_CTYPE, setlocale( LC_CTYPE, 0 ) );
00275 GpgME::setDefaultLocale( LC_MESSAGES, setlocale( LC_MESSAGES, 0 ) );
00276 return (gpgme_engine_check_version (GPGMEPLUG_PROTOCOL) == GPG_ERR_NO_ERROR);
00277 }
00278
00279
00280 bool CryptPlug::hasFeature( Feature flag )
00281 {
00282
00283 switch ( flag ) {
00284 case Feature_SignMessages:
00285 case Feature_VerifySignatures:
00286 case Feature_EncryptMessages:
00287 case Feature_DecryptMessages:
00288 case Feature_SendCertificates:
00289 case Feature_PinEntrySettings:
00290 case Feature_StoreMessagesWithSigs:
00291 case Feature_EncryptionCRLs:
00292 case Feature_StoreMessagesEncrypted:
00293 case Feature_CheckCertificatePath:
00294 return true;
00295 case Feature_WarnSignCertificateExpiry:
00296 case Feature_WarnSignEmailNotInCertificate:
00297 case Feature_WarnEncryptCertificateExpiry:
00298 case Feature_WarnEncryptEmailNotInCertificate:
00299 return GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS;
00300
00301 case Feature_CRLDirectoryService:
00302 case Feature_CertificateDirectoryService:
00303 case Feature_undef:
00304 default:
00305 return false;
00306 }
00307 }
00308
00309
00310 static
00311 void storeNewCharPtr( char** dest, const char* src )
00312 {
00313 int sLen = strlen( src );
00314 *dest = (char*)xmalloc( sLen + 1 );
00315 strcpy( *dest, src );
00316 }
00317
00318 bool CryptPlug::decryptMessage( const char* ciphertext,
00319 bool cipherIsBinary,
00320 int cipherLen,
00321 const char** cleartext,
00322 const char* ,
00323 int* errId,
00324 char** errTxt )
00325 {
00326 gpgme_ctx_t ctx;
00327 gpgme_error_t err;
00328 gpgme_data_t gCiphertext, gPlaintext;
00329 size_t rCLen = 0;
00330 char* rCiph = 0;
00331 bool bOk = false;
00332
00333 if( !ciphertext )
00334 return false;
00335
00336 err = gpgme_new (&ctx);
00337 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00338
00339 gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
00340
00341
00342
00343
00344
00345 gpgme_data_new_from_mem( &gCiphertext,
00346 ciphertext,
00347 cipherIsBinary
00348 ? cipherLen
00349 : strlen( ciphertext ),
00350 1 );
00351
00352 gpgme_data_new( &gPlaintext );
00353
00354 err = gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
00355 if( err ) {
00356 fprintf( stderr, "\ngpgme_op_decrypt() returned this error code: %i\n\n", err );
00357 if( errId )
00358 *errId = err;
00359 if( errTxt ) {
00360 const char* _errTxt = gpgme_strerror( err );
00361 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
00362 if( *errTxt )
00363 strcpy(*errTxt, _errTxt );
00364 }
00365 }
00366
00367 gpgme_data_release( gCiphertext );
00368
00369 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
00370
00371 *cleartext = (char*)malloc( rCLen + 1 );
00372 if( *cleartext ) {
00373 if( rCLen ) {
00374 bOk = true;
00375 strncpy((char*)*cleartext, rCiph, rCLen );
00376 }
00377 ((char*)(*cleartext))[rCLen] = 0;
00378 }
00379
00380 free( rCiph );
00381 gpgme_release( ctx );
00382 return bOk;
00383 }
00384
00385
00386 static char *
00387 trim_trailing_spaces( char *string )
00388 {
00389 char *p, *mark;
00390
00391 for( mark = NULL, p = string; *p; p++ ) {
00392 if( isspace( *p ) ) {
00393 if( !mark )
00394 mark = p;
00395 }
00396 else
00397 mark = NULL;
00398 }
00399 if( mark )
00400 *mark = '\0' ;
00401
00402 return string ;
00403 }
00404
00405
00406
00407
00408 static const unsigned char *
00409 parse_dn_part (CryptPlug::DnPair *array, const unsigned char *string)
00410 {
00411 const unsigned char *s, *s1;
00412 size_t n;
00413 char *p;
00414
00415
00416 for (s = string+1; *s && *s != '='; s++)
00417 ;
00418 if (!*s)
00419 return NULL;
00420 n = s - string;
00421 if (!n)
00422 return NULL;
00423 p = (char*)xmalloc (n+1);
00424
00425
00426 memcpy (p, string, n);
00427 p[n] = 0;
00428 trim_trailing_spaces ((char*)p);
00429
00430 for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
00431 if ( !strcasecmp ((char*)p, oidmap[i].oid) ) {
00432 free( p );
00433 p = xstrdup (oidmap[i].name);
00434 break;
00435 }
00436 array->key = p;
00437 string = s + 1;
00438
00439 if (*string == '#')
00440 {
00441 string++;
00442 for (s=string; hexdigitp (s); s++)
00443 s++;
00444 n = s - string;
00445 if (!n || (n & 1))
00446 return NULL;
00447 n /= 2;
00448 array->value = p = (char*)xmalloc (n+1);
00449
00450
00451 for (s1=string; n; s1 += 2, n--)
00452 *p++ = xtoi_2 (s1);
00453 *p = 0;
00454 }
00455 else
00456 {
00457 for (n=0, s=string; *s; s++)
00458 {
00459 if (*s == '\\')
00460 {
00461 s++;
00462 if (*s == ',' || *s == '=' || *s == '+'
00463 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
00464 || *s == '\\' || *s == '\"' || *s == ' ')
00465 n++;
00466 else if (hexdigitp (s) && hexdigitp (s+1))
00467 {
00468 s++;
00469 n++;
00470 }
00471 else
00472 return NULL;
00473 }
00474 else if (*s == '\"')
00475 return NULL;
00476 else if (*s == ',' || *s == '=' || *s == '+'
00477 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
00478 break;
00479 else
00480 n++;
00481 }
00482
00483 array->value = p = (char*)xmalloc (n+1);
00484
00485
00486 for (s=string; n; s++, n--)
00487 {
00488 if (*s == '\\')
00489 {
00490 s++;
00491 if (hexdigitp (s))
00492 {
00493 *p++ = xtoi_2 (s);
00494 s++;
00495 }
00496 else
00497 *p++ = *s;
00498 }
00499 else
00500 *p++ = *s;
00501 }
00502 *p = 0;
00503 }
00504 return s;
00505 }
00506
00507
00508
00509
00510
00511 static CryptPlug::DnPair *
00512 parse_dn (const unsigned char *string)
00513 {
00514 struct CryptPlug::DnPair *array;
00515 size_t arrayidx, arraysize;
00516
00517 if( !string )
00518 return NULL;
00519
00520 arraysize = 7;
00521 arrayidx = 0;
00522 array = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
00523
00524
00525 while (*string)
00526 {
00527 while (*string == ' ')
00528 string++;
00529 if (!*string)
00530 break;
00531 if (arrayidx >= arraysize)
00532 {
00533 struct CryptPlug::DnPair *a2;
00534
00535 arraysize += 5;
00536 a2 = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
00537 for (unsigned int i=0; i < arrayidx; i++)
00538 {
00539 a2[i].key = array[i].key;
00540 a2[i].value = array[i].value;
00541 }
00542 free (array);
00543 array = a2;
00544 }
00545 array[arrayidx].key = NULL;
00546 array[arrayidx].value = NULL;
00547 string = parse_dn_part (array+arrayidx, string);
00548 arrayidx++;
00549 if (!string)
00550 goto failure;
00551 while (*string == ' ')
00552 string++;
00553 if (*string && *string != ',' && *string != ';' && *string != '+')
00554 goto failure;
00555 if (*string)
00556 string++;
00557 }
00558 array[arrayidx].key = NULL;
00559 array[arrayidx].value = NULL;
00560 return array;
00561
00562 failure:
00563 for (unsigned i=0; i < arrayidx; i++)
00564 {
00565 free (array[i].key);
00566 free (array[i].value);
00567 }
00568 free (array);
00569 return NULL;
00570 }
00571
00572 static void
00573 add_dn_part( QCString& result, struct CryptPlug::DnPair& dnPair )
00574 {
00575
00576 QCString mappedPart( dnPair.key );
00577 for ( unsigned int i = 0 ; i < numOidMaps ; ++i ){
00578 if( !strcasecmp( dnPair.key, oidmap[i].oid ) ) {
00579 mappedPart = oidmap[i].name;
00580 break;
00581 }
00582 }
00583 result.append( mappedPart );
00584 result.append( "=" );
00585 result.append( dnPair.value );
00586 }
00587
00588 static int
00589 add_dn_parts( QCString& result, struct CryptPlug::DnPair* dn, const char* part )
00590 {
00591 int any = 0;
00592
00593 if( dn ) {
00594 for(; dn->key; ++dn ) {
00595 if( !strcmp( dn->key, part ) ) {
00596 if( any )
00597 result.append( "," );
00598 add_dn_part( result, *dn );
00599 any = 1;
00600 }
00601 }
00602 }
00603 return any;
00604 }
00605
00606 static char*
00607 reorder_dn( struct CryptPlug::DnPair *dn,
00608 char** attrOrder = 0,
00609 const char* unknownAttrsHandling = 0 )
00610 {
00611 struct CryptPlug::DnPair *dnOrg = dn;
00612
00613
00614 const char* defaultpart[] = {
00615 "CN", "S", "SN", "GN", "T", "UID",
00616 "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET",
00617 "L", "PC", "SP", "ST",
00618 "OU",
00619 "O",
00620 "C",
00621 NULL
00622 };
00623 const char** stdpart = attrOrder ? ((const char**)attrOrder) : defaultpart;
00624 int any=0, any2=0, found_X_=0, i;
00625 QCString result;
00626 QCString resultUnknowns;
00627
00628
00629 if( dn ){
00630 for(; dn->key; ++dn ) {
00631 for( i = 0; stdpart[i]; ++i ) {
00632 if( !strcmp( dn->key, stdpart[i] ) ) {
00633 break;
00634 }
00635 }
00636 if( !stdpart[i] ) {
00637 if( any2 )
00638 resultUnknowns.append( "," );
00639 add_dn_part( resultUnknowns, *dn );
00640 any2 = 1;
00641 }
00642 }
00643 dn = dnOrg;
00644 }
00645
00646
00647 if( unknownAttrsHandling &&
00648 !strcmp(unknownAttrsHandling, "PREFIX")
00649 && *resultUnknowns ){
00650 result.append( resultUnknowns );
00651 any = 1;
00652 }else{
00653 any = 0;
00654 }
00655
00656
00657 for( i = 0; stdpart[i]; ++i ) {
00658 dn = dnOrg;
00659 if( any ) {
00660 result.append( "," );
00661 }
00662 if( any2 &&
00663 !strcmp(stdpart[i], "_X_") &&
00664 unknownAttrsHandling &&
00665 !strcmp(unknownAttrsHandling, "INFIX") ){
00666 if ( !resultUnknowns.isEmpty() ) {
00667 result.append( resultUnknowns );
00668 any = 1;
00669 }
00670 found_X_ = 1;
00671 }else{
00672 any = add_dn_parts( result, dn, stdpart[i] );
00673 }
00674 }
00675
00676
00677 if( !unknownAttrsHandling ||
00678 !strcmp(unknownAttrsHandling, "POSTFIX") ||
00679 ( !strcmp(unknownAttrsHandling, "INFIX") && !found_X_ ) ){
00680 if( !resultUnknowns.isEmpty() ) {
00681 if( any ){
00682 result.append( "," );
00683 }
00684 result.append( resultUnknowns );
00685 }
00686 }
00687
00688 char* cResult = (char*)xmalloc( (result.length()+1)*sizeof(char) );
00689 if( result.isEmpty() )
00690 *cResult = 0;
00691 else
00692 strcpy( cResult, result );
00693 return cResult;
00694 }
00695
00696 GpgME::ImportResult CryptPlug::importCertificateFromMem( const char* data, size_t length )
00697 {
00698 using namespace GpgME;
00699
00700 std::auto_ptr<Context> context( Context::createForProtocol( mProtocol ) );
00701 if ( !context.get() )
00702 return ImportResult();
00703
00704 Data keydata( data, length, false );
00705 if ( keydata.isNull() )
00706 return ImportResult();
00707
00708 return context->importKeys( keydata );
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 static gpgme_sig_stat_t
00720 sig_stat_from_status( gpgme_error_t err )
00721 {
00722 switch ( gpg_err_code(err) ) {
00723 case GPG_ERR_NO_ERROR:
00724 return GPGME_SIG_STAT_GOOD;
00725 case GPG_ERR_BAD_SIGNATURE:
00726 return GPGME_SIG_STAT_BAD;
00727 case GPG_ERR_NO_PUBKEY:
00728 return GPGME_SIG_STAT_NOKEY;
00729 case GPG_ERR_NO_DATA:
00730 return GPGME_SIG_STAT_NOSIG;
00731 case GPG_ERR_SIG_EXPIRED:
00732 return GPGME_SIG_STAT_GOOD_EXP;
00733 case GPG_ERR_KEY_EXPIRED:
00734 return GPGME_SIG_STAT_GOOD_EXPKEY;
00735 default:
00736 return GPGME_SIG_STAT_ERROR;
00737 }
00738 }
00739
00740
00741 static gpgme_sig_stat_t
00742 intersect_stati( gpgme_signature_t first )
00743 {
00744 if ( !first )
00745 return GPGME_SIG_STAT_NONE;
00746 gpgme_sig_stat_t result = sig_stat_from_status( first->status );
00747 for ( gpgme_signature_t sig = first->next ; sig ; sig = sig->next )
00748 if ( sig_stat_from_status( sig->status ) != result )
00749 return GPGME_SIG_STAT_DIFF;
00750 return result;
00751 }
00752
00753 static const char*
00754 sig_status_to_string( gpgme_sig_stat_t status )
00755 {
00756 const char *result;
00757
00758 switch (status) {
00759 case GPGME_SIG_STAT_NONE:
00760 result = "Oops: Signature not verified";
00761 break;
00762 case GPGME_SIG_STAT_NOSIG:
00763 result = "No signature found";
00764 break;
00765 case GPGME_SIG_STAT_GOOD:
00766 result = "Good signature";
00767 break;
00768 case GPGME_SIG_STAT_BAD:
00769 result = "BAD signature";
00770 break;
00771 case GPGME_SIG_STAT_NOKEY:
00772 result = "No public key to verify the signature";
00773 break;
00774 case GPGME_SIG_STAT_ERROR:
00775 result = "Error verifying the signature";
00776 break;
00777 case GPGME_SIG_STAT_DIFF:
00778 result = "Different results for signatures";
00779 break;
00780 default:
00781 result = "Error: Unknown status";
00782 break;
00783 }
00784
00785 return result;
00786 }
00787
00788
00789
00790 static
00791 void obtain_signature_information( gpgme_ctx_t ctx,
00792 gpgme_sig_stat_t & overallStatus,
00793 struct CryptPlug::SignatureMetaData* sigmeta,
00794 char** attrOrder,
00795 const char* unknownAttrsHandling,
00796 bool * signatureFound=0 )
00797 {
00798 gpgme_error_t err;
00799 unsigned long sumGPGME;
00800 SigStatusFlags sumPlug;
00801 struct CryptPlug::DnPair* a;
00802 int sig_idx=0;
00803
00804 assert( ctx );
00805 assert( sigmeta );
00806
00807 sigmeta->extended_info = 0;
00808 gpgme_verify_result_t result = gpgme_op_verify_result( ctx );
00809 if ( !result )
00810 return;
00811 for ( gpgme_signature_t signature = result->signatures ; signature ; signature = signature->next, ++sig_idx ) {
00812 void* alloc_return = realloc( sigmeta->extended_info,
00813 sizeof( CryptPlug::SignatureMetaDataExtendedInfo )
00814 * ( sig_idx + 1 ) );
00815 if ( !alloc_return )
00816 break;
00817 sigmeta->extended_info = (CryptPlug::SignatureMetaDataExtendedInfo*)alloc_return;
00818
00819
00820 CryptPlug::SignatureMetaDataExtendedInfo & this_info = sigmeta->extended_info[sig_idx];
00821
00822
00823 memset( &this_info, 0, sizeof (CryptPlug::SignatureMetaDataExtendedInfo) );
00824
00825
00826 if ( signature->timestamp ) {
00827 this_info.creation_time = (tm*)malloc( sizeof( struct tm ) );
00828 if ( this_info.creation_time ) {
00829 struct tm * ctime_val = localtime( (time_t*)&signature->timestamp );
00830 memcpy( this_info.creation_time,
00831 ctime_val, sizeof( struct tm ) );
00832 }
00833 }
00834
00835
00836 sumGPGME = signature->summary;
00837 fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
00838
00839 sumPlug = 0;
00840 #define convert(X) if ( sumGPGME & GPGME_SIGSUM_##X ) sumPlug |= SigStat_##X
00841 convert(VALID);
00842 convert(GREEN);
00843 convert(RED);
00844 convert(KEY_REVOKED);
00845 convert(KEY_EXPIRED);
00846 convert(SIG_EXPIRED);
00847 convert(KEY_MISSING);
00848 convert(CRL_MISSING);
00849 convert(CRL_TOO_OLD);
00850 convert(BAD_POLICY);
00851 convert(SYS_ERROR);
00852 #undef convert
00853 if( sumGPGME && !sumPlug )
00854 sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
00855 this_info.sigStatusFlags = sumPlug;
00856
00857
00858 if ( signature->fpr )
00859 storeNewCharPtr( &this_info.fingerprint, signature->fpr );
00860
00861
00862 this_info.validity = GPGME_VALIDITY_UNKNOWN;
00863
00864
00865 gpgme_key_t key = 0;
00866
00867
00868 err = gpgme_get_sig_key (ctx, sig_idx, &key);
00869
00870 if ( !err && key ) {
00871 const char* attr_string;
00872 unsigned long attr_ulong;
00873
00874
00875 attr_string = key->subkeys ? key->subkeys->keyid : 0 ;
00876 if ( attr_string )
00877 storeNewCharPtr( &this_info.keyid, attr_string );
00878
00879
00880 attr_string = key->subkeys ? gpgme_pubkey_algo_name( key->subkeys->pubkey_algo ) : 0 ;
00881 if (attr_string != 0)
00882 storeNewCharPtr( &this_info.algo, attr_string );
00883 attr_ulong = key->subkeys ? key->subkeys->pubkey_algo : 0 ;
00884 this_info.algo_num = attr_ulong;
00885
00886
00887 attr_ulong = key->uids ? key->uids->validity : 0 ;
00888 this_info.validity = attr_ulong;
00889
00890
00891
00892
00893 attr_string = key->uids ? key->uids->uid : 0 ;
00894 if (attr_string != 0) {
00895 a = parse_dn( (const unsigned char*)attr_string );
00896 this_info.userid = reorder_dn( a, attrOrder, unknownAttrsHandling );
00897 }
00898
00899 attr_ulong = 0;
00900 this_info.userid_num = attr_ulong;
00901
00902
00903 this_info.keylen = key->subkeys ? key->subkeys->length : 0 ;
00904
00905
00906 attr_ulong = key->subkeys ? key->subkeys->timestamp : 0 ;
00907 this_info.key_created = attr_ulong;
00908
00909
00910 attr_ulong = key->subkeys ? key->subkeys->expires : 0 ;
00911 this_info.key_expires = attr_ulong;
00912
00913
00914 attr_string = key->uids ? key->uids->name : 0 ;
00915 if (attr_string != 0) {
00916 a = parse_dn( (const unsigned char*)attr_string );
00917 this_info.name = reorder_dn( a, attrOrder, unknownAttrsHandling );
00918 }
00919
00920
00921 this_info.emailCount = 0;
00922 this_info.emailList = 0;
00923 for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) {
00924 attr_string = uid->email;
00925 if ( attr_string && *attr_string) {
00926 fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
00927 if( !this_info.emailCount )
00928 alloc_return = malloc( sizeof( char*) );
00929 else
00930 alloc_return = realloc( this_info.emailList,
00931 sizeof( char*)
00932 * (this_info.emailCount + 1) );
00933 if( alloc_return ) {
00934 this_info.emailList = (char**)alloc_return;
00935 storeNewCharPtr( &( this_info.emailList[ this_info.emailCount ] ),
00936 attr_string );
00937 ++this_info.emailCount;
00938 }
00939 }
00940 }
00941 if( !this_info.emailCount )
00942 fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" );
00943
00944
00945 attr_string = key->uids ? key->uids->comment : 0 ;
00946 if (attr_string != 0)
00947 storeNewCharPtr( &this_info.comment, attr_string );
00948 }
00949
00950 gpgme_sig_stat_t status = sig_stat_from_status( signature->status );
00951 const char* sig_status = sig_status_to_string( status );
00952 storeNewCharPtr( &this_info.status_text, sig_status );
00953 }
00954 sigmeta->extended_info_count = sig_idx;
00955 overallStatus = intersect_stati( result->signatures );
00956 sigmeta->status_code = overallStatus;
00957 storeNewCharPtr( &sigmeta->status, sig_status_to_string( overallStatus ) );
00958 if ( signatureFound )
00959 *signatureFound = ( overallStatus != GPGME_SIG_STAT_NONE );
00960 }
00961
00962 bool CryptPlug::checkMessageSignature( char** cleartext,
00963 const char* signaturetext,
00964 bool signatureIsBinary,
00965 int signatureLen,
00966 struct CryptPlug::SignatureMetaData* sigmeta,
00967 char** attrOrder,
00968 const char* unknownAttrsHandling )
00969 {
00970 gpgme_ctx_t ctx;
00971 gpgme_sig_stat_t status = GPGME_SIG_STAT_NONE;
00972 gpgme_data_t datapart, sigpart;
00973 char* rClear = 0;
00974 size_t clearLen;
00975 bool isOpaqueSigned;
00976
00977 if( !cleartext ) {
00978 if( sigmeta )
00979 storeNewCharPtr( &sigmeta->status,
00980 __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
00981
00982 return false;
00983 }
00984
00985 isOpaqueSigned = !*cleartext;
00986
00987 gpgme_new( &ctx );
00988 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00989 gpgme_set_armor (ctx, signatureIsBinary ? 0 : 1);
00990
00991
00992 if( isOpaqueSigned )
00993 gpgme_data_new( &datapart );
00994 else
00995 gpgme_data_new_from_mem( &datapart, *cleartext,
00996 strlen( *cleartext ), 1 );
00997
00998 gpgme_data_new_from_mem( &sigpart,
00999 signaturetext,
01000 signatureIsBinary
01001 ? signatureLen
01002 : strlen( signaturetext ),
01003 1 );
01004
01005 if ( isOpaqueSigned )
01006 gpgme_op_verify( ctx, sigpart, 0, datapart );
01007 else
01008 gpgme_op_verify( ctx, sigpart, datapart, 0 );
01009
01010 if( isOpaqueSigned ) {
01011 rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
01012 *cleartext = (char*)malloc( clearLen + 1 );
01013 if( *cleartext ) {
01014 if( clearLen )
01015 strncpy(*cleartext, rClear, clearLen );
01016 (*cleartext)[clearLen] = '\0';
01017 }
01018 free( rClear );
01019 }
01020 else
01021 gpgme_data_release( datapart );
01022
01023 gpgme_data_release( sigpart );
01024
01025 obtain_signature_information( ctx, status, sigmeta,
01026 attrOrder, unknownAttrsHandling );
01027
01028 gpgme_release( ctx );
01029 return ( status == GPGME_SIG_STAT_GOOD );
01030 }
01031
01032 bool CryptPlug::decryptAndCheckMessage( const char* ciphertext,
01033 bool cipherIsBinary,
01034 int cipherLen,
01035 const char** cleartext,
01036 const char* ,
01037 bool* signatureFound,
01038 struct CryptPlug::SignatureMetaData* sigmeta,
01039 int* errId,
01040 char** errTxt,
01041 char** attrOrder,
01042 const char* unknownAttrsHandling )
01043 {
01044 gpgme_ctx_t ctx;
01045 gpgme_error_t err;
01046 gpgme_decrypt_result_t decryptresult;
01047 gpgme_data_t gCiphertext, gPlaintext;
01048 gpgme_sig_stat_t sigstatus = GPGME_SIG_STAT_NONE;
01049 size_t rCLen = 0;
01050 char* rCiph = 0;
01051 bool bOk = false;
01052 bool bWrongKeyUsage = false;
01053
01054 if( !ciphertext )
01055 return false;
01056
01057 err = gpgme_new (&ctx);
01058 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
01059
01060 gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
01061
01062
01063
01064
01065
01066 gpgme_data_new_from_mem( &gCiphertext,
01067 ciphertext,
01068 cipherIsBinary
01069 ? cipherLen
01070 : strlen( ciphertext ),
01071 1 );
01072
01073 gpgme_data_new( &gPlaintext );
01074
01075 err = gpgme_op_decrypt_verify( ctx, gCiphertext, gPlaintext );
01076 gpgme_data_release( gCiphertext );
01077
01078 decryptresult = gpgme_op_decrypt_result( ctx );
01079 #ifdef HAVE_GPGME_WRONG_KEY_USAGE
01080 if( decryptresult->wrong_key_usage )
01081 bWrongKeyUsage = true;
01082 #endif
01083
01084 if( err ) {
01085 fprintf( stderr, "\ngpgme_op_decrypt_verify() returned this error code: %i\n\n", err );
01086 if( errId )
01087 *errId = err;
01088 if( errTxt ) {
01089 const char* _errTxt = gpgme_strerror( err );
01090 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
01091 if( *errTxt )
01092 strcpy(*errTxt, _errTxt );
01093 }
01094 gpgme_data_release( gPlaintext );
01095 gpgme_release( ctx );
01096 return bOk;
01097 }
01098
01099 if( bWrongKeyUsage ) {
01100 if( errId )
01101 *errId = CRYPTPLUG_ERR_WRONG_KEY_USAGE;
01102 }
01103
01104 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
01105
01106 *cleartext = (char*)malloc( rCLen + 1 );
01107 if( *cleartext ) {
01108 if( rCLen ) {
01109 bOk = true;
01110 strncpy((char*)*cleartext, rCiph, rCLen );
01111 }
01112 ((char*)(*cleartext))[rCLen] = 0;
01113 }
01114 free( rCiph );
01115
01116 obtain_signature_information( ctx, sigstatus, sigmeta,
01117 attrOrder, unknownAttrsHandling,
01118 signatureFound );
01119
01120 gpgme_release( ctx );
01121 return bOk;
01122 }
01123