Changeset 59679 in vbox for trunk/src/VBox/Main
- Timestamp:
- Feb 15, 2016 1:10:06 PM (9 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ApplianceImplPrivate.h
r59669 r59679 69 69 , hMemFileTheirManifest(NIL_RTVFSFILE) 70 70 , fSignerCertLoaded(false) 71 , fCertificateIsSelfSigned(false) 72 , fSignatureValid(false) 71 73 , fCertificateValid(false) 72 , fSignatureValid(false) 74 , fCertificateMissingPath(true) 75 , fCertificateValidTime(false) 73 76 , pbSignedDigest(NULL) 74 77 , cbSignedDigest(0) … … 126 129 fSignerCertLoaded = false; 127 130 } 128 enmSignedDigestType = RTDIGESTTYPE_INVALID; 129 fSignatureValid = false; 130 fCertificateValid = false; 131 fDeterminedDigestTypes = false; 132 fDigestTypes = RTMANIFEST_ATTR_SHA1 | RTMANIFEST_ATTR_SHA256 | RTMANIFEST_ATTR_SHA512; 131 enmSignedDigestType = RTDIGESTTYPE_INVALID; 132 fCertificateIsSelfSigned = false; 133 fSignatureValid = false; 134 fCertificateValid = false; 135 fCertificateMissingPath = true; 136 fCertificateValidTime = false; 137 fDeterminedDigestTypes = false; 138 fDigestTypes = RTMANIFEST_ATTR_SHA1 | RTMANIFEST_ATTR_SHA256 | RTMANIFEST_ATTR_SHA512; 139 strCertError.setNull(); 133 140 } 134 141 … … 167 174 /** Set if the SignerCert member contains usable data. */ 168 175 bool fSignerCertLoaded; 176 /** Cached RTCrX509Validity_IsValidAtTimeSpec result set by read(). */ 177 bool fCertificateIsSelfSigned; 178 /** Set by read() if pbSignedDigest verified correctly against SignerCert. */ 179 bool fSignatureValid; 169 180 /** Set by read() when the SignerCert checked out fine. */ 170 181 bool fCertificateValid; 171 /** Set by read() if pbSignedDigest verified correctly against SignerCert. */ 172 bool fSignatureValid; 182 /** Set by read() when the SignerCert certificate path couldn't be built. */ 183 bool fCertificateMissingPath; 184 /** Set by read() when the SignerCert (+path) is valid in the temporal sense. */ 185 bool fCertificateValidTime; 186 /** For keeping certificate error messages we delay from read() to import(). */ 187 Utf8Str strCertError; 173 188 /** The signed digest of the manifest. */ 174 189 uint8_t *pbSignedDigest; -
trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
r59621 r59679 1119 1119 void Appliance::i_addWarning(const char* aWarning, ...) 1120 1120 { 1121 va_list args; 1122 va_start(args, aWarning); 1123 Utf8Str str(aWarning, args); 1124 va_end(args); 1125 m->llWarnings.push_back(str); 1121 try 1122 { 1123 va_list args; 1124 va_start(args, aWarning); 1125 Utf8Str str(aWarning, args); 1126 va_end(args); 1127 m->llWarnings.push_back(str); 1128 } 1129 catch (...) 1130 { 1131 AssertFailed(); 1132 } 1126 1133 } 1127 1134 … … 1216 1223 1217 1224 case TaskOVF::Import: 1218 if (pTask->locInfo.storageType == VFSType_File) 1219 pTask->rc = pAppliance->i_importFS(pTask); 1225 /** @todo allow overriding these? */ 1226 if (!pAppliance->m->fSignatureValid && pAppliance->m->pbSignedDigest) 1227 pTask->rc = pAppliance->setError(E_FAIL, tr("The manifest signature for '%s' is not valid"), 1228 pTask->locInfo.strPath.c_str()); 1229 else if (!pAppliance->m->fCertificateValid && pAppliance->m->pbSignedDigest) 1230 { 1231 if (pAppliance->m->strCertError.isNotEmpty()) 1232 pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is not valid: %s"), 1233 pTask->locInfo.strPath.c_str(), pAppliance->m->strCertError.c_str()); 1234 else 1235 pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is not valid"), 1236 pTask->locInfo.strPath.c_str()); 1237 } 1238 else if (pAppliance->m->fCertificateMissingPath && pAppliance->m->pbSignedDigest) 1239 pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is does not have a valid CA path"), 1240 pTask->locInfo.strPath.c_str()); 1220 1241 else 1221 pTask->rc = E_NOTIMPL; 1242 { 1243 if (pTask->locInfo.storageType == VFSType_File) 1244 pTask->rc = pAppliance->i_importFS(pTask); 1245 else 1246 pTask->rc = E_NOTIMPL; 1247 } 1222 1248 break; 1223 1249 -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r59671 r59679 1570 1570 { 1571 1571 m->fSignerCertLoaded = true; 1572 m->fCertificateIsSelfSigned = RTCrX509Certificate_IsSelfSigned(&m->SignerCert); 1572 1573 1573 1574 /* … … 1701 1702 /* 1702 1703 * Validate the signed digest. 1704 * 1705 * It's possible we should allow the user to ignore signature 1706 * mismatches, but for now it's a show stopper. 1703 1707 */ 1704 1708 HRESULT hrc; … … 1734 1738 RTCrPkixSignatureRelease(hSignature); 1735 1739 } 1736 } 1740 else 1741 hrc = setErrorVrc(vrc, tr("RTCrPkixSignatureCreateByObjId failed: %Rrc"), vrc); 1742 } 1743 else 1744 hrc = setErrorVrc(vrc, tr("RTCrDigestUpdateFromVfsFile failed: %Rrc"), vrc); 1737 1745 RTCrDigestRelease(hDigest); 1738 1746 } … … 1741 1749 1742 1750 /* 1743 * If the signed digest checked out, validate the certificate. 1751 * Validate the certificate. 1752 * 1753 * We don't fail here on if we cannot validate the certificate, we postpone 1754 * that till the import stage, so that we can allow the user to ignore it. 1755 * 1756 * The certificate validity time is deliberately ignored as the OVF 1757 * specification does not include a way of timestamping the signature 1758 * and it would be seriously annoying for users if OVAs expired with 1759 * their certificates. This is of course a security concern, but the 1760 * whole signing of OVFs is currently weirdly trusting (self signed 1761 * certs), so this is the least of our current problems. 1744 1762 */ 1745 if (SUCCEEDED(hrc)) 1746 { 1747 RTERRINFOSTATIC StaticErrInfo; 1748 if (RTCrX509Certificate_IsSelfSigned(&m->SignerCert)) 1749 { 1750 /* 1751 * It's a self signed certificate. We assume the frontend will 1752 * present this fact to the user and give a choice whether this 1753 * is acceptible. But, first make sure it makes internal sense. 1754 */ 1755 /** @todo Not entirely sure if we care whether a self issued certificate is 1756 marked as CA. But let's be a little bit picky about it for now. */ 1757 if ( m->SignerCert.TbsCertificate.T3.pBasicConstraints 1758 && m->SignerCert.TbsCertificate.T3.pBasicConstraints->CA.fValue) 1763 Assert(!m->fCertificateValid); 1764 Assert(m->fCertificateMissingPath); 1765 Assert(!m->fCertificateValidTime); 1766 Assert(m->strCertError.isEmpty()); 1767 Assert(m->fCertificateIsSelfSigned == RTCrX509Certificate_IsSelfSigned(&m->SignerCert)); 1768 1769 HRESULT hrc2 = S_OK; 1770 RTERRINFOSTATIC StaticErrInfo; 1771 if (m->fCertificateIsSelfSigned) 1772 { 1773 /* 1774 * It's a self signed certificate. We assume the frontend will 1775 * present this fact to the user and give a choice whether this 1776 * is acceptible. But, first make sure it makes internal sense. 1777 */ 1778 m->fCertificateMissingPath = false; 1779 vrc = RTCrX509Certificate_VerifySignatureSelfSigned(&m->SignerCert, RTErrInfoInitStatic(&StaticErrInfo)); 1780 if (RT_SUCCESS(vrc)) 1781 { 1782 m->fCertificateValid = true; 1783 1784 /* Check whether the certificate is currently valid, just warn if not. */ 1785 RTTIMESPEC Now; 1786 if (RTCrX509Validity_IsValidAtTimeSpec(&m->SignerCert.TbsCertificate.Validity, RTTimeNow(&Now))) 1787 m->fCertificateValidTime = true; 1788 else 1789 i_addWarning(tr("Self signed certificate used to sign '%s' is not currently valid"), 1790 pTask->locInfo.strPath.c_str()); 1791 1792 /* Just warn if it's not a CA. Self-signed certificates are 1793 hardly trustworthy to start with without the user's consent. */ 1794 if ( !m->SignerCert.TbsCertificate.T3.pBasicConstraints 1795 || !m->SignerCert.TbsCertificate.T3.pBasicConstraints->CA.fValue) 1796 i_addWarning(tr("Self signed certificate used to sign '%s' is not marked as certificate authority (CA)"), 1797 pTask->locInfo.strPath.c_str()); 1798 } 1799 else 1800 { 1801 try { m->strCertError = Utf8StrFmt(tr("Verification of the self signed certificate failed (%Rrc, %s)"), 1802 vrc, StaticErrInfo.Core.pszMsg); } 1803 catch (...) { AssertFailed(); } 1804 i_addWarning(tr("Verification of the self signed certificate used to sign '%s' failed (%Rrc): %s"), 1805 pTask->locInfo.strPath.c_str(), vrc, StaticErrInfo.Core.pszMsg); 1806 } 1807 } 1808 else 1809 { 1810 /* 1811 * The certificate is not self-signed. Use the system certificate 1812 * stores to try build a path that validates successfully. 1813 */ 1814 RTCRX509CERTPATHS hCertPaths; 1815 vrc = RTCrX509CertPathsCreate(&hCertPaths, &m->SignerCert); 1816 if (RT_SUCCESS(vrc)) 1817 { 1818 /* Get trusted certificates from the system and add them to the path finding mission. */ 1819 RTCRSTORE hTrustedCerts; 1820 vrc = RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(&hTrustedCerts, 1821 RTErrInfoInitStatic(&StaticErrInfo)); 1822 if (RT_SUCCESS(vrc)) 1759 1823 { 1760 vrc = RTCrX509Certificate_VerifySignatureSelfSigned(&m->SignerCert, RTErrInfoInitStatic(&StaticErrInfo)); 1824 vrc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts); 1825 if (RT_FAILURE(vrc)) 1826 hrc2 = setError(E_FAIL, tr("RTCrX509CertPathsSetTrustedStore failed (%Rrc)"), vrc); 1827 RTCrStoreRelease(hTrustedCerts); 1828 } 1829 else 1830 hrc2 = setError(E_FAIL, 1831 tr("Failed to query trusted CAs and Certificates from the system and for the current user (%Rrc, %s)"), 1832 vrc, StaticErrInfo.Core.pszMsg); 1833 1834 /* Add untrusted intermediate certificates. */ 1835 if (RT_SUCCESS(vrc)) 1836 { 1837 /// @todo RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts); 1838 /// By scanning for additional certificates in the .cert file? It would be 1839 /// convenient to be able to supply intermediate certificates for the user, 1840 /// right? Or would that be unacceptable as it may weaken security? 1841 /// 1842 /// Anyway, we should look for intermediate certificates on the system, at 1843 /// least. 1844 } 1845 if (RT_SUCCESS(vrc)) 1846 { 1847 /* 1848 * Do the building and verification of certificate paths. 1849 */ 1850 vrc = RTCrX509CertPathsBuild(hCertPaths, RTErrInfoInitStatic(&StaticErrInfo)); 1761 1851 if (RT_SUCCESS(vrc)) 1762 1852 { 1763 /** @todo Consider the certificate expiration date!! Though see timestamp 1764 * concern below in the non-self-issued case */ 1765 hrc = S_OK; 1766 m->fCertificateValid = true; 1853 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(&StaticErrInfo)); 1854 if (RT_SUCCESS(vrc)) 1855 { 1856 /* 1857 * Mark the certificate as good. 1858 */ 1859 /** @todo check the certificate purpose? If so, share with self-signed. */ 1860 m->fCertificateValid = true; 1861 m->fCertificateMissingPath = false; 1862 1863 /* 1864 * We add a warning if the certificate path isn't valid at the current 1865 * time. Since the time is only considered during path validation and we 1866 * can repeat the validation process (but not building), it's easy to check. 1867 */ 1868 RTTIMESPEC Now; 1869 vrc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, RTTimeNow(&Now)); 1870 if (RT_SUCCESS(vrc)) 1871 { 1872 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(&StaticErrInfo)); 1873 if (RT_SUCCESS(vrc)) 1874 m->fCertificateValidTime = true; 1875 else 1876 i_addWarning(tr("The certificate used to sign '%s' (or a certificate in the path) is not currently valid (%Rrc)"), 1877 pTask->locInfo.strPath.c_str(), vrc); 1878 } 1879 else 1880 hrc2 = setErrorVrc(vrc, "RTCrX509CertPathsSetValidTimeSpec failed: %Rrc", vrc); 1881 } 1882 else if (vrc == VERR_CR_X509_CPV_NO_TRUSTED_PATHS) 1883 { 1884 m->fCertificateValid = true; 1885 i_addWarning(tr("No trusted certificate paths")); 1886 } 1887 else 1888 hrc2 = setError(E_FAIL, tr("Certificate path validation failed (%Rrc, %s)"), 1889 vrc, StaticErrInfo.Core.pszMsg); 1767 1890 } 1768 1891 else 1769 hrc = setErrorVrc(vrc, tr("Verification of the self signed certificate used to sign '%s' failed (%Rrc): %s"),1770 pTask->locInfo.strPath.c_str(),vrc, StaticErrInfo.Core.pszMsg);1892 hrc2 = setError(E_FAIL, tr("Certificate path building failed (%Rrc, %s)"), 1893 vrc, StaticErrInfo.Core.pszMsg); 1771 1894 } 1772 else 1773 hrc = setError(E_FAIL, 1774 tr("Self signed certificate used to sign '%s' is not marked as certificate authority (CA)"), 1775 pTask->locInfo.strPath.c_str()); 1895 RTCrX509CertPathsRelease(hCertPaths); 1776 1896 } 1777 1897 else 1778 { 1779 /* 1780 * The certificate is not self-signed. Use the system certificate 1781 * stores to try validate it. 1782 */ 1783 RTCRX509CERTPATHS hCertPaths; 1784 vrc = RTCrX509CertPathsCreate(&hCertPaths, &m->SignerCert); 1785 if (RT_SUCCESS(vrc)) 1786 { 1787 /* Get trusted certificates from the system and add them to the path finding mission. */ 1788 RTCRSTORE hTrustedCerts; 1789 vrc = RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(&hTrustedCerts, 1790 RTErrInfoInitStatic(&StaticErrInfo)); 1791 if (RT_SUCCESS(vrc)) 1792 { 1793 vrc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts); 1794 if (RT_FAILURE(vrc)) 1795 hrc = setError(E_FAIL, tr("RTCrX509CertPathsSetTrustedStore failed (%Rrc)"), vrc); 1796 RTCrStoreRelease(hTrustedCerts); 1797 } 1798 else 1799 hrc = setError(E_FAIL, 1800 tr("Failed to query trusted CAs and Certificates from the system and for the current user (%Rrc, %s)"), 1801 vrc, StaticErrInfo.Core.pszMsg); 1802 1803 /* Add untrusted intermediate certificates. */ 1804 if (RT_SUCCESS(vrc)) 1805 { 1806 /// @todo RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts); 1807 /// By scanning for additional certificates in the .cert file? It would be 1808 /// convenient to be able to supply intermediate certificates for the user, 1809 /// right? Or would that be unacceptable as it may weaken security? 1810 /// 1811 /// Anyway, we should look for intermediate certificates on the system, at 1812 /// least. 1813 } 1814 1815 /* Set the validation timestamp? */ 1816 if (RT_SUCCESS(vrc)) 1817 { 1818 /// @todo RTCrX509CertPathsSetValidTimeSpec(hCertPaths, pValidationTime); 1819 /// Not having a timestamp signature is a bit crippling to deployment using 1820 /// certificates with a short expiration date... Need to allow the user to 1821 } 1822 1823 if (RT_SUCCESS(vrc)) 1824 { 1825 /* 1826 * Do the building and verification. 1827 */ 1828 vrc = RTCrX509CertPathsBuild(hCertPaths, RTErrInfoInitStatic(&StaticErrInfo)); 1829 if (RT_SUCCESS(vrc)) 1830 { 1831 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(&StaticErrInfo)); 1832 if (RT_SUCCESS(vrc)) 1833 { 1834 /* 1835 * The certificate is good. 1836 */ 1837 /** @todo check the certificate purpose? */ 1838 m->fCertificateValid = true; 1839 hrc = S_OK; 1840 } 1841 else 1842 hrc = setError(E_FAIL, tr("Certificate path validation failed (%Rrc, %s)"), 1843 vrc, StaticErrInfo.Core.pszMsg); 1844 } 1845 else 1846 hrc = setError(E_FAIL, tr("Certificate path building failed (%Rrc, %s)"), 1847 vrc, StaticErrInfo.Core.pszMsg); 1848 1849 } 1850 RTCrX509CertPathsRelease(hCertPaths); 1851 } 1852 } 1898 hrc2 = setErrorVrc(vrc, tr("RTCrX509CertPathsCreate failed: %Rrc"), vrc); 1853 1899 } 1900 1901 /* Merge statuses from signature and certificate validation, prefering the signature one. */ 1902 if (SUCCEEDED(hrc) && FAILED(hrc2)) 1903 hrc = hrc2; 1904 if (FAILED(hrc)) 1905 return hrc; 1854 1906 } 1855 1907
Note:
See TracChangeset
for help on using the changeset viewer.