kpgpbase6.cpp
00001 /* 00002 kpgpbase6.cpp 00003 00004 Copyright (C) 2001,2002 the KPGP authors 00005 See file AUTHORS.kpgp for details 00006 00007 This file is part of KPGP, the KDE PGP/GnuPG support library. 00008 00009 KPGP is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software Foundation, 00016 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #ifdef HAVE_CONFIG_H 00020 #include <config.h> 00021 #endif 00022 00023 #include "kpgpbase.h" 00024 00025 #include <string.h> /* strncmp */ 00026 #include <assert.h> 00027 00028 #include <tqdatetime.h> 00029 00030 #include <klocale.h> 00031 #include <kdebug.h> 00032 00033 #define PGP6 "pgp" 00034 00035 namespace Kpgp { 00036 00037 Base6::Base6() 00038 : Base2() 00039 { 00040 } 00041 00042 00043 Base6::~Base6() 00044 { 00045 } 00046 00047 00048 int 00049 Base6::decrypt( Block& block, const char *passphrase ) 00050 { 00051 int index, index2; 00052 int exitStatus = 0; 00053 00054 clear(); 00055 input = block.text(); 00056 exitStatus = run( PGP6 " +batchmode +language=C -f", passphrase); 00057 if( !output.isEmpty() ) 00058 block.setProcessedText( output ); 00059 block.setError( error ); 00060 00061 if(exitStatus == -1) { 00062 errMsg = i18n("error running PGP"); 00063 status = RUN_ERR; 00064 block.setStatus( status ); 00065 return status; 00066 } 00067 00068 // encrypted message 00069 if( error.find("File is encrypted.") != -1) 00070 { 00071 //kdDebug(5100) << "kpgpbase: message is encrypted" << endl; 00072 status |= ENCRYPTED; 00073 if((index = error.find("Key for user ID")) != -1) 00074 { 00075 // Find out the key for which the phrase is needed 00076 index = error.find(':', index) + 2; 00077 index2 = error.find('\n', index); 00078 block.setRequiredUserId( error.mid(index, index2 - index) ); 00079 //kdDebug(5100) << "Base: key needed is \"" << block.requiredUserId() << "\"!\n"; 00080 00081 // Test output length to find out, if the passphrase is 00082 // bad. If someone knows a better way, please fix this. 00085 if (!passphrase || !output.length()) 00086 { 00087 errMsg = i18n("Bad passphrase; could not decrypt."); 00088 //kdDebug(5100) << "Base: passphrase is bad" << endl; 00089 status |= BADPHRASE; 00090 status |= ERROR; 00091 } 00092 } 00093 else if( error.find("You do not have the secret key needed to decrypt this file.") != -1) 00094 { 00095 errMsg = i18n("You do not have the secret key for this message."); 00096 //kdDebug(5100) << "Base: no secret key for this message" << endl; 00097 status |= NO_SEC_KEY; 00098 status |= ERROR; 00099 } 00100 } 00101 00102 // signed message 00103 00104 // Examples (made with PGP 6.5.8) 00105 /* Example no. 1 (signed with unknown key): 00106 * File is signed. signature not checked. 00107 * Signature made 2001/11/25 11:55 GMT 00108 * key does not meet validity threshold. 00109 * 00110 * WARNING: Because this public key is not certified with a trusted 00111 * signature, it is not known with high confidence that this public key 00112 * actually belongs to: "(KeyID: 0x475027BD)". 00113 */ 00114 /* Example no. 2 (signed with untrusted key): 00115 * File is signed. Good signature from user "Joe User <joe@foo.bar>". 00116 * Signature made 2001/12/05 13:09 GMT 00117 * 00118 * WARNING: Because this public key is not certified with a trusted 00119 * signature, it is not known with high confidence that this public key 00120 * actually belongs to: "Joe User <joe@foo.bar>". 00121 */ 00122 /* Example no. 3 (signed with trusted key): 00123 * File is signed. Good signature from user "Joe User <joe@foo.bar>". 00124 * Signature made 2001/12/05 13:09 GMT 00125 */ 00126 if(((index = error.find("File is signed.")) != -1) 00127 || (error.find("Good signature") != -1 )) 00128 { 00129 //kdDebug(5100) << "Base: message is signed" << endl; 00130 status |= SIGNED; 00131 // determine the signature date 00132 if( ( index2 = error.find( "Signature made", index ) ) != -1 ) 00133 { 00134 index2 += 15; 00135 int eol = error.find( '\n', index2 ); 00136 block.setSignatureDate( error.mid( index2, eol-index2 ) ); 00137 kdDebug(5100) << "Message was signed on '" << block.signatureDate() << "'\n"; 00138 } 00139 else 00140 block.setSignatureDate( TQCString() ); 00141 // determine signature status and signature key 00142 if( error.find("signature not checked") != -1) 00143 { 00144 index = error.find("KeyID:",index); 00145 block.setSignatureKeyId( error.mid(index+9,8) ); 00146 block.setSignatureUserId( TQString() ); 00147 status |= UNKNOWN_SIG; 00148 status |= GOODSIG; 00149 } 00150 else if((index = error.find("Good signature")) != -1 ) 00151 { 00152 status |= GOODSIG; 00153 // get signer 00154 index = error.find('"',index)+1; 00155 index2 = error.find('"', index); 00156 block.setSignatureUserId( error.mid(index, index2-index) ); 00157 00158 // get key ID of signer 00159 index = error.find("KeyID:",index2); 00160 if (index == -1) 00161 block.setSignatureKeyId( TQCString() ); 00162 else 00163 block.setSignatureKeyId( error.mid(index+9,8) ); 00164 } 00165 else if( error.find("Can't find the right public key") != -1 ) 00166 { 00167 // #### fix this hack 00168 // #### This doesn't happen with PGP 6.5.8 because it seems to 00169 // #### automatically create an empty pubring if it doesn't exist. 00170 status |= UNKNOWN_SIG; 00171 status |= GOODSIG; // this is a hack... 00172 block.setSignatureUserId( i18n("??? (file ~/.pgp/pubring.pkr not found)") ); 00173 block.setSignatureKeyId( "???" ); 00174 } 00175 else 00176 { 00177 status |= ERROR; 00178 block.setSignatureUserId( TQString() ); 00179 block.setSignatureKeyId( TQCString() ); 00180 } 00181 } 00182 //kdDebug(5100) << "status = " << status << endl; 00183 block.setStatus( status ); 00184 return status; 00185 } 00186 00187 00188 Key* 00189 Base6::readPublicKey( const KeyID& keyID, 00190 const bool readTrust /* = false */, 00191 Key* key /* = 0 */ ) 00192 { 00193 int exitStatus = 0; 00194 00195 status = 0; 00196 exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kvvc " 00197 "0x" + keyID, 0, true ); 00198 00199 if(exitStatus != 0) { 00200 status = ERROR; 00201 return 0; 00202 } 00203 00204 key = parseSingleKey( output, key ); 00205 00206 if( key == 0 ) 00207 { 00208 return 0; 00209 } 00210 00211 if( readTrust ) 00212 { 00213 exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kc " 00214 "0x" + keyID, 0, true ); 00215 00216 if(exitStatus != 0) { 00217 status = ERROR; 00218 return 0; 00219 } 00220 00221 parseTrustDataForKey( key, output ); 00222 } 00223 00224 return key; 00225 } 00226 00227 00228 KeyList 00229 Base6::publicKeys( const TQStringList & patterns ) 00230 { 00231 return doGetPublicKeys( PGP6 " +batchmode -compatible +verbose=0 " 00232 "+language=C -kvvc", patterns ); 00233 } 00234 00235 00236 /* 00237 TQStrList 00238 Base6::pubKeys() 00239 { 00240 int index, index2; 00241 int exitStatus = 0; 00242 int compatibleMode = 1; 00243 00244 status = 0; 00245 exitStatus = run("pgp +batchmode +language=C -kv -f"); 00246 00247 if(exitStatus != 0) { 00248 status = ERROR; 00249 return 0; 00250 } 00251 00252 //truncate trailing "\n" 00253 if (error.length() > 1) error.truncate(error.length()-1); 00254 00255 TQStrList publicKeys; 00256 index = error.find("bits/keyID",1); // skip first to "\n" 00257 if (index ==-1) 00258 { 00259 index = error.find("Type bits",1); // skip first to "\n" 00260 if (index == -1) 00261 return 0; 00262 else 00263 compatibleMode = 0; 00264 } 00265 00266 while( (index = error.find("\n",index)) != -1) 00267 { 00268 //parse line 00269 TQCString line; 00270 if( (index2 = error.find("\n",index+1)) != -1) 00271 // skip last line 00272 { 00273 int index3; 00274 if (compatibleMode) 00275 { 00276 int index_pub = error.find("pub ",index); 00277 int index_sec = error.find("sec ",index); 00278 if (index_pub < 0) 00279 index3 = index_sec; 00280 else if (index_sec < 0) 00281 index3 = index_pub; 00282 else 00283 index3 = (index_pub < index_sec ? index_pub : index_sec); 00284 } 00285 else 00286 { 00287 int index_rsa = error.find("RSA ",index); 00288 int index_dss = error.find("DSS ",index); 00289 if (index_rsa < 0) 00290 index3 = index_dss; 00291 else if (index_dss < 0) 00292 index3 = index_rsa; 00293 else 00294 index3 = (index_rsa < index_dss ? index_rsa : index_dss); 00295 } 00296 00297 if( (index3 >index2) || (index3 == -1) ) 00298 { 00299 // second address for the same key 00300 line = error.mid(index+1,index2-index-1); 00301 line = line.stripWhiteSpace(); 00302 } else { 00303 // line with new key 00304 int index4 = error.find(TQRegExp("/\\d{2}/\\d{2} "), index); 00305 line = error.mid(index4+7,index2-index4-7); 00306 } 00307 //kdDebug(5100) << "Base: found key for " << (const char *)line << endl; 00308 00309 // don't add PGP's comments to the key list 00310 if (strncmp(line.data(),"*** KEY EXPIRED ***",19) && 00311 line.find(TQRegExp("^expires \\d{4}/\\d{2}/\\d{2}")) < 0 && 00312 strncmp(line.data(),"*** DEFAULT SIGNING KEY ***",27)) { 00313 publicKeys.append(line); 00314 } 00315 } 00316 else 00317 break; 00318 index = index2; 00319 } 00320 00321 // Also look for pgp key groups 00322 exitStatus = run("pgp +batchmode +language=C -gv -f"); 00323 00324 if(exitStatus != 0) { 00325 status = ERROR; 00326 return 0; 00327 } 00328 00329 index = 0; 00330 while ( (index = error.find("\n >", index)) != -1 ) { 00331 TQCString line; 00332 index += 4; 00333 index2 = error.find(" \"", index); 00334 line = error.mid(index, index2-index+1).stripWhiteSpace(); 00335 00336 //kdDebug(5100) << "Base6: found key group for " << line << endl; 00337 publicKeys.append(line); 00338 } 00339 00340 return publicKeys; 00341 } 00342 */ 00343 00344 00345 KeyList 00346 Base6::secretKeys( const TQStringList & patterns ) 00347 { 00348 return publicKeys( patterns ); 00349 } 00350 00351 00352 int 00353 Base6::isVersion6() 00354 { 00355 int exitStatus = 0; 00356 00357 exitStatus = run( PGP6, 0, true ); 00358 00359 if(exitStatus == -1) { 00360 errMsg = i18n("error running PGP"); 00361 status = RUN_ERR; 00362 return 0; 00363 } 00364 00365 if( error.find("Version 6") != -1) 00366 { 00367 //kdDebug(5100) << "kpgpbase: pgp version 6.x detected" << endl; 00368 return 1; 00369 } 00370 00371 //kdDebug(5100) << "kpgpbase: not pgp version 6.x" << endl; 00372 return 0; 00373 } 00374 00375 00376 Key* 00377 Base6::parseKeyData( const TQCString& output, int& offset, Key* key /* = 0 */ ) 00378 // This function parses the data for a single key which is output by PGP 6 00379 // with the following command line arguments: 00380 // +batchmode -compatible +verbose=0 +language=C -kvvc 00381 // It expects the key data to start at offset and returns the start of 00382 // the next key's data in offset. 00383 { 00384 if( ( strncmp( output.data() + offset, "DSS", 3 ) != 0 ) && 00385 ( strncmp( output.data() + offset, "RSA", 3 ) != 0 ) ) 00386 { 00387 kdDebug(5100) << "Unknown key type or corrupt key data.\n"; 00388 return 0; 00389 } 00390 00391 Subkey *subkey = 0; 00392 bool firstLine = true; 00393 bool canSign = false; 00394 bool canEncr = false; 00395 bool fpr = false; 00396 00397 while( true ) 00398 { 00399 int eol; 00400 00401 // search the end of the current line 00402 if( ( eol = output.find( '\n', offset ) ) == -1 ) 00403 break; 00404 00405 //kdDebug(5100) << "Parsing: " << output.mid(offset, eol-offset) << endl; 00406 00407 if( firstLine && ( !strncmp( output.data() + offset, "DSS", 3 ) || 00408 !strncmp( output.data() + offset, "RSA", 3 ) ) ) 00409 { // line contains primary key data 00410 // Example 1: 00411 // RSA 1024 0xE2D074D3 2001/09/09 Test Key <testkey@xyz> 00412 // Example 2 (disabled key): 00413 // RSA@ 1024 0x8CCB2C1B 2001/11/04 Disabled Test Key <disabled@xyz> 00414 // Example 3 (expired key): 00415 // RSA 1024 0x7B94827D 2001/09/09 *** KEY EXPIRED *** 00416 // Example 4 (revoked key): 00417 // RSA 1024 0x956721F9 2001/09/09 *** KEY REVOKED *** 00418 // Example 5 (default signing key): 00419 // RSA 1024 0x12345678 2001/09/09 *** DEFAULT SIGNING KEY *** 00420 // Example 6 (expiring key): 00421 // RSA 2048 0xC11DB2E5 2000/02/24 expires 2001/12/31 00422 // Example 7 (complex example): 00423 // DSS 1024 0x80E104A7 2000/06/05 expires 2002/05/31 00424 // DSS 1024 0x80E104A7 2001/06/27 *** KEY REVOKED ***expires 2002/06/27 00425 // DH 1024 0x80E104A7 2000/06/05 *** KEY REVOKED ****** KEY EXPIRED *** 00426 //kdDebug(5100)<<"Primary key data:\n"; 00427 bool sign = false; 00428 bool encr = false; 00429 00430 // set default key capabilities 00431 if( !strncmp( output.data() + offset, "DSS", 3 ) ) 00432 sign = true; 00433 if( !strncmp( output.data() + offset, "RSA", 3 ) ) 00434 { 00435 sign = true; 00436 encr = true; 00437 } 00438 00439 int pos, pos2; 00440 00441 if( key == 0 ) 00442 key = new Key(); 00443 else 00444 key->clear(); 00445 00446 subkey = new Subkey( "", false ); 00447 key->addSubkey( subkey ); 00448 // expiration date defaults to never 00449 subkey->setExpirationDate( -1 ); 00450 00451 // Key Flags 00452 switch( output[offset+3] ) 00453 { 00454 case ' ': // nothing special 00455 break; 00456 case '@': // disabled key 00457 subkey->setDisabled( true ); 00458 key->setDisabled( true ); 00459 break; 00460 default: 00461 kdDebug(5100) << "Unknown key flag.\n"; 00462 } 00463 00464 // Key Length 00465 pos = offset + 4; 00466 while( output[pos] == ' ' ) 00467 pos++; 00468 pos2 = output.find( ' ', pos ); 00469 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() ); 00470 //kdDebug(5100) << "Key Length: "<<subkey->keyLength()<<endl; 00471 00472 // Key ID 00473 pos = pos2 + 1; 00474 while( output[pos] == ' ' ) 00475 pos++; 00476 pos += 2; // skip the '0x' 00477 pos2 = output.find( ' ', pos ); 00478 subkey->setKeyID( output.mid( pos, pos2-pos ) ); 00479 //kdDebug(5100) << "Key ID: "<<subkey->keyID()<<endl; 00480 00481 // Creation Date 00482 pos = pos2 + 1; 00483 while( output[pos] == ' ' ) 00484 pos++; 00485 pos2 = output.find( ' ', pos ); 00486 int year = output.mid( pos, 4 ).toInt(); 00487 int month = output.mid( pos+5, 2 ).toInt(); 00488 int day = output.mid( pos+8, 2 ).toInt(); 00489 TQDateTime dt( TQDate( year, month, day ), TQTime( 00, 00 ) ); 00490 TQDateTime epoch( TQDate( 1970, 01, 01 ), TQTime( 00, 00 ) ); 00491 // The calculated creation date isn't exactly correct because TQDateTime 00492 // doesn't know anything about timezones and always assumes local time 00493 // although epoch is of course UTC. But as PGP 6 anyway doesn't print 00494 // the time this doesn't matter too much. 00495 subkey->setCreationDate( epoch.secsTo( dt ) ); 00496 00497 // User ID or key properties 00498 pos = pos2 + 1; 00499 while( output[pos] == ' ' ) 00500 pos++; 00501 while( pos < eol ) 00502 { // loop over User ID resp. key properties 00503 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) ) 00504 { 00505 sign = false; 00506 encr = false; 00507 subkey->setRevoked( true ); 00508 key->setRevoked( true ); 00509 pos += 19; 00510 //kdDebug(5100) << "Key was revoked.\n"; 00511 } 00512 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) ) 00513 { 00514 sign = false; 00515 encr = false; 00516 subkey->setExpired( true ); 00517 key->setExpired( true ); 00518 pos += 19; 00519 //kdDebug(5100) << "Key has expired.\n"; 00520 } 00521 else if( !strncmp( output.data() + pos, "expires ", 8 ) ) 00522 { 00523 pos += 8; 00524 int year = output.mid( pos, 4 ).toInt(); 00525 int month = output.mid( pos+5, 2 ).toInt(); 00526 int day = output.mid( pos+8, 2 ).toInt(); 00527 TQDateTime dt( TQDate( year, month, day ), TQTime( 00, 00 ) ); 00528 // Here the same comments as for the creation date are valid. 00529 subkey->setExpirationDate( epoch.secsTo( dt ) ); 00530 pos += 10; 00531 //kdDebug(5100) << "Key expires...\n"; 00532 } 00533 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) ) 00534 { 00535 pos += 27; 00536 //kdDebug(5100) << "Key is default signing key.\n"; 00537 } 00538 else 00539 { 00540 TQCString uid = output.mid( pos, eol-pos ); 00541 key->addUserID( uid ); 00542 pos = eol; 00543 //kdDebug(5100) << "User ID:"<<uid<<endl; 00544 } 00545 } 00546 // set key capabilities of the primary subkey 00547 subkey->setCanEncrypt( encr ); 00548 subkey->setCanSign( sign ); 00549 subkey->setCanCertify( sign ); 00550 // remember the global key capabilities 00551 canSign = sign; 00552 canEncr = encr; 00553 } 00554 else if( !strncmp( output.data() + offset, "DSS", 3 ) || 00555 !strncmp( output.data() + offset, " DH", 3 ) || 00556 !strncmp( output.data() + offset, "RSA", 3 ) ) 00557 { // line contains secondary key data (or data for the next key) 00558 if( fpr ) 00559 break; // here begins the next key's data 00560 //kdDebug(5100)<<"Secondary key data:\n"; 00561 00562 if( key == 0 ) 00563 break; 00564 00565 bool sign = false; 00566 bool encr = false; 00567 00568 // set default key capabilities 00569 if( !strncmp( output.data() + offset, "DSS", 3 ) ) 00570 sign = true; 00571 if( !strncmp( output.data() + offset, " DH", 3 ) ) 00572 encr = true; 00573 if( !strncmp( output.data() + offset, "RSA", 3 ) ) 00574 { 00575 sign = true; 00576 encr = true; 00577 } 00578 00579 int pos, pos2; 00580 00581 // Key Length of secondary key (ignored) 00582 pos = offset + 4; 00583 while( output[pos] == ' ' ) 00584 pos++; 00585 pos2 = output.find( ' ', pos ); 00586 00587 // Key ID (ignored as it is anyway equal to the primary key id) 00588 pos = pos2 + 1; 00589 while( output[pos] == ' ' ) 00590 pos++; 00591 pos2 = output.find( ' ', pos ); 00592 00593 // Creation Date of secondary key (ignored) 00594 pos = pos2 + 1; 00595 while( output[pos] == ' ' ) 00596 pos++; 00597 pos2 = output.find( ' ', pos ); 00598 00599 // User ID or key properties 00600 pos = pos2 + 1; 00601 while( output[pos] == ' ' ) 00602 pos++; 00603 while( pos < eol ) 00604 { // loop over User ID resp. key properties 00605 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) ) 00606 { 00607 sign = false; 00608 encr = false; 00609 pos += 19; 00610 //kdDebug(5100) << "Key was revoked.\n"; 00611 } 00612 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) ) 00613 { 00614 sign = false; 00615 encr = false; 00616 pos += 19; 00617 //kdDebug(5100) << "Key has expired.\n"; 00618 } 00619 else if( !strncmp( output.data() + pos, "expires ", 8 ) ) 00620 { 00621 pos += 18; // skip the expiration date 00622 //kdDebug(5100) << "Key expires...\n"; 00623 } 00624 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) ) 00625 { 00626 pos += 27; 00627 //kdDebug(5100) << "Key is default signing key.\n"; 00628 } 00629 else 00630 { 00631 TQCString uid = output.mid( pos, eol-pos ); 00632 key->addUserID( uid ); 00633 pos = eol; 00634 //kdDebug(5100) << "User ID:"<<uid<<endl; 00635 } 00636 } 00637 // store the global key capabilities 00638 canSign = canSign || sign; 00639 canEncr = canEncr || encr; 00640 } 00641 else if( !strncmp( output.data() + offset, "Unknown type", 12 ) ) 00642 { // line contains key data of unknown type (ignored) 00643 kdDebug(5100)<<"Unknown key type.\n"; 00644 } 00645 else if( output[offset] == ' ' ) 00646 { // line contains additional key data 00647 if( key == 0 ) 00648 break; 00649 //kdDebug(5100)<<"Additional key data:\n"; 00650 00651 int pos = offset + 1; 00652 while( output[pos] == ' ' ) 00653 pos++; 00654 00655 if( !strncmp( output.data() + pos, "Key fingerprint = ", 18 ) ) 00656 { // line contains a fingerprint 00657 // Example: 00658 // Key fingerprint = D0 6C BB 3A F5 16 82 C4 F3 A0 8A B3 7B 16 99 70 00659 00660 fpr = true; // we found a fingerprint 00661 00662 pos += 18; 00663 TQCString fingerprint = output.mid( pos, eol-pos ); 00664 // remove white space from the fingerprint 00665 for ( int idx = 0 ; (idx = fingerprint.find(' ', idx)) >= 0 ; ) 00666 fingerprint.replace( idx, 1, "" ); 00667 00668 //kdDebug(5100)<<"Fingerprint: "<<fingerprint<<endl; 00669 assert( subkey != 0 ); 00670 subkey->setFingerprint( fingerprint ); 00671 } 00672 else 00673 { // line contains an additional user id 00674 // Example: 00675 // Test key (2nd user ID) <abc@xyz> 00676 00677 //kdDebug(5100)<<"User ID: "<<output.mid( pos, eol-pos )<<endl; 00678 key->addUserID( output.mid( pos, eol-pos ) ); 00679 } 00680 } 00681 else if( !strncmp( output.data() + offset, "sig", 3 ) ) 00682 { // line contains signature data (ignored) 00683 //kdDebug(5100)<<"Signature.\n"; 00684 } 00685 else // end of key data 00686 break; 00687 00688 firstLine = false; 00689 offset = eol + 1; 00690 } 00691 00692 if( key != 0 ) 00693 { 00694 // set the global key capabilities 00695 key->setCanEncrypt( canEncr ); 00696 key->setCanSign( canSign ); 00697 key->setCanCertify( canSign ); 00698 //kdDebug(5100)<<"Key capabilities: "<<(canEncr?"E":"")<<(canSign?"SC":"")<<endl; 00699 } 00700 00701 return key; 00702 } 00703 00704 00705 Key* 00706 Base6::parseSingleKey( const TQCString& output, Key* key /* = 0 */ ) 00707 { 00708 int offset; 00709 00710 // search start of header line 00711 if( !strncmp( output.data(), "Type bits", 9 ) ) 00712 offset = 9; 00713 else 00714 { 00715 offset = output.find( "\nType bits" ); 00716 if( offset == -1 ) 00717 return 0; 00718 else 00719 offset += 10; 00720 } 00721 00722 // key data begins in the next line 00723 offset = output.find( '\n', offset ) + 1; 00724 if( offset == 0 ) 00725 return 0; 00726 00727 key = parseKeyData( output, offset, key ); 00728 00729 //kdDebug(5100) << "finished parsing keys" << endl; 00730 00731 return key; 00732 } 00733 00734 00735 KeyList 00736 Base6::parseKeyList( const TQCString& output, bool secretKeys ) 00737 { 00738 kdDebug(5100) << "Kpgp::Base6::parseKeyList()" << endl; 00739 KeyList keys; 00740 Key *key = 0; 00741 int offset; 00742 00743 // search start of header line 00744 if( !strncmp( output.data(), "Type bits", 9 ) ) 00745 offset = 0; 00746 else 00747 { 00748 offset = output.find( "\nType bits" ) + 1; 00749 if( offset == 0 ) 00750 return keys; 00751 } 00752 00753 // key data begins in the next line 00754 offset = output.find( '\n', offset ) + 1; 00755 if( offset == -1 ) 00756 return keys; 00757 00758 do 00759 { 00760 key = parseKeyData( output, offset ); 00761 if( key != 0 ) 00762 { 00763 key->setSecret( secretKeys ); 00764 keys.append( key ); 00765 } 00766 } 00767 while( key != 0 ); 00768 00769 //kdDebug(5100) << "finished parsing keys" << endl; 00770 00771 return keys; 00772 } 00773 00774 00775 void 00776 Base6::parseTrustDataForKey( Key* key, const TQCString& str ) 00777 { 00778 if( ( key == 0 ) || str.isEmpty() ) 00779 return; 00780 00781 TQCString keyID = "0x" + key->primaryKeyID(); 00782 UserIDList userIDs = key->userIDs(); 00783 00784 // search the start of the trust data 00785 int offset = str.find( "\n\n KeyID" ); 00786 if( offset == -1 ) 00787 return; 00788 00789 offset = str.find( '\n', offset ) + 1; 00790 if( offset == 0 ) 00791 return; 00792 00793 bool ultimateTrust = false; 00794 if( !strncmp( str.data() + offset+13, "ultimate", 8 ) ) 00795 ultimateTrust = true; 00796 00797 while( true ) 00798 { // loop over all trust information about this key 00799 00800 int eol; 00801 00802 // search the end of the current line 00803 if( ( eol = str.find( '\n', offset ) ) == -1 ) 00804 break; 00805 00806 if( str[offset+23] != ' ' ) 00807 { // line contains a validity value for a user ID 00808 00809 // determine the validity 00810 Validity validity = KPGP_VALIDITY_UNKNOWN; 00811 if( !strncmp( str.data() + offset+23, "complete", 8 ) ) 00812 if( ultimateTrust ) 00813 validity = KPGP_VALIDITY_ULTIMATE; 00814 else 00815 validity = KPGP_VALIDITY_FULL; 00816 else if( !strncmp( str.data() + offset+23, "marginal", 8 ) ) 00817 validity = KPGP_VALIDITY_MARGINAL; 00818 else if( !strncmp( str.data() + offset+23, "invalid", 7 ) ) 00819 validity = KPGP_VALIDITY_UNDEFINED; 00820 00821 // determine the user ID 00822 int pos = offset + 33; 00823 TQString uid = str.mid( pos, eol-pos ); 00824 00825 // set the validity of the corresponding user ID 00826 for( UserIDListIterator it( userIDs ); it.current(); ++it ) 00827 if( (*it)->text() == uid ) 00828 { 00829 kdDebug(5100)<<"Setting the validity of "<<uid<<" to "<<validity<<endl; 00830 (*it)->setValidity( validity ); 00831 break; 00832 } 00833 } 00834 00835 offset = eol + 1; 00836 } 00837 } 00838 00839 00840 } // namespace Kpgp