Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / KeyRing.cc
index 709224c..d6b8246 100644 (file)
@@ -310,16 +310,15 @@ namespace zypp
   PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
   {
     MIL << "Searching key [" << id << "] in keyring " << keyring << endl;
-    PublicKeyData ret;
-    for ( const PublicKeyData & key : publicKeyData( keyring ) )
+    const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
+    for_( it, keys.begin(), keys.end() )
     {
-      if ( key.providesKey( id ) )
+      if ( id == (*it).id() )
       {
-       ret = key;
-       break;
+        return *it;
       }
     }
-    return ret;
+    return PublicKeyData();
   }
 
   PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
@@ -386,14 +385,14 @@ namespace zypp
     if( signature.empty() || (!PathInfo( signature ).isExist()) )
     {
       bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
-      MIL << "askUserToAcceptUnsignedFile: " << res << endl;
+      MIL << "User decision on unsigned file: " << res << endl;
       return res;
     }
 
-    // get the id of the signature (it might be a subkey id!)
+    // get the id of the signature
     std::string id = readSignatureKeyId( signature );
 
-    // does key exists in trusted keyring
+    // doeskey exists in trusted keyring
     PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) );
     if ( trustedKeyData )
     {
@@ -406,32 +405,27 @@ namespace zypp
       {
         // bnc #393160: Comment #30: Compare at least the fingerprint
         // in case an attacker created a key the the same id.
-       //
-       // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
-       // to compare the subkey sets, to tell whether a key was updated.
-       // because created() remains unchanged if the primary key is not touched.
-       // For now we wait until a new subkey signs the data and treat it as a
-       //  new key (else part below).
         if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint()
           && trustedKeyData.created() < generalKeyData.created() )
         {
           MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
           importKey( exportKey( generalKeyData, generalKeyRing() ), true );
-         trustedKeyData = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
+         trustedKeyData = generalKeyData = PublicKeyData(); // invalidated by import.
        }
       }
 
-      // it exists, is trusted, does it validate?
+      if ( ! trustedKeyData )  // invalidated by previous import
+       trustedKeyData = publicKeyExists( id, trustedKeyRing() );
       report->infoVerify( filedesc, trustedKeyData, context );
+
+      // it exists, is trusted, does it validates?
       if ( verifyFile( file, signature, trustedKeyRing() ) )
       {
         return (sigValid_r=true);      // signature is actually successfully validated!
       }
       else
       {
-       bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( trustedKeyData, trustedKeyRing() ), context );
-       MIL << "askUserToAcceptVerificationFailed: " << res << endl;
-        return res;
+        return report->askUserToAcceptVerificationFailed( filedesc, exportKey( trustedKeyData, trustedKeyRing() ), context );
       }
     }
     else
@@ -449,6 +443,7 @@ namespace zypp
             reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
         {
           MIL << "User wants to trust key " << id << " " << key.name() << endl;
+          //dumpFile( unKey.path() );
 
           Pathname whichKeyring;
           if ( reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
@@ -460,17 +455,25 @@ namespace zypp
           else
             whichKeyring = generalKeyRing();
 
-          // does it validate?
-         report->infoVerify( filedesc, generalKeyData, context );
+          // emit key added
           if ( verifyFile( file, signature, whichKeyring ) )
           {
+            MIL << "File signature is verified" << endl;
            return (sigValid_r=true);   // signature is actually successfully validated!
           }
           else
           {
-           bool res = report->askUserToAcceptVerificationFailed( filedesc, key, context );
-           MIL << "askUserToAcceptVerificationFailed: " << res << endl;
-           return res;
+            MIL << "File signature check fails" << endl;
+            if ( report->askUserToAcceptVerificationFailed( filedesc, key, context ) )
+            {
+              MIL << "User continues anyway." << endl;
+              return true;
+            }
+            else
+            {
+              MIL << "User does not want to continue" << endl;
+              return false;
+            }
           }
         }
         else
@@ -481,11 +484,18 @@ namespace zypp
       }
       else
       {
-        // signed with an unknown key...
+        // unknown key...
         MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
-       bool res = report->askUserToAcceptUnknownKey( filedesc, id, context );
-       MIL << "askUserToAcceptUnknownKey: " << res << endl;
-       return res;
+        if ( report->askUserToAcceptUnknownKey( filedesc, id, context ) )
+        {
+          MIL << "User wants to accept unknown key " << id << endl;
+          return true;
+        }
+        else
+        {
+          MIL << "User does not want to accept unknown key " << id << endl;
+          return false;
+        }
       }
     }
     return false;
@@ -558,39 +568,58 @@ namespace zypp
       MIL << "Deleted key " << id << " from keyring " << keyring << endl;
   }
 
+
   std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
   {
     if ( ! PathInfo( signature ).isFile() )
       ZYPP_THROW(Exception( str::Format(_("Signature file %s not found")) % signature.asString() ));
 
-    MIL << "Determining key id of signature " << signature << endl;
+    MIL << "Determining key id if signature " << signature << endl;
+    // HACK create a tmp keyring with no keys
+    filesystem::TmpDir dir( _base_dir, "fake-keyring" );
+    std::string tmppath( dir.path().asString() );
+
     const char* argv[] =
     {
       GPG_BINARY,
-      "--list-packets",
+      "--homedir", tmppath.c_str(),
+      "--no-default-keyring",
+      "--quiet",
+      "--no-tty",
+      "--no-greeting",
+      "--batch",
+      "--status-fd", "1",
       signature.asString().c_str(),
       NULL
     };
-    ExternalProgram prog( argv ,ExternalProgram::Discard_Stderr, false, -1, true );
-
-    // :signature packet: algo 1, keyid 1397BC53640DB551
-    //         version 4, created 1501094968, md5len 0, sigclass 0x00
-    //         digest algo 8, begin of digest 15 89
-    //         hashed subpkt 2 len 4 (sig created 2017-07-26)
-    //         subpkt 16 len 8 (issuer key ID 1397BC53640DB551)
-    //         data: [4095 bits]
+
+    ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true );
+
+    std::string line;
+    int count = 0;
+
+    str::regex rxNoKey( "^\\[GNUPG:\\] NO_PUBKEY (.+)\n$" );
     std::string id;
-    for( std::string line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
+    for( line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
     {
-      if ( id.empty() && str::startsWith( line, ":signature packet:" ) )
+      //MIL << "[" << line << "]" << endl;
+      str::smatch what;
+      if( str::regex_match( line, what, rxNoKey ) )
       {
-       static const str::regex rxKeyId( " keyid +([0-9A-Z]+)" );
-       str::smatch what;
-       if( str::regex_match( line, what, rxKeyId ) )
-         id = what[1];
+        if ( what.size() >= 1 )
+       {
+          id = what[1];
+         break;
+       }
+        //dumpRegexpResults( what );
       }
     }
 
+    if ( count == 0 )
+    {
+      MIL << "no output" << endl;
+    }
+
     MIL << "Determined key id [" << id << "] for signature " << signature << endl;
     prog.close();
     return id;