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 #include "libkleo/kleo/oidmap.h"
00028
00029 #include <gpgme++/context.h>
00030 #include <gpgme++/data.h>
00031 #include <gpgme++/importresult.h>
00032
00050 #include <QString>
00051
00052 #include <QByteArray>
00053
00054 #include <string>
00055 #include <vector>
00056 #include <algorithm>
00057 #include <iostream>
00058 #include <memory>
00059
00060 #include <stdio.h>
00061 #include <string.h>
00062 #include <strings.h>
00063 #include <assert.h>
00064 #include <errno.h>
00065 #include <time.h>
00066 #include <ctype.h>
00067 #include <locale.h>
00068
00069 #define __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO "Error: Cannot run checkMessageSignature() with cleartext == 0"
00070
00071
00072
00073
00074
00075
00076 #ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
00077 #define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
00078 #define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT false
00079 #define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME false
00080 #define GPGMEPLUG_ENCSIGN_CTYPE_MAIN ""
00081 #define GPGMEPLUG_ENCSIGN_CDISP_MAIN ""
00082 #define GPGMEPLUG_ENCSIGN_CTENC_MAIN ""
00083 #define GPGMEPLUG_ENCSIGN_CTYPE_VERSION ""
00084 #define GPGMEPLUG_ENCSIGN_CDISP_VERSION ""
00085 #define GPGMEPLUG_ENCSIGN_CTENC_VERSION ""
00086 #define GPGMEPLUG_ENCSIGN_BTEXT_VERSION ""
00087 #define GPGMEPLUG_ENCSIGN_CTYPE_CODE ""
00088 #define GPGMEPLUG_ENCSIGN_CDISP_CODE ""
00089 #define GPGMEPLUG_ENCSIGN_CTENC_CODE ""
00090 #define GPGMEPLUG_ENCSIGN_FLAT_PREFIX ""
00091 #define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR ""
00092 #define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX ""
00093 #endif
00094
00095 #include "cryptplug.h"
00096
00097 SMIMECryptPlug::SMIMECryptPlug() : CryptPlug() {
00098 GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_CMS;
00099 mProtocol = GpgME::CMS;
00100
00101
00102
00103 GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false;
00104 GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = true;
00105 GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false;
00106 GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = "application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\"";
00107 GPGMEPLUG_OPA_SIGN_CDISP_MAIN = "attachment; filename=\"smime.p7m\"";
00108 GPGMEPLUG_OPA_SIGN_CTENC_MAIN = "base64";
00109 GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = "";
00110 GPGMEPLUG_OPA_SIGN_CDISP_VERSION = "";
00111 GPGMEPLUG_OPA_SIGN_CTENC_VERSION = "";
00112 GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = "";
00113 GPGMEPLUG_OPA_SIGN_CTYPE_CODE = "";
00114 GPGMEPLUG_OPA_SIGN_CDISP_CODE = "";
00115 GPGMEPLUG_OPA_SIGN_CTENC_CODE = "";
00116 GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = "";
00117 GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = "";
00118 GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = "";
00119
00120 GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true;
00121 GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true;
00122 GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true;
00123 GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1";
00124 GPGMEPLUG_DET_SIGN_CDISP_MAIN = "";
00125 GPGMEPLUG_DET_SIGN_CTENC_MAIN = "";
00126 GPGMEPLUG_DET_SIGN_CTYPE_VERSION = "";
00127 GPGMEPLUG_DET_SIGN_CDISP_VERSION = "";
00128 GPGMEPLUG_DET_SIGN_CTENC_VERSION = "";
00129 GPGMEPLUG_DET_SIGN_BTEXT_VERSION = "";
00130 GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pkcs7-signature; name=\"smime.p7s\"";
00131 GPGMEPLUG_DET_SIGN_CDISP_CODE = "attachment; filename=\"smime.p7s\"";
00132 GPGMEPLUG_DET_SIGN_CTENC_CODE = "base64";
00133 GPGMEPLUG_DET_SIGN_FLAT_PREFIX = "";
00134 GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = "";
00135 GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = "";
00136
00137 __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = true;
00138
00139
00140 GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false;
00141 GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true;
00142 GPGMEPLUG_ENC_MAKE_MULTI_MIME = false;
00143 GPGMEPLUG_ENC_CTYPE_MAIN = "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"";
00144 GPGMEPLUG_ENC_CDISP_MAIN = "attachment; filename=\"smime.p7m\"";
00145 GPGMEPLUG_ENC_CTENC_MAIN = "base64";
00146 GPGMEPLUG_ENC_CTYPE_VERSION = "";
00147 GPGMEPLUG_ENC_CDISP_VERSION = "";
00148 GPGMEPLUG_ENC_CTENC_VERSION = "";
00149 GPGMEPLUG_ENC_BTEXT_VERSION = "";
00150 GPGMEPLUG_ENC_CTYPE_CODE = "";
00151 GPGMEPLUG_ENC_CDISP_CODE = "";
00152 GPGMEPLUG_ENC_CTENC_CODE = "";
00153 GPGMEPLUG_ENC_FLAT_PREFIX = "";
00154 GPGMEPLUG_ENC_FLAT_SEPARATOR = "";
00155 GPGMEPLUG_ENC_FLAT_POSTFIX = "";
00156 __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = true;
00157 }
00158
00159 OpenPGPCryptPlug::OpenPGPCryptPlug() : CryptPlug() {
00160 GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_OpenPGP;
00161 mProtocol = GpgME::OpenPGP;
00162
00163
00164
00165 GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false;
00166 GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = false;
00167 GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false;
00168 GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = "";
00169 GPGMEPLUG_OPA_SIGN_CDISP_MAIN = "";
00170 GPGMEPLUG_OPA_SIGN_CTENC_MAIN = "";
00171 GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = "";
00172 GPGMEPLUG_OPA_SIGN_CDISP_VERSION = "";
00173 GPGMEPLUG_OPA_SIGN_CTENC_VERSION = "";
00174 GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = "";
00175 GPGMEPLUG_OPA_SIGN_CTYPE_CODE = "";
00176 GPGMEPLUG_OPA_SIGN_CDISP_CODE = "";
00177 GPGMEPLUG_OPA_SIGN_CTENC_CODE = "";
00178 GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = "";
00179 GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = "";
00180 GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = "";
00181
00182 GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true;
00183 GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true;
00184 GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true;
00185 GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pgp-signature\"; micalg=pgp-sha1";
00186 GPGMEPLUG_DET_SIGN_CDISP_MAIN = "";
00187 GPGMEPLUG_DET_SIGN_CTENC_MAIN = "";
00188 GPGMEPLUG_DET_SIGN_CTYPE_VERSION = "";
00189 GPGMEPLUG_DET_SIGN_CDISP_VERSION = "";
00190 GPGMEPLUG_DET_SIGN_CTENC_VERSION = "";
00191 GPGMEPLUG_DET_SIGN_BTEXT_VERSION = "";
00192 GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pgp-signature";
00193 GPGMEPLUG_DET_SIGN_CDISP_CODE = "";
00194 GPGMEPLUG_DET_SIGN_CTENC_CODE = "";
00195 GPGMEPLUG_DET_SIGN_FLAT_PREFIX = "";
00196 GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = "";
00197 GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = "";
00198
00199 __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = false;
00200
00201
00202 GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false;
00203 GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true;
00204 GPGMEPLUG_ENC_MAKE_MULTI_MIME = true;
00205 GPGMEPLUG_ENC_CTYPE_MAIN = "multipart/encrypted; protocol=\"application/pgp-encrypted\"";
00206 GPGMEPLUG_ENC_CDISP_MAIN = "";
00207 GPGMEPLUG_ENC_CTENC_MAIN = "";
00208 GPGMEPLUG_ENC_CTYPE_VERSION = "application/pgp-encrypted";
00209 GPGMEPLUG_ENC_CDISP_VERSION = "attachment";
00210 GPGMEPLUG_ENC_CTENC_VERSION = "";
00211 GPGMEPLUG_ENC_BTEXT_VERSION = "Version: 1";
00212 GPGMEPLUG_ENC_CTYPE_CODE = "application/octet-stream";
00213 GPGMEPLUG_ENC_CDISP_CODE = "inline; filename=\"msg.asc\"";
00214 GPGMEPLUG_ENC_CTENC_CODE = "";
00215 GPGMEPLUG_ENC_FLAT_PREFIX = "";
00216 GPGMEPLUG_ENC_FLAT_SEPARATOR = "";
00217 GPGMEPLUG_ENC_FLAT_POSTFIX = "";
00218 __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = false;
00219 }
00220
00221 #define days_from_seconds(x) ((x)/86400)
00222
00223
00224 #define MAX_GPGME_IDX 20
00225
00226
00227 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
00228 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
00229 #define hexdigitp(a) (digitp (a) \
00230 || (*(a) >= 'A' && *(a) <= 'F') \
00231 || (*(a) >= 'a' && *(a) <= 'f'))
00232
00233 #define atoi_1(p) (*(p) - '0' )
00234 #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
00235 #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
00236 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
00237 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
00238 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
00239
00240 static void *
00241 xmalloc (size_t n)
00242 {
00243 void *p = malloc (n);
00244 if (!p)
00245 {
00246 fputs ("\nfatal: out of core\n", stderr);
00247 exit (4);
00248 }
00249 return p;
00250 }
00251
00252
00253
00254
00255 static char *
00256 xstrdup (const char *string)
00257 {
00258 char *p = (char*)xmalloc (strlen (string)+1);
00259 strcpy (p, string);
00260 return p;
00261 }
00262
00263
00264 CryptPlug::CryptPlug() {
00265 }
00266
00267 CryptPlug::~CryptPlug() {
00268 }
00269
00270 bool CryptPlug::initialize() {
00271 GpgME::setDefaultLocale( LC_CTYPE, setlocale( LC_CTYPE, 0 ) );
00272 #ifdef Q_WS_WIN
00273
00274 #else
00275 GpgME::setDefaultLocale( LC_MESSAGES, setlocale( LC_MESSAGES, 0 ) );
00276 #endif
00277 return (gpgme_engine_check_version (GPGMEPLUG_PROTOCOL) == GPG_ERR_NO_ERROR);
00278 }
00279
00280
00281 bool CryptPlug::hasFeature( Feature flag )
00282 {
00283
00284 switch ( flag ) {
00285 case Feature_SignMessages:
00286 case Feature_VerifySignatures:
00287 case Feature_EncryptMessages:
00288 case Feature_DecryptMessages:
00289 case Feature_SendCertificates:
00290 case Feature_PinEntrySettings:
00291 case Feature_StoreMessagesWithSigs:
00292 case Feature_EncryptionCRLs:
00293 case Feature_StoreMessagesEncrypted:
00294 case Feature_CheckCertificatePath:
00295 return true;
00296 case Feature_WarnSignCertificateExpiry:
00297 case Feature_WarnSignEmailNotInCertificate:
00298 case Feature_WarnEncryptCertificateExpiry:
00299 case Feature_WarnEncryptEmailNotInCertificate:
00300 return GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS;
00301
00302 case Feature_CRLDirectoryService:
00303 case Feature_CertificateDirectoryService:
00304 case Feature_undef:
00305 default:
00306 return false;
00307 }
00308 }
00309
00310
00311 static
00312 void storeNewCharPtr( char** dest, const char* src )
00313 {
00314 int sLen = strlen( src );
00315 *dest = (char*)xmalloc( sLen + 1 );
00316 strcpy( *dest, src );
00317 }
00318
00319 bool CryptPlug::decryptMessage( const char* ciphertext,
00320 bool cipherIsBinary,
00321 int cipherLen,
00322 const char** cleartext,
00323 const char* ,
00324 int* errId,
00325 char** errTxt )
00326 {
00327 gpgme_ctx_t ctx;
00328 gpgme_error_t err;
00329 gpgme_data_t gCiphertext, gPlaintext;
00330 size_t rCLen = 0;
00331 char* rCiph = 0;
00332 bool bOk = false;
00333
00334 if( !ciphertext )
00335 return false;
00336
00337 err = gpgme_new (&ctx);
00338 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00339
00340 gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
00341
00342
00343
00344
00345
00346 gpgme_data_new_from_mem( &gCiphertext,
00347 ciphertext,
00348 cipherIsBinary
00349 ? cipherLen
00350 : strlen( ciphertext ),
00351 1 );
00352
00353 gpgme_data_new( &gPlaintext );
00354
00355 err = gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
00356 if( err ) {
00357 fprintf( stderr, "\ngpgme_op_decrypt() returned this error code: %i\n\n", err );
00358 if( errId )
00359 *errId = err;
00360 if( errTxt ) {
00361 const char* _errTxt = gpgme_strerror( err );
00362 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
00363 if( *errTxt )
00364 strcpy(*errTxt, _errTxt );
00365 }
00366 }
00367
00368 gpgme_data_release( gCiphertext );
00369
00370 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
00371
00372 *cleartext = (char*)malloc( rCLen + 1 );
00373 if( *cleartext ) {
00374 if( rCLen ) {
00375 bOk = true;
00376 strncpy((char*)*cleartext, rCiph, rCLen );
00377 }
00378 ((char*)(*cleartext))[rCLen] = 0;
00379 }
00380
00381 free( rCiph );
00382 gpgme_release( ctx );
00383 return bOk;
00384 }
00385
00386
00387 static char *
00388 trim_trailing_spaces( char *string )
00389 {
00390 char *p, *mark;
00391
00392 for( mark = NULL, p = string; *p; p++ ) {
00393 if( isspace( *p ) ) {
00394 if( !mark )
00395 mark = p;
00396 }
00397 else
00398 mark = NULL;
00399 }
00400 if( mark )
00401 *mark = '\0' ;
00402
00403 return string ;
00404 }
00405
00406
00407
00408
00409 static const unsigned char *
00410 parse_dn_part (CryptPlug::DnPair *array, const unsigned char *string)
00411 {
00412 const unsigned char *s, *s1;
00413 size_t n;
00414 char *p;
00415
00416
00417 for (s = string+1; *s && *s != '='; s++)
00418 ;
00419 if (!*s)
00420 return NULL;
00421 n = s - string;
00422 if (!n)
00423 return NULL;
00424 p = (char*)xmalloc (n+1);
00425
00426
00427 memcpy (p, string, n);
00428 p[n] = 0;
00429 trim_trailing_spaces ((char*)p);
00430
00431 for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
00432 if ( !strcasecmp ((char*)p, oidmap[i].oid) ) {
00433 free( p );
00434 p = xstrdup (oidmap[i].name);
00435 break;
00436 }
00437 array->key = p;
00438 string = s + 1;
00439
00440 if (*string == '#')
00441 {
00442 string++;
00443 for (s=string; hexdigitp (s); s++)
00444 s++;
00445 n = s - string;
00446 if (!n || (n & 1))
00447 return NULL;
00448 n /= 2;
00449 array->value = p = (char*)xmalloc (n+1);
00450
00451
00452 for (s1=string; n; s1 += 2, n--)
00453 *p++ = xtoi_2 (s1);
00454 *p = 0;
00455 }
00456 else
00457 {
00458 for (n=0, s=string; *s; s++)
00459 {
00460 if (*s == '\\')
00461 {
00462 s++;
00463 if (*s == ',' || *s == '=' || *s == '+'
00464 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
00465 || *s == '\\' || *s == '\"' || *s == ' ')
00466 n++;
00467 else if (hexdigitp (s) && hexdigitp (s+1))
00468 {
00469 s++;
00470 n++;
00471 }
00472 else
00473 return NULL;
00474 }
00475 else if (*s == '\"')
00476 return NULL;
00477 else if (*s == ',' || *s == '=' || *s == '+'
00478 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
00479 break;
00480 else
00481 n++;
00482 }
00483
00484 array->value = p = (char*)xmalloc (n+1);
00485
00486
00487 for (s=string; n; s++, n--)
00488 {
00489 if (*s == '\\')
00490 {
00491 s++;
00492 if (hexdigitp (s))
00493 {
00494 *p++ = xtoi_2 (s);
00495 s++;
00496 }
00497 else
00498 *p++ = *s;
00499 }
00500 else
00501 *p++ = *s;
00502 }
00503 *p = 0;
00504 }
00505 return s;
00506 }
00507
00508
00509
00510
00511
00512 static CryptPlug::DnPair *
00513 parse_dn (const unsigned char *string)
00514 {
00515 struct CryptPlug::DnPair *array;
00516 size_t arrayidx, arraysize;
00517
00518 if( !string )
00519 return NULL;
00520
00521 arraysize = 7;
00522 arrayidx = 0;
00523 array = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
00524
00525
00526 while (*string)
00527 {
00528 while (*string == ' ')
00529 string++;
00530 if (!*string)
00531 break;
00532 if (arrayidx >= arraysize)
00533 {
00534 struct CryptPlug::DnPair *a2;
00535
00536 arraysize += 5;
00537 a2 = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array);
00538 for (unsigned int i=0; i < arrayidx; i++)
00539 {
00540 a2[i].key = array[i].key;
00541 a2[i].value = array[i].value;
00542 }
00543 free (array);
00544 array = a2;
00545 }
00546 array[arrayidx].key = NULL;
00547 array[arrayidx].value = NULL;
00548 string = parse_dn_part (array+arrayidx, string);
00549 arrayidx++;
00550 if (!string)
00551 goto failure;
00552 while (*string == ' ')
00553 string++;
00554 if (*string && *string != ',' && *string != ';' && *string != '+')
00555 goto failure;
00556 if (*string)
00557 string++;
00558 }
00559 array[arrayidx].key = NULL;
00560 array[arrayidx].value = NULL;
00561 return array;
00562
00563 failure:
00564 for (unsigned i=0; i < arrayidx; i++)
00565 {
00566 free (array[i].key);
00567 free (array[i].value);
00568 }
00569 free (array);
00570 return NULL;
00571 }
00572
00573 static void
00574 add_dn_part( QByteArray& result, struct CryptPlug::DnPair& dnPair )
00575 {
00576
00577 QByteArray mappedPart( dnPair.key );
00578 for ( unsigned int i = 0 ; i < numOidMaps ; ++i ){
00579 if( !strcasecmp( dnPair.key, oidmap[i].oid ) ) {
00580 mappedPart = oidmap[i].name;
00581 break;
00582 }
00583 }
00584 result.append( mappedPart );
00585 result.append( "=" );
00586 result.append( dnPair.value );
00587 }
00588
00589 static int
00590 add_dn_parts( QByteArray& result, struct CryptPlug::DnPair* dn, const char* part )
00591 {
00592 int any = 0;
00593
00594 if( dn ) {
00595 for(; dn->key; ++dn ) {
00596 if( !strcmp( dn->key, part ) ) {
00597 if( any )
00598 result.append( "," );
00599 add_dn_part( result, *dn );
00600 any = 1;
00601 }
00602 }
00603 }
00604 return any;
00605 }
00606
00607 static char*
00608 reorder_dn( struct CryptPlug::DnPair *dn,
00609 char** attrOrder = 0,
00610 const char* unknownAttrsHandling = 0 )
00611 {
00612 struct CryptPlug::DnPair *dnOrg = dn;
00613
00614
00615 const char* defaultpart[] = {
00616 "CN", "S", "SN", "GN", "T", "UID",
00617 "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET",
00618 "L", "PC", "SP", "ST",
00619 "OU",
00620 "O",
00621 "C",
00622 NULL
00623 };
00624 const char** stdpart = attrOrder ? ((const char**)attrOrder) : defaultpart;
00625 int any=0, any2=0, found_X_=0, i;
00626 QByteArray result;
00627 QByteArray resultUnknowns;
00628
00629
00630 if( dn ){
00631 for(; dn->key; ++dn ) {
00632 for( i = 0; stdpart[i]; ++i ) {
00633 if( !strcmp( dn->key, stdpart[i] ) ) {
00634 break;
00635 }
00636 }
00637 if( !stdpart[i] ) {
00638 if( any2 )
00639 resultUnknowns.append( "," );
00640 add_dn_part( resultUnknowns, *dn );
00641 any2 = 1;
00642 }
00643 }
00644 dn = dnOrg;
00645 }
00646
00647
00648 if( unknownAttrsHandling &&
00649 !strcmp(unknownAttrsHandling, "PREFIX")
00650 && !resultUnknowns.isEmpty() ){
00651 result.append( resultUnknowns );
00652 any = 1;
00653 }else{
00654 any = 0;
00655 }
00656
00657
00658 for( i = 0; stdpart[i]; ++i ) {
00659 dn = dnOrg;
00660 if( any ) {
00661 result.append( "," );
00662 }
00663 if( any2 &&
00664 !strcmp(stdpart[i], "_X_") &&
00665 unknownAttrsHandling &&
00666 !strcmp(unknownAttrsHandling, "INFIX") ){
00667 if ( !resultUnknowns.isEmpty() ) {
00668 result.append( resultUnknowns );
00669 any = 1;
00670 }
00671 found_X_ = 1;
00672 }else{
00673 any = add_dn_parts( result, dn, stdpart[i] );
00674 }
00675 }
00676
00677
00678 if( !unknownAttrsHandling ||
00679 !strcmp(unknownAttrsHandling, "POSTFIX") ||
00680 ( !strcmp(unknownAttrsHandling, "INFIX") && !found_X_ ) ){
00681 if( !resultUnknowns.isEmpty() ) {
00682 if( any ){
00683 result.append( "," );
00684 }
00685 result.append( resultUnknowns );
00686 }
00687 }
00688
00689 char* cResult = (char*)xmalloc( (result.length()+1)*sizeof(char) );
00690 if( result.isEmpty() )
00691 *cResult = 0;
00692 else
00693 strcpy( cResult, result );
00694 return cResult;
00695 }
00696
00697 GpgME::ImportResult CryptPlug::importCertificateFromMem( const char* data, size_t length )
00698 {
00699 using namespace GpgME;
00700
00701 std::auto_ptr<Context> context( Context::createForProtocol( mProtocol ) );
00702 if ( !context.get() )
00703 return ImportResult();
00704
00705 Data keydata( data, length, false );
00706 if ( keydata.isNull() )
00707 return ImportResult();
00708
00709 return context->importKeys( keydata );
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 static gpgme_sig_stat_t
00721 sig_stat_from_status( gpgme_error_t err )
00722 {
00723 switch ( gpg_err_code(err) ) {
00724 case GPG_ERR_NO_ERROR:
00725 return GPGME_SIG_STAT_GOOD;
00726 case GPG_ERR_BAD_SIGNATURE:
00727 return GPGME_SIG_STAT_BAD;
00728 case GPG_ERR_NO_PUBKEY:
00729 return GPGME_SIG_STAT_NOKEY;
00730 case GPG_ERR_NO_DATA:
00731 return GPGME_SIG_STAT_NOSIG;
00732 case GPG_ERR_SIG_EXPIRED:
00733 return GPGME_SIG_STAT_GOOD_EXP;
00734 case GPG_ERR_KEY_EXPIRED:
00735 return GPGME_SIG_STAT_GOOD_EXPKEY;
00736 default:
00737 return GPGME_SIG_STAT_ERROR;
00738 }
00739 }
00740
00741
00742 static gpgme_sig_stat_t
00743 intersect_stati( gpgme_signature_t first )
00744 {
00745 if ( !first )
00746 return GPGME_SIG_STAT_NONE;
00747 gpgme_sig_stat_t result = sig_stat_from_status( first->status );
00748 for ( gpgme_signature_t sig = first->next ; sig ; sig = sig->next )
00749 if ( sig_stat_from_status( sig->status ) != result )
00750 return GPGME_SIG_STAT_DIFF;
00751 return result;
00752 }
00753
00754 static const char*
00755 sig_status_to_string( gpgme_sig_stat_t status )
00756 {
00757 const char *result;
00758
00759 switch (status) {
00760 case GPGME_SIG_STAT_NONE:
00761 result = "Oops: Signature not verified";
00762 break;
00763 case GPGME_SIG_STAT_NOSIG:
00764 result = "No signature found";
00765 break;
00766 case GPGME_SIG_STAT_GOOD:
00767 result = "Good signature";
00768 break;
00769 case GPGME_SIG_STAT_BAD:
00770 result = "BAD signature";
00771 break;
00772 case GPGME_SIG_STAT_NOKEY:
00773 result = "No public key to verify the signature";
00774 break;
00775 case GPGME_SIG_STAT_ERROR:
00776 result = "Error verifying the signature";
00777 break;
00778 case GPGME_SIG_STAT_DIFF:
00779 result = "Different results for signatures";
00780 break;
00781 default:
00782 result = "Error: Unknown status";
00783 break;
00784 }
00785
00786 return result;
00787 }
00788
00789
00790
00791 static
00792 void obtain_signature_information( gpgme_ctx_t ctx,
00793 gpgme_sig_stat_t & overallStatus,
00794 struct CryptPlug::SignatureMetaData* sigmeta,
00795 char** attrOrder,
00796 const char* unknownAttrsHandling,
00797 bool * signatureFound=0 )
00798 {
00799 gpgme_error_t err;
00800 unsigned long sumGPGME;
00801 SigStatusFlags sumPlug;
00802 struct CryptPlug::DnPair* a;
00803 int sig_idx=0;
00804
00805 assert( ctx );
00806 assert( sigmeta );
00807
00808 sigmeta->extended_info = 0;
00809 gpgme_verify_result_t result = gpgme_op_verify_result( ctx );
00810 if ( !result )
00811 return;
00812 for ( gpgme_signature_t signature = result->signatures ; signature ; signature = signature->next, ++sig_idx ) {
00813 void* alloc_return = realloc( sigmeta->extended_info,
00814 sizeof( CryptPlug::SignatureMetaDataExtendedInfo )
00815 * ( sig_idx + 1 ) );
00816 if ( !alloc_return )
00817 break;
00818 sigmeta->extended_info = (CryptPlug::SignatureMetaDataExtendedInfo*)alloc_return;
00819
00820
00821 CryptPlug::SignatureMetaDataExtendedInfo & this_info = sigmeta->extended_info[sig_idx];
00822
00823
00824 memset( &this_info, 0, sizeof (CryptPlug::SignatureMetaDataExtendedInfo) );
00825
00826
00827 if ( signature->timestamp ) {
00828 this_info.creation_time = (tm*)malloc( sizeof( struct tm ) );
00829 if ( this_info.creation_time ) {
00830 struct tm * ctime_val = localtime( (time_t*)&signature->timestamp );
00831 memcpy( this_info.creation_time,
00832 ctime_val, sizeof( struct tm ) );
00833 }
00834 }
00835
00836
00837 sumGPGME = signature->summary;
00838 fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
00839
00840 sumPlug = 0;
00841 #define convert(X) if ( sumGPGME & GPGME_SIGSUM_##X ) sumPlug |= SigStat_##X
00842 convert(VALID);
00843 convert(GREEN);
00844 convert(RED);
00845 convert(KEY_REVOKED);
00846 convert(KEY_EXPIRED);
00847 convert(SIG_EXPIRED);
00848 convert(KEY_MISSING);
00849 convert(CRL_MISSING);
00850 convert(CRL_TOO_OLD);
00851 convert(BAD_POLICY);
00852 convert(SYS_ERROR);
00853 #undef convert
00854 if( sumGPGME && !sumPlug )
00855 sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
00856 this_info.sigStatusFlags = sumPlug;
00857
00858
00859 if ( signature->fpr )
00860 storeNewCharPtr( &this_info.fingerprint, signature->fpr );
00861
00862
00863 this_info.validity = GPGME_VALIDITY_UNKNOWN;
00864
00865
00866 gpgme_key_t key = 0;
00867
00868
00869 err = gpgme_get_sig_key (ctx, sig_idx, &key);
00870
00871 if ( !err && key ) {
00872 const char* attr_string;
00873 unsigned long attr_ulong;
00874
00875
00876 attr_string = key->subkeys ? key->subkeys->keyid : 0 ;
00877 if ( attr_string )
00878 storeNewCharPtr( &this_info.keyid, attr_string );
00879
00880
00881 attr_string = key->subkeys ? gpgme_pubkey_algo_name( key->subkeys->pubkey_algo ) : 0 ;
00882 if (attr_string != 0)
00883 storeNewCharPtr( &this_info.algo, attr_string );
00884 attr_ulong = key->subkeys ? key->subkeys->pubkey_algo : 0 ;
00885 this_info.algo_num = attr_ulong;
00886
00887
00888 attr_ulong = key->uids ? key->uids->validity : 0 ;
00889 this_info.validity = attr_ulong;
00890
00891
00892
00893
00894 attr_string = key->uids ? key->uids->uid : 0 ;
00895 if (attr_string != 0) {
00896 a = parse_dn( (const unsigned char*)attr_string );
00897 this_info.userid = reorder_dn( a, attrOrder, unknownAttrsHandling );
00898 }
00899
00900 attr_ulong = 0;
00901 this_info.userid_num = attr_ulong;
00902
00903
00904 this_info.keylen = key->subkeys ? key->subkeys->length : 0 ;
00905
00906
00907 attr_ulong = key->subkeys ? key->subkeys->timestamp : 0 ;
00908 this_info.key_created = attr_ulong;
00909
00910
00911 attr_ulong = key->subkeys ? key->subkeys->expires : 0 ;
00912 this_info.key_expires = attr_ulong;
00913
00914
00915 attr_string = key->uids ? key->uids->name : 0 ;
00916 if (attr_string != 0) {
00917 a = parse_dn( (const unsigned char*)attr_string );
00918 this_info.name = reorder_dn( a, attrOrder, unknownAttrsHandling );
00919 }
00920
00921
00922 this_info.emailCount = 0;
00923 this_info.emailList = 0;
00924 for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) {
00925 attr_string = uid->email;
00926 if ( attr_string && *attr_string) {
00927 fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
00928 if( !this_info.emailCount )
00929 alloc_return = malloc( sizeof( char*) );
00930 else
00931 alloc_return = realloc( this_info.emailList,
00932 sizeof( char*)
00933 * (this_info.emailCount + 1) );
00934 if( alloc_return ) {
00935 this_info.emailList = (char**)alloc_return;
00936 storeNewCharPtr( &( this_info.emailList[ this_info.emailCount ] ),
00937 attr_string );
00938 ++this_info.emailCount;
00939 }
00940 }
00941 }
00942 if( !this_info.emailCount )
00943 fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" );
00944
00945
00946 attr_string = key->uids ? key->uids->comment : 0 ;
00947 if (attr_string != 0)
00948 storeNewCharPtr( &this_info.comment, attr_string );
00949 }
00950
00951 gpgme_sig_stat_t status = sig_stat_from_status( signature->status );
00952 const char* sig_status = sig_status_to_string( status );
00953 storeNewCharPtr( &this_info.status_text, sig_status );
00954 }
00955 sigmeta->extended_info_count = sig_idx;
00956 overallStatus = intersect_stati( result->signatures );
00957 sigmeta->status_code = overallStatus;
00958 storeNewCharPtr( &sigmeta->status, sig_status_to_string( overallStatus ) );
00959 if ( signatureFound )
00960 *signatureFound = ( overallStatus != GPGME_SIG_STAT_NONE );
00961 }
00962
00963 bool CryptPlug::checkMessageSignature( char** cleartext,
00964 const char* signaturetext,
00965 bool signatureIsBinary,
00966 int signatureLen,
00967 struct CryptPlug::SignatureMetaData* sigmeta,
00968 char** attrOrder,
00969 const char* unknownAttrsHandling )
00970 {
00971 gpgme_ctx_t ctx;
00972 gpgme_sig_stat_t status = GPGME_SIG_STAT_NONE;
00973 gpgme_data_t datapart, sigpart;
00974 char* rClear = 0;
00975 size_t clearLen;
00976 bool isOpaqueSigned;
00977
00978 if( !cleartext ) {
00979 if( sigmeta )
00980 storeNewCharPtr( &sigmeta->status,
00981 __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
00982
00983 return false;
00984 }
00985
00986 isOpaqueSigned = !*cleartext;
00987
00988 gpgme_new( &ctx );
00989 gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
00990 gpgme_set_armor (ctx, signatureIsBinary ? 0 : 1);
00991
00992
00993 if( isOpaqueSigned )
00994 gpgme_data_new( &datapart );
00995 else
00996 gpgme_data_new_from_mem( &datapart, *cleartext,
00997 strlen( *cleartext ), 1 );
00998
00999 gpgme_data_new_from_mem( &sigpart,
01000 signaturetext,
01001 signatureIsBinary
01002 ? signatureLen
01003 : strlen( signaturetext ),
01004 1 );
01005
01006 if ( isOpaqueSigned )
01007 gpgme_op_verify( ctx, sigpart, 0, datapart );
01008 else
01009 gpgme_op_verify( ctx, sigpart, datapart, 0 );
01010
01011 if( isOpaqueSigned ) {
01012 rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
01013 *cleartext = (char*)malloc( clearLen + 1 );
01014 if( *cleartext ) {
01015 if( clearLen )
01016 strncpy(*cleartext, rClear, clearLen );
01017 (*cleartext)[clearLen] = '\0';
01018 }
01019 free( rClear );
01020 }
01021 else
01022 gpgme_data_release( datapart );
01023
01024 gpgme_data_release( sigpart );
01025
01026 obtain_signature_information( ctx, status, sigmeta,
01027 attrOrder, unknownAttrsHandling );
01028
01029 gpgme_release( ctx );
01030 return ( status == GPGME_SIG_STAT_GOOD );
01031 }
01032
01033 bool CryptPlug::decryptAndCheckMessage( const char* ciphertext,
01034 bool cipherIsBinary,
01035 int cipherLen,
01036 const char** cleartext,
01037 const char* ,
01038 bool* signatureFound,
01039 struct CryptPlug::SignatureMetaData* sigmeta,
01040 int* errId,
01041 char** errTxt,
01042 char** attrOrder,
01043 const char* unknownAttrsHandling )
01044 {
01045 gpgme_ctx_t ctx;
01046 gpgme_error_t err;
01047 gpgme_decrypt_result_t decryptresult;
01048 gpgme_data_t gCiphertext, gPlaintext;
01049 gpgme_sig_stat_t sigstatus = GPGME_SIG_STAT_NONE;
01050 size_t rCLen = 0;
01051 char* rCiph = 0;
01052 bool bOk = 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 if( err ) {
01079 fprintf( stderr, "\ngpgme_op_decrypt_verify() returned this error code: %i\n\n", err );
01080 if( errId )
01081 *errId = err;
01082 if( errTxt ) {
01083 const char* _errTxt = gpgme_strerror( err );
01084 *errTxt = (char*)malloc( strlen( _errTxt ) + 1 );
01085 if( *errTxt )
01086 strcpy(*errTxt, _errTxt );
01087 }
01088 gpgme_data_release( gPlaintext );
01089 gpgme_release( ctx );
01090 return bOk;
01091 }
01092 decryptresult = gpgme_op_decrypt_result( ctx );
01093
01094 bool bWrongKeyUsage = false;
01095 #ifdef HAVE_GPGME_WRONG_KEY_USAGE
01096 if( decryptresult && decryptresult->wrong_key_usage )
01097 bWrongKeyUsage = true;
01098 #endif
01099
01100 if( bWrongKeyUsage ) {
01101 if( errId )
01102 *errId = CRYPTPLUG_ERR_WRONG_KEY_USAGE;
01103 }
01104
01105 rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
01106
01107 *cleartext = (char*)malloc( rCLen + 1 );
01108 if( *cleartext ) {
01109 if( rCLen ) {
01110 bOk = true;
01111 strncpy((char*)*cleartext, rCiph, rCLen );
01112 }
01113 ((char*)(*cleartext))[rCLen] = 0;
01114 }
01115 free( rCiph );
01116
01117 obtain_signature_information( ctx, sigstatus, sigmeta,
01118 attrOrder, unknownAttrsHandling,
01119 signatureFound );
01120
01121 gpgme_release( ctx );
01122 return bOk;
01123 }
01124