CVE-2012-6119 (Java, published 2013-04-02T22:55Z)
Description: 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.
Severity: LOW (CVSS v3 base score: )
Weakness: CWE-264 \u2014 Permissions, Privileges, and Access Controls
Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Repository: https://github.com/candlepin/candlepin
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 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.


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();