#include <config.h> #include <apt-pkg/error.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/gpgv.h> #include <string> #include <gtest/gtest.h> #include "file-helpers.h" /* The test files are created with the 'Joe Sixpack' and 'Marvin Paranoid' test key included in the integration testing framework */ TEST(OpenMaybeClearSignedFileTest,SimpleSignedFile) { std::string tempfile; FileFd fd; // Using c++11 raw-strings would be nifty, but travis doesn't support it… createTemporaryFile("simplesignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); } TEST(OpenMaybeClearSignedFileTest,WhitespaceSignedFile) { std::string tempfile; FileFd fd; // no raw-string here to protect the whitespace from cleanup createTemporaryFile("simplesignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE----- \t \n" "Hash: SHA512 \n" " \n" "Test \n" "-----BEGIN PGP SIGNATURE----- \n" " \n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt \n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l \n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg \n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k \n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx \n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns \n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq \n" "=TB1F \n" "-----END PGP SIGNATURE-----"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); } TEST(OpenMaybeClearSignedFileTest,SignedFileWithContentHeaders) { std::string tempfile; FileFd fd; createTemporaryFile("headerssignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Version: 0.8.15~exp1\n" "Hash: SHA512\n" "Comment: I love you!\n" "X-Expires: never\n" "Multilines: no\n" " yes\n" " maybe\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); } // That isn't how multiple signatures are done TEST(OpenMaybeClearSignedFileTest,SignedFileWithTwoSignatures) { std::string tempfile; FileFd fd; createTemporaryFile("doublesignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFHBAEBCgAxFiEE3mauypFRr6GHfsMd6FJdR1KBROIFAlhT/yYTHG1hcnZpbkBl\n" "eGFtcGxlLm9yZwAKCRDoUl1HUoFE4qq3B/459MSk3xCW30wc5+ul5ZxTSg6eLYPJ\n" "tfVNYi90/ZxRrYQAN+EWozEIZcxoMYp8Ans3++irkjPbHs4NsesmFKt2W5meFl4V\n" "oUzYrOh5y5GlDeF7ok5g9atQe8BojjBics+g1IBYcnaMU+ywONmlixa03IPGfxV5\n" "oTx02Xvlns20i6HRc0WFtft5q1hXo4EIlVc9O0u902SVEEkeuHF3+bCcXrNLPBJA\n" "+8dxmH5+i89f/kVqURrdHdEuA1tsTNyb2C+lvRONh21H8QRRTU/iUQSzV6vZvof5\n" "ASc9hsAZRG0xHuRU0F94V/XrkWw8QYAobJ/yxvs4L0EuA4optbSqawDB\n" "=CP8j\n" "-----END PGP SIGNATURE-----\n"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); } TEST(OpenMaybeClearSignedFileTest,TwoSimpleSignedFile) { std::string tempfile; FileFd fd; // read only the first message createTemporaryFile("twosimplesignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n" "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----"); EXPECT_TRUE(_error->empty()); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_FALSE(_error->empty()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); ASSERT_FALSE(_error->empty()); std::string msg; _error->PopMessage(msg); EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unsigned lines.", msg); } TEST(OpenMaybeClearSignedFileTest,UnsignedFile) { std::string tempfile; FileFd fd; createTemporaryFile("unsignedfile", fd, &tempfile, "Test"); EXPECT_FALSE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); } TEST(OpenMaybeClearSignedFileTest,GarbageTop) { std::string tempfile; FileFd fd; createTemporaryFile("garbagetop", fd, &tempfile, "Garbage\n" "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n"); EXPECT_FALSE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(_error->empty()); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); ASSERT_FALSE(_error->empty()); ASSERT_FALSE(_error->PendingError()); std::string msg; _error->PopMessage(msg); EXPECT_EQ("Clearsigned file '" + tempfile + "' does not start with a signed message block.", msg); } TEST(OpenMaybeClearSignedFileTest,GarbageHeader) { std::string tempfile; FileFd fd; createTemporaryFile("garbageheader", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE----- Garbage\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n"); EXPECT_FALSE(StartsWithGPGClearTextSignature(tempfile)); // beware: the file will be successfully opened as unsigned file EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "-----BEGIN PGP SIGNED MESSAGE----- Garbage\n"); EXPECT_FALSE(fd.Eof()); } TEST(OpenMaybeClearSignedFileTest,GarbageBottom) { std::string tempfile; FileFd fd; createTemporaryFile("garbagebottom", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----\n" "\n" "iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n" "cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n" "3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n" "X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n" "V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n" "pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n" "JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n" "=TB1F\n" "-----END PGP SIGNATURE-----\n" "Garbage"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(_error->empty()); EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_TRUE(fd.IsOpen()); char buffer[100]; EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer))); EXPECT_STREQ(buffer, "Test"); EXPECT_TRUE(fd.Eof()); ASSERT_FALSE(_error->empty()); ASSERT_FALSE(_error->PendingError()); std::string msg; _error->PopMessage(msg); EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unsigned lines.", msg); } TEST(OpenMaybeClearSignedFileTest,BogusNoSig) { std::string tempfile; FileFd fd; createTemporaryFile("bogusnosig", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(_error->empty()); EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_FALSE(_error->empty()); EXPECT_FALSE(fd.IsOpen()); std::string msg; _error->PopMessage(msg); EXPECT_EQ("Splitting of file " + tempfile + " failed as it doesn't contain all expected parts 0 1 0", msg); } TEST(OpenMaybeClearSignedFileTest,BogusSigStart) { std::string tempfile; FileFd fd; createTemporaryFile("bogusnosig", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n" "Hash: SHA512\n" "\n" "Test\n" "-----BEGIN PGP SIGNATURE-----"); EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile)); EXPECT_TRUE(_error->empty()); EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd)); if (tempfile.empty() == false) unlink(tempfile.c_str()); EXPECT_FALSE(_error->empty()); EXPECT_FALSE(fd.IsOpen()); std::string msg; _error->PopMessage(msg); EXPECT_EQ("Signature in file " + tempfile + " wasn't closed", msg); }