CVE-2012-6119: Permissions, Privileges, and Access Controls (CWE-264)
value: Candlepin before 0.7.24, as used in Red Hat Subscription Asset Manager before 1.2.1, does not properly check manifest signatures, which allows local users to modify manifests.
CWE description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Published: 2013-04-02T22:55Z
Repository: https://github.com/candlepin/candlepin
Language: Java
Files changed: candlepin.spec, code/setup/cpsetup, conf/candlepin-upstream-ca.crt, src/main/java/org/candlepin/sync/Importer.java, src/test/java/org/candlepin/sync/ImporterTest.java
Commit date: 2013-01-08 14:44:59 -0400
Commit message: 835977: Re-enable manifest signature checking.

The production/stage public candlepin certificate is now packaged in the
RPM. This is flagged as a config file but *without* noreplace, so any
deployment using their own upstream cert (we don't think there are any)
will have to restore it from the rpmsave file that results after a
candlepin rpm upgrade. This was done because we expect this to be the
desired behavior, there is no known usecase for using your own
upstream cert at this time.

Diff: diff --git a/candlepin.spec b/candlepin.spec
index 9b162399a..25a24d0bb 100644
--- a/candlepin.spec
+++ b/candlepin.spec
@@ -195,10 +195,11 @@ cd -
 %install
 rm -rf $RPM_BUILD_ROOT
 # Create the directory structure required to lay down our files
 # common
 install -d -m 755 $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/certs/
+install -m 644 conf/candlepin-upstream-ca.crt %{buildroot}%{_sysconfdir}/%{name}/certs
 install -d -m 755 $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/
 install -d -m 755 $RPM_BUILD_ROOT/%{_datadir}/%{name}/
 install -m 755 code/setup/cpsetup $RPM_BUILD_ROOT/%{_datadir}/%{name}/cpsetup
 install -m 755 code/setup/cpdb $RPM_BUILD_ROOT/%{_datadir}/%{name}/cpdb
 touch $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/%{name}.conf
@@ -281,10 +282,14 @@ fi
 %dir %{_datadir}/%{name}/
 %{_datadir}/%{name}/cpsetup
 %{_datadir}/%{name}/cpdb
 %{_sysconfdir}/%{name}/certs/
 %ghost %attr(644, root, root) %{_sysconfdir}/%{name}/certs/candlepin-ca.crt
+# Default is to track the rpm version of this cert for manifest signatures.
+# If a deployment is managing their own, they will need to restore from the
+# .rpmsave backup after upgrading the candlepin rpm.
+%config %attr(644, root, root) %{_sysconfdir}/%{name}/certs/candlepin-upstream-ca.crt
 %doc LICENSE
 %doc README
 
 %files jboss
 %defattr(-,jboss,jboss,-)
diff --git a/code/setup/cpsetup b/code/setup/cpsetup
index 8e5371858..e871bffb7 100755
--- a/code/setup/cpsetup
+++ b/code/setup/cpsetup
@@ -127,11 +127,10 @@ class TomcatSetup(object):
 class CertSetup(object):
     def __init__(self):
         self.cert_home = '/etc/candlepin/certs'
         self.ca_key_passwd = self.cert_home + '/candlepin-ca-password.txt'
         self.ca_key = self.cert_home + '/candlepin-ca.key'
-        self.ca_upstream_cert = self.cert_home + '/candlepin-upstream-ca.crt'
         self.ca_pub_key = self.cert_home + '/candlepin-ca-pub.key'
         self.ca_cert = self.cert_home + '/candlepin-ca.crt'
         self.keystore = self.cert_home + '/keystore'
 
     def generate(self):
@@ -149,11 +148,10 @@ class CertSetup(object):
         print("Creating CA public key")
         run_command_with_sudo('openssl rsa -pubout -in %s -out %s' % (self.ca_key, self.ca_pub_key))
         print("Creating CA certificate")
         run_command_with_sudo('openssl req -new -x509 -days 365 -key %s -out %s -subj "/CN=%s/C=US/L=Raleigh/"' % (self.ca_key, self.ca_cert, socket.gethostname()))
         run_command_with_sudo('openssl pkcs12 -export -in %s -inkey %s -out %s -name tomcat -CAfile %s -caname root -chain -password pass:password' % (self.ca_cert, self.ca_key, self.keystore, self.ca_cert))
-        run_command_with_sudo('cp %s %s' % (self.ca_cert, self.ca_upstream_cert))
         run_command_with_sudo('chmod a+r %s' % self.keystore)
 
 
 def write_candlepin_conf(options):
     """
diff --git a/conf/candlepin-upstream-ca.crt b/conf/candlepin-upstream-ca.crt
new file mode 100644
index 000000000..5e1f3b1d1
--- /dev/null
+++ b/conf/candlepin-upstream-ca.crt
@@ -0,0 +1,40 @@
+-----BEGIN CERTIFICATE-----
+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
+g6EHdPrR+A==
+-----END CERTIFICATE-----
diff --git a/src/main/java/org/candlepin/sync/Importer.java b/src/main/java/org/candlepin/sync/Importer.java
index b2fbc4701..21fb10d78 100644
--- a/src/main/java/org/candlepin/sync/Importer.java
+++ b/src/main/java/org/candlepin/sync/Importer.java
@@ -20,10 +20,11 @@ import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
+import java.security.cert.CertificateException;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -209,44 +210,41 @@ public class Importer {
         Map<String, Object> result = new HashMap<String, Object>();
         try {
             tmpDir = new SyncUtils(config).makeTempDir("import");
             extractArchive(tmpDir, exportFile);
 
-//           only need this call when sig file is verified
-//            exportStream = new FileInputStream(new File(tmpDir, "consumer_export.zip"));
-
-            /*
-             * Disabling this once again for a little bit longer. Dependent projects
-             * are not yet ready for it, and we're having some difficulty with the actual
-             * upstream cert to use.
-             *
-             * When we bring this back, we should probably report this conflict
-             * immediately, rather than continuing to extract and trying to find any
-             * other conflicts to pass back.
-             */
-//            boolean verifiedSignature = pki.verifySHA256WithRSAHashWithUpstreamCACert(
-//                exportStream,
-//                loadSignature(new File(tmpDir, "signature")));
-//            if (!verifiedSignature) {
-//                log.warn("Manifest signature check failed.");
-//                if (!forcedConflicts
-//                    .isForced(ImportConflicts.Conflict.SIGNATURE_CONFLICT)) {
-//                    conflicts.addConflict(
-//                        i18n.tr("Failed import file hash check."),
-//                        ImportConflicts.Conflict.SIGNATURE_CONFLICT);
-//                }
-//                else {
-//                    log.warn("Ignoring signature check failure.");
-//                }
-//            }
-
             File signature = new File(tmpDir, "signature");
             if (signature.length() == 0) {
                 throw new ImportExtractionException(i18n.tr("The archive does not " +
                                           "contain the required signature file"));
             }
 
+            exportStream = new FileInputStream(new File(tmpDir, "consumer_export.zip"));
+            boolean verifiedSignature = pki.verifySHA256WithRSAHashWithUpstreamCACert(
+                exportStream,
+                loadSignature(new File(tmpDir, "signature")));
+            if (!verifiedSignature) {
+                log.warn("Archive signature check failed.");
+                if (!overrides
+                    .isForced(Conflict.SIGNATURE_CONFLICT)) {
+
+                    /*
+                     * Normally for import conflicts that can be overridden, we try to
+                     * report them all the first time so if the user intends to override,
+                     * they can do so with just one more request. However in the case of
+                     * a bad signature, we're going to report immediately due to the nature
+                     * of what this might mean.
+                     */
+                    throw new ImportConflictException(
+                        i18n.tr("Archive failed signature check"),
+                        Conflict.SIGNATURE_CONFLICT);
+                }
+                else {
+                    log.warn("Ignoring signature check failure.");
+                }
+            }
+
             File consumerExport = new File(tmpDir, "consumer_export.zip");
             File exportDir = extractArchive(tmpDir, consumerExport);
 
             Map<String, File> importFiles = new HashMap<String, File>();
             File[] listFiles = exportDir.listFiles();
@@ -263,14 +261,10 @@ public class Importer {
                 Meta.class);
             result.put("consumer", consumer);
             result.put("meta", m);
             return result;
         }
-//        catch (CertificateException e) {
-//            log.error("Exception caught importing archive", e);
-//            throw new ImportExtractionException("unable to extract export archive", e);
-//        }
         catch (FileNotFoundException fnfe) {
             log.error("Archive file does not contain consumer_export.zip", fnfe);
             throw new ImportExtractionException(i18n.tr("The archive does not contain " +
                                            "the required consumer_export.zip file"));
         }
@@ -286,10 +280,15 @@ public class Importer {
         }
         catch (IOException e) {
             log.error("Exception caught importing archive", e);
             throw new ImportExtractionException("unable to extract export archive", e);
         }
+        catch (CertificateException e) {
+            log.error("Certificate exception checking archive signature", e);
+            throw new ImportExtractionException(
+                "Certificate exception checking archive signature", e);
+        }
         finally {
             if (tmpDir != null) {
                 try {
                     FileUtils.deleteDirectory(tmpDir);
                 }
diff --git a/src/test/java/org/candlepin/sync/ImporterTest.java b/src/test/java/org/candlepin/sync/ImporterTest.java
index 9c70c0b5e..d2b5c704c 100644
--- a/src/test/java/org/candlepin/sync/ImporterTest.java
+++ b/src/test/java/org/candlepin/sync/ImporterTest.java
@@ -29,10 +29,11 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintStream;
 import java.io.Reader;
 import java.net.URISyntaxException;
 import java.util.Date;
 import java.util.HashMap;
@@ -47,10 +48,11 @@ import org.candlepin.config.CandlepinCommonTestConfig;
 import org.candlepin.config.Config;
 import org.candlepin.config.ConfigProperties;
 import org.candlepin.model.ExporterMetadata;
 import org.candlepin.model.ExporterMetadataCurator;
 import org.candlepin.model.Owner;
+import org.candlepin.pki.PKIUtility;
 import org.candlepin.sync.Importer.ImportFile;
 import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.junit.After;
@@ -351,19 +353,47 @@ public class ImporterTest {
             return;
         }
         assertTrue(false);
     }
 
-    @Test
-    public void testImportZipSigConsumerNotZip()
+    @Test(expected = ImportConflictException.class)
+    public void testImportBadSignature()
         throws IOException, ImporterException {
+        PKIUtility pki = mock(PKIUtility.class);
         Importer i = new Importer(null, null, null, null, null, null, null,
-            null, config, null, null, null, i18n);
+            pki, config, null, null, null, i18n);
+
+        Owner owner = mock(Owner.class);
+        ConflictOverrides co = mock(ConflictOverrides.class);
+
+        File archive = new File("/tmp/file.zip");
+        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive));
+        out.putNextEntry(new ZipEntry("signature"));
+        out.write("This is the placeholder for the signature file".getBytes());
+        File ceArchive = new File("/tmp/consumer_export.zip");
+        FileOutputStream fos = new FileOutputStream(ceArchive);
+        fos.write("This is just a flat file".getBytes());
+        fos.close();
+        addFileToArchive(out, ceArchive);
+        out.close();
+
+        i.loadExport(owner, archive, co);
+    }
+
+    @Test
+    public void testImportBadConsumerZip() throws Exception {
+        PKIUtility pki = mock(PKIUtility.class);
+        Importer i = new Importer(null, null, null, null, null, null, null,
+            pki, config, null, null, null, i18n);
 
         Owner owner = mock(Owner.class);
         ConflictOverrides co = mock(ConflictOverrides.class);
 
+        // Mock a passed signature check:
+        when(pki.verifySHA256WithRSAHashWithUpstreamCACert(any(InputStream.class),
+            any(byte [].class))).thenReturn(true);
+
         File archive = new File("/tmp/file.zip");
         ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive));
         out.putNextEntry(new ZipEntry("signature"));
         out.write("This is the placeholder for the signature file".getBytes());
         File ceArchive = new File("/tmp/consumer_export.zip");
@@ -375,26 +405,32 @@ public class ImporterTest {
 
         try {
             i.loadExport(owner, archive, co);
         }
         catch (ImportExtractionException e) {
-            assertEquals(e.getMessage(), i18n.tr("The archive {0} is " +
-                "not a properly compressed file or is empty", "consumer_export.zip"));
+            System.out.println(e.getMessage());
+            assertTrue(e.getMessage().contains(
+                "not a properly compressed file or is empty"));
             return;
         }
-        assertTrue(false);
+        fail();
     }
 
     @Test
     public void testImportZipSigAndEmptyConsumerZip()
-        throws IOException, ImporterException {
+        throws Exception {
+        PKIUtility pki = mock(PKIUtility.class);
         Importer i = new Importer(null, null, null, null, null, null, null,
-            null, config, null, null, null, i18n);
+            pki, config, null, null, null, i18n);
 
         Owner owner = mock(Owner.class);
         ConflictOverrides co = mock(ConflictOverrides.class);
 
+        // Mock a passed signature check:
+        when(pki.verifySHA256WithRSAHashWithUpstreamCACert(any(InputStream.class),
+            any(byte [].class))).thenReturn(true);
+
         File archive = new File("/tmp/file.zip");
         ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive));
         out.putNextEntry(new ZipEntry("signature"));
         out.write("This is the placeholder for the signature file".getBytes());
         File ceArchive = new File("/tmp/consumer_export.zip");
@@ -406,15 +442,14 @@ public class ImporterTest {
 
         try {
             i.loadExport(owner, archive, co);
         }
         catch (ImportExtractionException e) {
-            assertEquals(e.getMessage(), i18n.tr("The consumer_export " +
-                "archive has no contents"));
+            assertTrue(e.getMessage().contains("consumer_export archive has no contents"));
             return;
         }
-        assertTrue(false);
+        fail();
     }
 
     @Test
     public void testImportNoMeta()
         throws IOException, ImporterException {

Vulnerable code:         self.ca_upstream_cert = self.cert_home + '/candlepin-upstream-ca.crt'
        run_command_with_sudo('cp %s %s' % (self.ca_cert, self.ca_upstream_cert))
//           only need this call when sig file is verified
//            exportStream = new FileInputStream(new File(tmpDir, "consumer_export.zip"));

            /*
             * Disabling this once again for a little bit longer. Dependent projects
             * are not yet ready for it, and we're having some difficulty with the actual
             * upstream cert to use.
             *
             * When we bring this back, we should probably report this conflict
             * immediately, rather than continuing to extract and trying to find any
             * other conflicts to pass back.
             */
//            boolean verifiedSignature = pki.verifySHA256WithRSAHashWithUpstreamCACert(
//                exportStream,
//                loadSignature(new File(tmpDir, "signature")));
//            if (!verifiedSignature) {
//                log.warn("Manifest signature check failed.");
//                if (!forcedConflicts
//                    .isForced(ImportConflicts.Conflict.SIGNATURE_CONFLICT)) {
//                    conflicts.addConflict(
//                        i18n.tr("Failed import file hash check."),
//                        ImportConflicts.Conflict.SIGNATURE_CONFLICT);
//                }
//                else {
//                    log.warn("Ignoring signature check failure.");
//                }
//            }

//        catch (CertificateException e) {
//            log.error("Exception caught importing archive", e);
//            throw new ImportExtractionException("unable to extract export archive", e);
//        }
    @Test
    public void testImportZipSigConsumerNotZip()
            null, config, null, null, null, i18n);
            assertEquals(e.getMessage(), i18n.tr("The archive {0} is " +
                "not a properly compressed file or is empty", "consumer_export.zip"));
        assertTrue(false);
        throws IOException, ImporterException {
            null, config, null, null, null, i18n);
            assertEquals(e.getMessage(), i18n.tr("The consumer_export " +
                "archive has no contents"));
        assertTrue(false);
Fixed code: install -m 644 conf/candlepin-upstream-ca.crt %{buildroot}%{_sysconfdir}/%{name}/certs
# Default is to track the rpm version of this cert for manifest signatures.
# If a deployment is managing their own, they will need to restore from the
# .rpmsave backup after upgrading the candlepin rpm.
%config %attr(644, root, root) %{_sysconfdir}/%{name}/certs/candlepin-upstream-ca.crt
-----BEGIN CERTIFICATE-----
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
g6EHdPrR+A==
-----END CERTIFICATE-----
import java.security.cert.CertificateException;
            exportStream = new FileInputStream(new File(tmpDir, "consumer_export.zip"));
            boolean verifiedSignature = pki.verifySHA256WithRSAHashWithUpstreamCACert(
                exportStream,
                loadSignature(new File(tmpDir, "signature")));
            if (!verifiedSignature) {
                log.warn("Archive signature check failed.");
                if (!overrides
                    .isForced(Conflict.SIGNATURE_CONFLICT)) {

                    /*
                     * Normally for import conflicts that can be overridden, we try to
                     * report them all the first time so if the user intends to override,
                     * they can do so with just one more request. However in the case of
                     * a bad signature, we're going to report immediately due to the nature
                     * of what this might mean.
                     */
                    throw new ImportConflictException(
                        i18n.tr("Archive failed signature check"),
                        Conflict.SIGNATURE_CONFLICT);
                }
                else {
                    log.warn("Ignoring signature check failure.");
                }
            }

        catch (CertificateException e) {
            log.error("Certificate exception checking archive signature", e);
            throw new ImportExtractionException(
                "Certificate exception checking archive signature", e);
        }
import java.io.InputStream;
import org.candlepin.pki.PKIUtility;
    @Test(expected = ImportConflictException.class)
    public void testImportBadSignature()
        PKIUtility pki = mock(PKIUtility.class);
            pki, config, null, null, null, i18n);

        Owner owner = mock(Owner.class);
        ConflictOverrides co = mock(ConflictOverrides.class);

        File archive = new File("/tmp/file.zip");
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive));
        out.putNextEntry(new ZipEntry("signature"));
        out.write("This is the placeholder for the signature file".getBytes());
        File ceArchive = new File("/tmp/consumer_export.zip");
        FileOutputStream fos = new FileOutputStream(ceArchive);
        fos.write("This is just a flat file".getBytes());
        fos.close();
        addFileToArchive(out, ceArchive);
        out.close();

        i.loadExport(owner, archive, co);
    }

    @Test
    public void testImportBadConsumerZip() throws Exception {
        PKIUtility pki = mock(PKIUtility.class);
        Importer i = new Importer(null, null, null, null, null, null, null,
            pki, config, null, null, null, i18n);
        // Mock a passed signature check:
        when(pki.verifySHA256WithRSAHashWithUpstreamCACert(any(InputStream.class),
            any(byte [].class))).thenReturn(true);

            System.out.println(e.getMessage());
            assertTrue(e.getMessage().contains(
                "not a properly compressed file or is empty"));
        fail();
        throws Exception {
        PKIUtility pki = mock(PKIUtility.class);
            pki, config, null, null, null, i18n);
        // Mock a passed signature check:
        when(pki.verifySHA256WithRSAHashWithUpstreamCACert(any(InputStream.class),
            any(byte [].class))).thenReturn(true);

            assertTrue(e.getMessage().contains("consumer_export archive has no contents"));
        fail();