libkpgp

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 <qdatetime.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( QCString() );
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( QString::null );
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( QCString() );
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( QString::null );
00179       block.setSignatureKeyId( QCString() );
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 QStringList & patterns )
00230 {
00231   return doGetPublicKeys( PGP6 " +batchmode -compatible +verbose=0 "
00232                           "+language=C -kvvc", patterns );
00233 }
00234 
00235 
00236 /*
00237 QStrList
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   QStrList 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     QCString 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(QRegExp("/\\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(QRegExp("^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     QCString 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 QStringList & 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 QCString& 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       QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00490       QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
00491       // The calculated creation date isn't exactly correct because QDateTime
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           QDateTime dt( QDate( year, month, day ), QTime( 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           QCString 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           QCString 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         QCString 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 QCString& 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 QCString& 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 QCString& str )
00777 {
00778   if( ( key == 0 ) || str.isEmpty() )
00779     return;
00780 
00781   QCString 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       QString 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
KDE Home | KDE Accessibility Home | Description of Access Keys