Changeset 84208 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- May 8, 2020 11:55:55 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 137816
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
r84167 r84208 1798 1798 * @param pszOva The name of the OVA. 1799 1799 * @param iVerbosity The noise level. 1800 * @param pStrName Where to return the manifest name. 1801 * @param phVfsManifest Where to return the manifest file handle (in mem). 1802 * @param pStrSignatureName Where to return the cert-file name if already 1803 * signed. 1800 * @param fReSign Whether it is acceptable to have an existing signature 1801 * in the OVA or not. 1802 * @param phVfsFssOva Where to return the OVA file system stream handle. 1803 * This has been opened for updating and we're positioned 1804 * at the end of the stream. 1805 * @param pStrManifestName Where to return the manifest name. 1806 * @param phVfsManifest Where to return the manifest file handle (copy in mem). 1807 * @param phVfsOldSignature Where to return the handle to the old signature object. 1808 * 1809 * @note Caller must clean up return values on failure too! 1804 1810 */ 1805 static int getManifestFromOva(const char *pszOva, unsigned iVerbosity, 1806 Utf8Str *pStrName, PRTVFSFILE phVfsManifest, Utf8Str *pStrSignatureName) 1811 static int openOvaAndGetManifestAndOldSignature(const char *pszOva, unsigned iVerbosity, bool fReSign, 1812 PRTVFSFSSTREAM phVfsFssOva, Utf8Str *pStrManifestName, 1813 PRTVFSFILE phVfsManifest, PRTVFSOBJ phVfsOldSignature) 1807 1814 { 1808 1815 /* 1809 1816 * Clear return values. 1810 1817 */ 1811 *phVfsManifest = NIL_RTVFSFILE; 1812 pStrName->setNull(); 1813 pStrSignatureName->setNull(); 1818 *phVfsFssOva = NIL_RTVFSFSSTREAM; 1819 pStrManifestName->setNull(); 1820 *phVfsManifest = NIL_RTVFSFILE; 1821 *phVfsOldSignature = NIL_RTVFSOBJ; 1814 1822 1815 1823 /* 1816 1824 * Open the file as a tar file system stream. 1817 1825 */ 1818 RTVFS IOSTREAM hVfsIosOva;1819 int rc = RTVfs IoStrmOpenNormal(pszOva, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, &hVfsIosOva);1826 RTVFSFILE hVfsFileOva; 1827 int rc = RTVfsFileOpenNormal(pszOva, RTFILE_O_OPEN | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE, &hVfsFileOva); 1820 1828 if (RT_FAILURE(rc)) 1821 return RTMsgErrorExitFailure("Failed to open OVA '%s' for reading: %Rrc", pszOva, rc);1822 1823 RTVFSFSSTREAM hVfsFss In;1824 rc = RTZipTarFsStreamF romIoStream(hVfsIosOva, 0 /*fFlags*/, &hVfsFssIn);1825 RTVfs IoStrmRelease(hVfsIosOva);1829 return RTMsgErrorExitFailure("Failed to open OVA '%s' for updating: %Rrc", pszOva, rc); 1830 1831 RTVFSFSSTREAM hVfsFssOva; 1832 rc = RTZipTarFsStreamForFile(hVfsFileOva, RTZIPTARFORMAT_DEFAULT, RTZIPTAR_C_UPDATE, &hVfsFssOva); 1833 RTVfsFileRelease(hVfsFileOva); 1826 1834 if (RT_FAILURE(rc)) 1827 1835 return RTMsgErrorExitFailure("Failed to open OVA '%s' as a TAR file: %Rrc", pszOva, rc); 1836 *phVfsFssOva = hVfsFssOva; 1828 1837 1829 1838 /* … … 1832 1841 if (iVerbosity >= 2) 1833 1842 RTMsgInfo("Scanning OVA '%s' for a manifest and signature...", pszOva); 1843 enum { kScanning, kSeenManifest, kSeenSignature } enmState = kScanning; 1834 1844 for (;;) 1835 1845 { … … 1840 1850 RTVFSOBJTYPE enmType; 1841 1851 RTVFSOBJ hVfsObj; 1842 rc = RTVfsFsStrmNext(hVfsFss In, &pszName, &enmType, &hVfsObj);1852 rc = RTVfsFsStrmNext(hVfsFssOva, &pszName, &enmType, &hVfsObj); 1843 1853 if (RT_FAILURE(rc)) 1844 1854 { … … 1851 1861 1852 1862 if (iVerbosity > 2) 1853 RTMsgInfo(" %s %s\n", 1854 enmType == RTVFSOBJTYPE_IO_STREAM || enmType == RTVFSOBJTYPE_FILE ? "file" 1855 : enmType == RTVFSOBJTYPE_DIR ? "dir " : "unk ", 1856 pszName); 1863 RTMsgInfo(" %s %s\n", RTVfsTypeName(enmType), pszName); 1857 1864 1858 1865 /* 1859 1866 * Should we process this entry? 1860 1867 */ 1861 if ( enmType == RTVFSOBJTYPE_IO_STREAM 1862 || enmType == RTVFSOBJTYPE_FILE) 1868 const char *pszSuffix = RTPathSuffix(pszName); 1869 if ( pszSuffix 1870 && RTStrICmpAscii(pszSuffix, ".mf") == 0 1871 && (enmType == RTVFSOBJTYPE_IO_STREAM || enmType == RTVFSOBJTYPE_FILE)) 1863 1872 { 1864 const char *pszSuffix = RTPathSuffix(pszName); 1865 if (pszSuffix && RTStrICmpAscii(pszSuffix, ".mf") == 0) 1873 if ( enmState >= kSeenManifest 1874 || *phVfsManifest != NIL_RTVFSFILE /* paranoia */) 1875 rc = RTMsgErrorRc(VERR_DUPLICATE, "OVA contains multiple manifests! first: %s second: %s", 1876 pStrManifestName->c_str(), pszName); 1877 else 1866 1878 { 1867 if (*phVfsManifest != NIL_RTVFSFILE) 1868 rc = RTMsgErrorRc(VERR_DUPLICATE, "OVA contains multiple manifests! first: %s second: %s", 1869 pStrName->c_str(), pszName); 1879 enmState = kSeenManifest; 1880 if (iVerbosity >= 2) 1881 RTMsgInfo("Found manifest file: %s", pszName); 1882 rc = pStrManifestName->assignNoThrow(pszName); 1883 if (RT_SUCCESS(rc)) 1884 { 1885 RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj); 1886 Assert(hVfsIos != NIL_RTVFSIOSTREAM); 1887 rc = RTVfsMemorizeIoStreamAsFile(hVfsIos, RTFILE_O_READ, phVfsManifest); 1888 RTVfsIoStrmRelease(hVfsIos); /* consumes stream handle. */ 1889 if (RT_FAILURE(rc)) 1890 rc = RTMsgErrorRc(VERR_DUPLICATE, "Failed to memorize the manifest: %Rrc", rc); 1891 } 1870 1892 else 1871 { 1872 if (iVerbosity >= 2) 1873 RTMsgInfo("Found manifest file: %s", pszName); 1874 rc = pStrName->assignNoThrow(pszName); 1875 if (RT_SUCCESS(rc)) 1876 { 1877 RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj); 1878 Assert(hVfsIos != NIL_RTVFSIOSTREAM); 1879 rc = RTVfsMemorizeIoStreamAsFile(hVfsIos, RTFILE_O_READ, phVfsManifest); 1880 RTVfsIoStrmRelease(hVfsIos); /* consumes stream handle. */ 1881 if (RT_FAILURE(rc)) 1882 rc = RTMsgErrorRc(VERR_DUPLICATE, "Failed to memorize the manifest: %Rrc", rc); 1883 } 1884 else 1885 RTMsgError("Out of memory!"); 1886 } 1893 RTMsgError("Out of memory!"); 1887 1894 } 1888 else if (pszSuffix && RTStrICmpAscii(pszSuffix, ".cert") == 0) 1895 } 1896 else if ( pszSuffix 1897 && RTStrICmpAscii(pszSuffix, ".cert") == 0 1898 && (enmType == RTVFSOBJTYPE_IO_STREAM || enmType == RTVFSOBJTYPE_FILE)) 1899 { 1900 if ( enmState >= kSeenSignature 1901 || *phVfsOldSignature != NIL_RTVFSOBJ /* paranoia */) 1902 rc = RTMsgErrorRc(VERR_WRONG_ORDER, "Multiple signature files! (%s)", pszName); 1903 else 1889 1904 { 1905 enmState = kSeenSignature; 1890 1906 if (iVerbosity >= 2) 1891 1907 RTMsgInfo("Found existing signature file: %s", pszName); 1892 rc = pStrSignatureName->assignNoThrow(pszName); 1908 *phVfsOldSignature = hVfsObj; 1909 hVfsObj = NIL_RTVFSOBJ; 1893 1910 } 1894 1911 } 1912 else if (enmState >= kSeenManifest) 1913 rc = RTMsgErrorRc(VERR_WRONG_ORDER, "Invalid OVA file ordering! (%s)", pszName); 1895 1914 1896 1915 /* … … 1903 1922 } 1904 1923 1905 RTVfsFsStrmRelease(hVfsFssIn);1906 1907 1924 /* 1908 1925 * Complain if no manifest. … … 1910 1927 if (RT_SUCCESS(rc) && *phVfsManifest == NIL_RTVFSFILE) 1911 1928 rc = RTMsgErrorRc(VERR_NOT_FOUND, "The OVA contains no manifest and cannot be signed!"); 1929 else if (RT_SUCCESS(rc) && *phVfsOldSignature != NIL_RTVFSOBJ && !fReSign) 1930 rc = RTMsgErrorRc(VERR_ALREADY_EXISTS, 1931 "The OVA is already signed! (Use the --force option to force re-signing it.)"); 1912 1932 1913 1933 return rc; 1934 } 1935 1936 1937 /** 1938 * Continues where openOvaAndGetManifestAndOldSignature() left off and writes 1939 * the signature file to the OVA. 1940 * 1941 * When @a hVfsOldSignature isn't NIL, the old signature it represent will be 1942 * replaced. The open function has already made sure there isn't anything 1943 * following the .cert file in that case. 1944 */ 1945 static int updateTheOvaSignature(RTVFSFSSTREAM hVfsFssOva, const char *pszOva, 1946 const char *pszSignatureName, RTVFSFILE hVfsFileSignature, RTVFSOBJ hVfsOldSignature) 1947 { 1948 /* 1949 * Truncate the file at the old signature, if present. 1950 */ 1951 int rc; 1952 if (hVfsOldSignature != NIL_RTVFSOBJ) 1953 { 1954 rc = RTZipTarFsStreamTruncate(hVfsFssOva, hVfsOldSignature, false /*fAfter*/); 1955 if (RT_FAILURE(rc)) 1956 return RTMsgErrorRc(rc, "RTZipTarFsStreamTruncate failed on '%s': %Rrc", pszOva, rc); 1957 } 1958 1959 /* 1960 * Append the signature file. We have to rewind it first or 1961 * we'll end up with VERR_EOF, probably not a great idea... 1962 */ 1963 rc = RTVfsFileSeek(hVfsFileSignature, 0, RTFILE_SEEK_BEGIN, NULL); 1964 if (RT_FAILURE(rc)) 1965 return RTMsgErrorRc(rc, "RTVfsFileSeek(hVfsFileSignature) failed: %Rrc", rc); 1966 1967 RTVFSOBJ hVfsObj = RTVfsObjFromFile(hVfsFileSignature); 1968 rc = RTVfsFsStrmAdd(hVfsFssOva, pszSignatureName, hVfsObj, 0 /*fFlags*/); 1969 RTVfsObjRelease(hVfsObj); 1970 if (RT_FAILURE(rc)) 1971 return RTMsgErrorRc(rc, "RTVfsFsStrmAdd('%s') failed on '%s': %Rrc", pszSignatureName, pszOva, rc); 1972 1973 /* 1974 * Terminate the file system stream. 1975 */ 1976 rc = RTVfsFsStrmEnd(hVfsFssOva); 1977 if (RT_FAILURE(rc)) 1978 return RTMsgErrorRc(rc, "RTVfsFsStrmEnd failed on '%s': %Rrc", pszOva, rc); 1979 1980 return VINF_SUCCESS; 1914 1981 } 1915 1982 … … 2003 2070 if (RT_SUCCESS(rc)) 2004 2071 { 2005 rc = (int)RTVfsFilePrintf(hVfsFileSignature, "%s(%s) = % .*Rhxs\n\n",2072 rc = (int)RTVfsFilePrintf(hVfsFileSignature, "%s(%s) = %#.*Rhxs\n\n", 2006 2073 pszDigestType, pszManifestName, cbSignature, pvSignature); 2007 2074 if (RT_SUCCESS(rc)) … … 2055 2122 2056 2123 /** 2057 * Alters the OVA file, adding (or replacing) the @a pszSignatureName member.2058 */2059 static int updateTheOvaSignature(const char *pszOva, const char *pszSignatureName, RTVFSFILE hVfsFileSignature, bool fIsSigned)2060 {2061 RT_NOREF(pszOva, pszSignatureName, hVfsFileSignature, fIsSigned);2062 2063 RTMsgError("TODO: updateTheOvaSignature");2064 return VINF_SUCCESS;2065 }2066 2067 2068 /**2069 2124 * Handles the 'ovasign' command. 2070 2125 */ … … 2195 2250 2196 2251 /* 2197 * Read the certificate and private key.2252 * Open the OVA, read the manifest and look for any existing signature. 2198 2253 */ 2199 RTERRINFOSTATIC ErrInfo; 2200 RTCRX509CERTIFICATE Certificate; 2201 rc = RTCrX509Certificate_ReadFromFile(&Certificate, pszCertificate, 0, &g_RTAsn1DefaultAllocator, 2202 RTErrInfoInitStatic(&ErrInfo)); 2203 if (RT_FAILURE(rc)) 2204 return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim", pszCertificate, rc, &ErrInfo.Core); 2205 2206 RTCRKEY hPrivateKey = NIL_RTCRKEY; 2207 rc = RTCrKeyCreateFromFile(&hPrivateKey, 0 /*fFlags*/, pszPrivateKey, strPrivateKeyPassword.c_str(), 2208 RTErrInfoInitStatic(&ErrInfo)); 2254 RTVFSFSSTREAM hVfsFssOva = NIL_RTVFSFSSTREAM; 2255 RTVFSOBJ hVfsOldSignature = NIL_RTVFSOBJ; 2256 RTVFSFILE hVfsFileManifest = NIL_RTVFSFILE; 2257 Utf8Str strManifestName; 2258 rc = openOvaAndGetManifestAndOldSignature(pszOva, iVerbosity, fReSign, 2259 &hVfsFssOva, &strManifestName, &hVfsFileManifest, &hVfsOldSignature); 2209 2260 if (RT_SUCCESS(rc)) 2210 2261 { 2211 if (iVerbosity > 1)2212 RTMsgInfo("Successfully read the certificate and private key.");2213 2214 2262 /* 2215 * Extract the manifest from the OVA and check whether it is already signed.2263 * Read the certificate and private key. 2216 2264 */ 2217 Utf8Str strManifestName; 2218 Utf8Str strSignatureName; 2219 RTVFSFILE hVfsFileManifest = NIL_RTVFSFILE; 2220 rc = getManifestFromOva(pszOva, iVerbosity, &strManifestName, &hVfsFileManifest, &strSignatureName); 2265 RTERRINFOSTATIC ErrInfo; 2266 RTCRX509CERTIFICATE Certificate; 2267 rc = RTCrX509Certificate_ReadFromFile(&Certificate, pszCertificate, 0, &g_RTAsn1DefaultAllocator, 2268 RTErrInfoInitStatic(&ErrInfo)); 2269 if (RT_FAILURE(rc)) 2270 return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim", pszCertificate, rc, &ErrInfo.Core); 2271 2272 RTCRKEY hPrivateKey = NIL_RTCRKEY; 2273 rc = RTCrKeyCreateFromFile(&hPrivateKey, 0 /*fFlags*/, pszPrivateKey, strPrivateKeyPassword.c_str(), 2274 RTErrInfoInitStatic(&ErrInfo)); 2221 2275 if (RT_SUCCESS(rc)) 2222 2276 { 2223 bool const fIsSigned = strSignatureName.isNotEmpty(); 2224 if (!fIsSigned || fReSign) 2277 if (iVerbosity > 1) 2278 RTMsgInfo("Successfully read the certificate and private key."); 2279 2280 /* 2281 * Do the signing and create the signature file. 2282 */ 2283 RTVFSFILE hVfsFileSignature = NIL_RTVFSFILE; 2284 rc = doTheOvaSigning(&Certificate, hPrivateKey, strManifestName.c_str(), hVfsFileManifest, 2285 fPkcs7, cIntermediateCerts, apszIntermediateCerts, 2286 &ErrInfo, &hVfsFileSignature); 2287 2288 /* 2289 * Construct the signature filename: 2290 */ 2291 if (RT_SUCCESS(rc)) 2225 2292 { 2226 /* 2227 * Do the signing and create the signature file. 2228 */ 2229 RTVFSFILE hVfsFileSignature = NIL_RTVFSFILE; 2230 rc = doTheOvaSigning(&Certificate, hPrivateKey, strManifestName.c_str(), hVfsFileManifest, 2231 fPkcs7, cIntermediateCerts, apszIntermediateCerts, 2232 &ErrInfo, &hVfsFileSignature); 2233 2234 /* 2235 * Construct the signature filename if there isn't one already: 2236 */ 2237 if (RT_SUCCESS(rc) && strSignatureName.isEmpty()) 2238 { 2239 rc = strSignatureName.assignNoThrow(strManifestName); 2240 if (RT_SUCCESS(rc)) 2241 rc = strSignatureName.stripSuffix().appendNoThrow(".cert"); 2242 } 2293 Utf8Str strSignatureName; 2294 rc = strSignatureName.assignNoThrow(strManifestName); 2295 if (RT_SUCCESS(rc)) 2296 rc = strSignatureName.stripSuffix().appendNoThrow(".cert"); 2243 2297 if (RT_SUCCESS(rc) && !fDryRun) 2244 2298 { … … 2246 2300 * Update the OVA. 2247 2301 */ 2248 rc = updateTheOvaSignature( pszOva, strSignatureName.c_str(), hVfsFileSignature, fIsSigned);2302 rc = updateTheOvaSignature(hVfsFssOva, pszOva, strSignatureName.c_str(), hVfsFileSignature, hVfsOldSignature); 2249 2303 } 2250 2304 } 2251 else 2252 rc = RTMsgErrorRc(VERR_ALREADY_EXISTS, 2253 "The OVA is already signed! (Use the --force option to force re-signing it.)"); 2305 RTCrKeyRelease(hPrivateKey); 2254 2306 } 2255 RTCrKeyRelease(hPrivateKey); 2307 else 2308 RTPrintf("Error reading the private key from %s: %Rrc%#RTeim", pszPrivateKey, rc, &ErrInfo.Core); 2309 RTCrX509Certificate_Delete(&Certificate); 2256 2310 } 2257 else 2258 RTPrintf("Error reading the private key from %s: %Rrc%#RTeim", pszPrivateKey, rc, &ErrInfo.Core); 2259 RTCrX509Certificate_Delete(&Certificate); 2311 2312 RTVfsObjRelease(hVfsOldSignature); 2313 RTVfsFileRelease(hVfsFileManifest); 2314 RTVfsFsStrmRelease(hVfsFssOva); 2260 2315 2261 2316 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
Note:
See TracChangeset
for help on using the changeset viewer.