From fb218ff20a6fe46458cb184025272503c9a64f19 Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Sun, 25 Dec 2022 13:52:20 -0600 Subject: [PATCH 1/3] relocating wallet files under wlsdeploy in archive --- .../weblogic/deploy/util/FileUtils.java | 67 +--- .../deploy/util/WLSDeployArchive.java | 304 +++++++++++++----- core/src/main/python/discover.py | 25 +- .../wlsdeploy/tool/util/archive_helper.py | 16 +- .../deploy/messages/wlsdeploy_rb.properties | 7 + .../weblogic/deploy/util/FileUtilsTest.java | 58 ---- .../deploy/util/WLSDeployArchiveTest.java | 138 ++++++++ .../atp-deprecated-empty-archive.zip | Bin 0 -> 170 bytes .../atp-deprecated-expanded-archive.zip | Bin 0 -> 25599 bytes .../atp-deprecated-zipped-archive.zip | Bin 0 -> 25615 bytes core/src/test/resources/atp-empty-archive.zip | Bin 0 -> 190 bytes .../test/resources/atp-expanded-archive.zip | Bin 0 -> 25947 bytes .../src/test/resources/atp-zipped-archive.zip | Bin 0 -> 25803 bytes 13 files changed, 389 insertions(+), 226 deletions(-) create mode 100644 core/src/test/resources/atp-deprecated-empty-archive.zip create mode 100644 core/src/test/resources/atp-deprecated-expanded-archive.zip create mode 100644 core/src/test/resources/atp-deprecated-zipped-archive.zip create mode 100644 core/src/test/resources/atp-empty-archive.zip create mode 100644 core/src/test/resources/atp-expanded-archive.zip create mode 100644 core/src/test/resources/atp-zipped-archive.zip diff --git a/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java b/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java index c12f57f5b..bfa9427fd 100644 --- a/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java +++ b/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle Corporation and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. */ package oracle.weblogic.deploy.util; @@ -617,75 +617,10 @@ public static byte[] readInputStreamToByteArray(InputStream input) throws IOExce return outputStream.toByteArray(); } - public static File writeInputStreamToFile(InputStream input, String fileName) throws IOException { - File tmpdir = getTmpDir(); - File file = new File(tmpdir, fileName); - try (FileOutputStream fos = new FileOutputStream(file)) { - byte[] byteArray = FileUtils.readInputStreamToByteArray(input); - fos.write(byteArray); - } - return file; - } - public static File getTmpDir() { return new File(System.getProperty("java.io.tmpdir")); } - public static void extractZipFileContent(WLSDeployArchive archiveFile, String zipEntry, String extractPath) { - final String METHOD = "extractZipFileContent"; - - try { - if (zipEntry != null) { - File extractDir = new File(extractPath); - extractDir.mkdirs(); - String walletZip = archiveFile.extractFile(zipEntry, - Files.createTempDirectory("tempwallet").toFile()); - - if (!Files.exists(Paths.get(extractPath))) { - Files.createDirectory(Paths.get(extractPath)); - } - - // verify that each target file is under the extract directory, - // to protect from the file overwrite security vulnerability (zip slip). - String canonicalExtractPath = extractDir.getCanonicalPath(); - - byte[] buffer = new byte[1024]; - FileInputStream fis = new FileInputStream(walletZip); - ZipInputStream zis = new ZipInputStream(fis); - ZipEntry ze = zis.getNextEntry(); - while (ze != null) { - String fileName = ze.getName(); - File newFile = new File(extractPath + File.separator + fileName); - String canonicalNewFile = newFile.getCanonicalPath(); - if(!canonicalNewFile.startsWith(canonicalExtractPath + File.separator)) { - throw new WLSDeployArchiveIOException("WLSDPLY-01119", ze.getName()); - } - - new File(newFile.getParent()).mkdirs(); - FileOutputStream fos = new FileOutputStream(newFile); - int len = zis.read(buffer); - while (len > 0) { - fos.write(buffer, 0, len); - len = zis.read(buffer); - } - fos.close(); - zis.closeEntry(); - ze = zis.getNextEntry(); - } - zis.closeEntry(); - zis.close(); - fis.close(); - Files.delete(Paths.get(walletZip)); - } - } catch (IOException | WLSDeployArchiveIOException ioe) { - String message = ExceptionHelper.getMessage("WLSDPLY-01118", archiveFile.getArchiveFileName(), - ioe.getLocalizedMessage()); - IllegalArgumentException iae = new IllegalArgumentException(message); - LOGGER.throwing(CLASS, METHOD, iae); - throw iae; - } - } - /** * Return a PrintWriter instance for the provided file name. * @param fileName Name of output file diff --git a/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java b/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java index 07804615b..8ddcb7873 100644 --- a/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java +++ b/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java @@ -11,7 +11,9 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.Files; import java.security.NoSuchAlgorithmException; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.jar.JarFile; @@ -33,20 +35,26 @@ public class WLSDeployArchive { public static final String WLSDPLY_ARCHIVE_BINARY_DIR = "wlsdeploy"; /** - * Top-level archive subdirectory where the config - * will be extracted. + * Top-level archive subdirectory where the config will be extracted. */ public static final String ARCHIVE_CONFIG_TARGET_DIR = WLSDPLY_ARCHIVE_BINARY_DIR + "/config"; + // Deprecated top-level archive subdirectory where the atp wallet is stored. + public static final String OLD_ARCHIVE_ATP_WALLET_PATH = "atpwallet"; + + // Deprecated top-level archive subdirectory where the opss wallet is stored. + public static final String OLD_ARCHIVE_OPSS_WALLET_PATH = "opsswallet"; + /** - * Top-level archive subdirectory where the atp wallet is stored + * Top-level archive subdirectory where the atp wallet is stored. */ - public static final String ARCHIVE_ATP_WALLET_PATH = "atpwallet"; + public static final String ARCHIVE_ATP_WALLET_PATH = WLSDPLY_ARCHIVE_BINARY_DIR + "/atpwallet"; /** - * Top-level archive subdirectory where the opss wallet is stored + * Top-level archive subdirectory where the opss wallet is stored. */ - public static final String ARCHIVE_OPSS_WALLET_PATH = "opsswallet"; + public static final String ARCHIVE_OPSS_WALLET_PATH = WLSDPLY_ARCHIVE_BINARY_DIR + "/opsswallet"; + /** * Top-level archive subdirectory where the model is stored and the subdirectory to which it will be extracted. */ @@ -129,7 +137,8 @@ public class WLSDeployArchive { */ public static final String ARCHIVE_JMS_FOREIGN_SERVER_DIR = ARCHIVE_JMS_DIR + "/foreignServer"; - public enum ArchiveEntryType { SHARED_LIBRARIES, APPLICATIONS, + public enum ArchiveEntryType { + SHARED_LIBRARIES, APPLICATIONS, APPLICATION_PLAN, SHLIB_PLAN, DOMAIN_LIB, @@ -179,17 +188,6 @@ public WLSDeployArchive(String archiveFileName) { LOGGER.exiting(CLASS, METHOD); } - /** - * Constructor to create an archive file instance for no generation of an archive file. - */ - private WLSDeployArchive() { - final String METHOD = ""; - LOGGER.entering(CLASS, METHOD); - LOGGER.exiting(CLASS, METHOD); - } - - public static WLSDeployArchive noArchiveFile() {return new WLSDeployArchive();} - /** * Determine whether or not the specified path string is a valid archive location. * @@ -202,8 +200,9 @@ public static boolean isPathIntoArchive(String path) { LOGGER.entering(CLASS, METHOD, path); boolean result = false; if (!StringUtils.isEmpty(path)) { - result = path.startsWith(WLSDPLY_ARCHIVE_BINARY_DIR + ZIP_SEP) || path - .startsWith(ARCHIVE_ATP_WALLET_PATH + ZIP_SEP) || path.startsWith(ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); + result = path.startsWith(WLSDPLY_ARCHIVE_BINARY_DIR + ZIP_SEP) + || path.startsWith(OLD_ARCHIVE_ATP_WALLET_PATH + ZIP_SEP) + || path.startsWith(OLD_ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); } LOGGER.exiting(CLASS, METHOD, result); return result; @@ -298,7 +297,7 @@ public File extractModel(File modelDirectory) throws WLSDeployArchiveIOException } /** - * Determines whether or not the archive contains a model file. + * Determines whether the archive contains a model file. * * @return true if the archive contains a model file, false otherwise * @throws WLSDeployArchiveIOException if an error occurs while reading the archive @@ -581,6 +580,7 @@ public String getApplicationArchivePath(String appPath) { /** * Get the archive path for the application in a well-formed application directory + * * @param appPath name of the application path * @return archive path for use in the model */ @@ -625,7 +625,7 @@ public String replaceApplication(String appPath, String tempFile) throws WLSDepl } public String addApplicationFolder(String appName, String appPath) - throws WLSDeployArchiveIOException { + throws WLSDeployArchiveIOException { final String METHOD = "addApplicationFolder"; LOGGER.entering(CLASS, METHOD, appName, appPath); File zipPath = new File(appPath); @@ -639,7 +639,7 @@ public String addApplicationFolder(String appName, String appPath) } public String addApplicationPlanFolder(String appName, String planDir) - throws WLSDeployArchiveIOException { + throws WLSDeployArchiveIOException { final String METHOD = "addApplicationPathFolder"; LOGGER.entering(CLASS, METHOD, appName, planDir); File zipPlan = new File(planDir); @@ -668,43 +668,75 @@ public List listApplications() throws WLSDeployArchiveIOException { } /** - * Get the path of the ATP wallet in the archive. + * Extract the ATP wallet in the archive. * - * @return path of the ATP wallet - * @throws WLSDeployArchiveIOException if an error occurs reading the archive + * @param domainHome the domain home directory + * @return the full path to the directory containing the extracted wallet files or null, if no wallet was found. + * @throws WLSDeployArchiveIOException if an error occurs while reading or extracting the archive files. */ - public String getATPWallet() throws WLSDeployArchiveIOException { - final String METHOD = "getATPWallet"; + public String extractATPWallet(File domainHome) throws WLSDeployArchiveIOException { + final String METHOD = "extractATPWallet"; - LOGGER.entering(CLASS, METHOD); - List result = getZipFile().listZipEntries(ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); - result.remove(ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); - LOGGER.exiting(CLASS, METHOD, result); - if (result.isEmpty()) { - return null; + LOGGER.entering(CLASS, METHOD, domainHome); + validateExistingDirectory(domainHome, "domainHome", getArchiveFileName(), METHOD); + + // Look in the updated location first + String extractPath = null; + List zipEntries = getZipFile().listZipEntries(ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); + zipEntries.remove(ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); + if (!zipEntries.isEmpty()) { + extractPath = ARCHIVE_ATP_WALLET_PATH + ZIP_SEP; + extractWallet(domainHome, extractPath, zipEntries, null); + extractPath = new File(domainHome, extractPath).getAbsolutePath(); } else { - return result.get(0); + // Look in the deprecated location. + zipEntries = getZipFile().listZipEntries(OLD_ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); + zipEntries.remove(OLD_ARCHIVE_ATP_WALLET_PATH + ZIP_SEP); + if (!zipEntries.isEmpty()) { + extractPath = ARCHIVE_ATP_WALLET_PATH + ZIP_SEP; + extractWallet(domainHome, extractPath, zipEntries, "WLSDPLY-01427"); + extractPath = new File(domainHome, extractPath).getAbsolutePath(); + } } + + LOGGER.exiting(CLASS, METHOD, extractPath); + return extractPath; } /** - * Get the path of the OPSS wallet in the archive. + * Extract the OPSS wallet from the archive. * - * @return path of the OPSS wallet - * @throws WLSDeployArchiveIOException if an error occurs reading the archive + * @param domainHome the domain home directory + * @return the full path to the directory containing the extracted wallet files or null, if no wallet was found. + * @throws WLSDeployArchiveIOException if an error occurs while reading or extracting the archive files. */ - public String getOPSSWallet() throws WLSDeployArchiveIOException { - final String METHOD = "getOPSSWallet"; + public String extractOPSSWallet(File domainHome) throws WLSDeployArchiveIOException { + final String METHOD = "extractOPSSWallet"; - LOGGER.entering(CLASS, METHOD); - List result = getZipFile().listZipEntries(ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); - result.remove(ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); - LOGGER.exiting(CLASS, METHOD, result); - if (result.isEmpty()) { - return null; + LOGGER.entering(CLASS, METHOD, domainHome); + validateExistingDirectory(domainHome, "domainHome", getArchiveFileName(), METHOD); + + // Look in the updated location first + String extractPath = null; + List zipEntries = getZipFile().listZipEntries(ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); + zipEntries.remove(ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); + if (!zipEntries.isEmpty()) { + extractPath = ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP; + extractWallet(domainHome, extractPath, zipEntries, null); + extractPath = new File(domainHome, extractPath).getAbsolutePath(); } else { - return result.get(0); + // Look in the deprecated location. + zipEntries = getZipFile().listZipEntries(OLD_ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); + zipEntries.remove(OLD_ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP); + if (!zipEntries.isEmpty()) { + extractPath = OLD_ARCHIVE_OPSS_WALLET_PATH + ZIP_SEP; + extractWallet(domainHome, extractPath, zipEntries, "WLSDPLY-01433"); + extractPath = new File(domainHome, extractPath).getAbsolutePath(); + } } + + LOGGER.exiting(CLASS, METHOD, extractPath); + return extractPath; } /** @@ -736,6 +768,7 @@ public void extractApplication(String applicationPath, File domainHome) throws W /** * Get the best guess of the name of the shared library as if it is in the archive file. * This does not reconcile duplicate names and other items that require the archive file. + * * @param shlibPath file name to find the name for * @return name for model archive file name */ @@ -809,6 +842,7 @@ public void extractSharedLibrary(String sharedLibraryPath, File domainHome) thro /** * Get the archive file name for the Domain library file. This does not reconcile duplicate names or other * items that require the archive file. + * * @param domainLibPath the file name to get the archive file name * @return model ready archive file name */ @@ -954,6 +988,7 @@ public void removeDomainBinScripts() throws WLSDeployArchiveIOException { /** * Get the archive path for the classpath library for use in the model. + * * @param libPath to get the archive path for * @return Archive path for the classpath library for use in the model */ @@ -1055,6 +1090,7 @@ public void extractCustomFiles(File domainHome) throws WLSDeployArchiveIOExcepti /** * Get the archive path of the application deployment plan. + * * @param planFile The deployment plan file name * @return Archive path for use in the model */ @@ -1099,6 +1135,7 @@ public String addApplicationDeploymentPlan(String planFile, String preferredName /** * Get the Archive Path for the Shared Library Plan + * * @param planFile Shared Library Deployment Plan file name * @return Archive path for the plan file for use in the model */ @@ -1132,6 +1169,7 @@ public String addSharedLibraryDeploymentPlan(String planFile, String preferredNa /** * Get the archive path for the scriptfile name. + * * @param scriptFile the script file to get the path name * @return The name of the file in the archive for use in the model */ @@ -1161,7 +1199,8 @@ public String addScript(String scriptFile) throws WLSDeployArchiveIOException { /** * Get the archive path for the servr identity key store file for use in the model - * @param serverName name of the server used to separate paths + * + * @param serverName name of the server used to separate paths * @param keystoreFile the file to get the archive path name * @return Archive path name for the server key store file */ @@ -1225,7 +1264,7 @@ public String addMimeMappingFile(String mimeMappingFile) throws WLSDeployArchive * Get the Coherence configuration file name in the archive to use in the model. * * @param clusterName The Coherence cluster name used to segregate the directories - * @param configFile the file name of the config file + * @param configFile the file name of the config file * @return Archive name for use in the model */ public String getCoherenceConfigArchivePath(String clusterName, String configFile) { @@ -1256,8 +1295,9 @@ public String addCoherenceConfigFile(String clusterName, String configFile) thro /** * Get the archive name for the foreign server binding file. + * * @param foreignServer The foreign server name used to segregate the directories - * @param configFile The file name to add + * @param configFile The file name to add * @return The location of the file in the archive to use in the model */ public String getForeignServerArchivePath(String foreignServer, String configFile) { @@ -1268,7 +1308,7 @@ public String getForeignServerArchivePath(String foreignServer, String configFil * Add a Foreign Server binding file to the archive * * @param foreignServer the Foreign Server name used to segregate the directories - * @param configFile the file or directory to add + * @param configFile the file or directory to add * @return the new location of the file to use in the model * @throws WLSDeployArchiveIOException if an error occurs while archiving the file * @throws IllegalArgumentException if the file does not exist or the foreignServer is empty or null @@ -1287,7 +1327,7 @@ public String addForeignServerFile(String foreignServer, String configFile) thro public String getCoherenceURLArchivePath(String clusterName, URL urlForConfigFile) { return getURLArchiveName(ARCHIVE_COHERENCE_TARGET_DIR + ZIP_SEP + clusterName, urlForConfigFile, - true); + true); } /** @@ -1307,7 +1347,7 @@ public String addCoherenceConfigFileFromUrl(String clusterName, URL urlForConfig validateNonEmptyString(clusterName, "clusterName", METHOD); validateNonNullObject(urlForConfigFile, "urlForConfigFile", METHOD); String newName = addUrlToZip(ARCHIVE_COHERENCE_TARGET_DIR + ZIP_SEP + clusterName, urlForConfigFile, - COHERENCE_CONFIG_FILE_EXTENSION, true); + COHERENCE_CONFIG_FILE_EXTENSION, true); LOGGER.exiting(CLASS, METHOD, newName); return newName; } @@ -1315,11 +1355,12 @@ public String addCoherenceConfigFileFromUrl(String clusterName, URL urlForConfig /** * Get the name of the persistence directory as an archive path. This does not reconcile duplicates or other * items deeper in the zip file logic. - * @param clusterName name of cluster specific to path + * + * @param clusterName name of cluster specific to path * @param directoryType type of persistence directory * @return Archive style path for directory */ - public String getCoherencePersistArchivePath(String clusterName, String directoryType){ + public String getCoherencePersistArchivePath(String clusterName, String directoryType) { return getArchiveName(ARCHIVE_COHERENCE_TARGET_DIR + ZIP_SEP + clusterName, directoryType); } @@ -1369,6 +1410,7 @@ public String addFileStoreDirectory(String fileStoreName) throws WLSDeployArchiv /** * Get the archive path to Node Manager Identity Key Store file. This does not reconcile duplicate names or * other items that the archive file does when adding to the archive. + * * @param keystoreFile file name of the key store file * @return archive file path for the model */ @@ -1398,20 +1440,21 @@ public String addNodeManagerKeyStoreFile(String keystoreFile) throws WLSDeployAr /** * Return the manifest for the specified path in the archive, if present. * The path may refer to a packaged EAR/JAR/WAR, or an exploded entry. + * * @param sourcePath the path to be checked * @return the Manifest object, or null * @throws WLSDeployArchiveIOException if there is a problem reading the archive, or the manifest */ public Manifest getManifest(String sourcePath) throws WLSDeployArchiveIOException { try { - if(containsFile(sourcePath)) { + if (containsFile(sourcePath)) { // a jarred app or library in the archive. - try(ZipInputStream zipStream = new ZipInputStream(getZipFile().getZipEntry(sourcePath))) { + try (ZipInputStream zipStream = new ZipInputStream(getZipFile().getZipEntry(sourcePath))) { // JarInputStream.getManifest() has problems if MANIFEST.MF is not the first entry, // so use ZipInputStream and search for the specific entry. ZipEntry zipEntry; - while((zipEntry = zipStream.getNextEntry()) != null) { - if(JarFile.MANIFEST_NAME.equals(zipEntry.getName())) { + while ((zipEntry = zipStream.getNextEntry()) != null) { + if (JarFile.MANIFEST_NAME.equals(zipEntry.getName())) { Manifest manifest = new Manifest(zipStream); zipStream.closeEntry(); return manifest; @@ -1419,7 +1462,7 @@ public Manifest getManifest(String sourcePath) throws WLSDeployArchiveIOExceptio zipStream.closeEntry(); } } - } else if(containsPath(sourcePath)) { + } else if (containsPath(sourcePath)) { // an exploded app or library in the archive. String manifestPath = sourcePath + "/" + JarFile.MANIFEST_NAME; if (containsFile(manifestPath)) { @@ -1428,9 +1471,9 @@ public Manifest getManifest(String sourcePath) throws WLSDeployArchiveIOExceptio } } } - } catch(IOException e) { + } catch (IOException e) { WLSDeployArchiveIOException aioe = new WLSDeployArchiveIOException("WLSDPLY-01426", sourcePath, - getArchiveFileName(), e.getLocalizedMessage()); + getArchiveFileName(), e.getLocalizedMessage()); LOGGER.throwing(aioe); throw aioe; } @@ -1498,6 +1541,7 @@ protected String getArchiveName(String zipPathPrefix, String itemToAdd, boolean } return newName; } + protected String addItemToZip(String zipPathPrefix, File itemToAdd) throws WLSDeployArchiveIOException { return addItemToZip(zipPathPrefix, itemToAdd, true); } @@ -1579,7 +1623,7 @@ protected String addUrlToZip(String zipPathPrefix, URL url, String extension, bo newName = addSingleFileToZip(tmpFile, newName, METHOD); } catch (IOException ioe) { WLSDeployArchiveIOException aioe = - new WLSDeployArchiveIOException("WLSDPLY-01410", ioe, url, ioe.getLocalizedMessage()); + new WLSDeployArchiveIOException("WLSDPLY-01410", ioe, url, ioe.getLocalizedMessage()); LOGGER.throwing(aioe); throw aioe; } catch (SecurityException se) { @@ -1613,6 +1657,98 @@ protected String addUrlToZip(String zipPathPrefix, URL url, String extension, bo return newName; } + protected void extractWallet(File domainHome, String extractPath, List zipEntries, String deprecationKey) + throws WLSDeployArchiveIOException { + final String METHOD = "extractWallet"; + LOGGER.entering(CLASS, METHOD, domainHome, extractPath, zipEntries, deprecationKey); + + File fullExtractPath = new File(domainHome, extractPath); + if (zipEntries != null && !zipEntries.isEmpty()) { + String firstZipEntry = zipEntries.get(0); + if (!fullExtractPath.exists() && !fullExtractPath.mkdirs()) { + WLSDeployArchiveIOException ex = new WLSDeployArchiveIOException("WLSDPLY-01430", firstZipEntry, + getArchiveFileName(), fullExtractPath.getAbsolutePath()); + LOGGER.throwing(CLASS, METHOD, ex); + throw ex; + } + + // The archive file wallet directory can either contain a single zip file containing the wallet files + // or one or more wallet files. Before starting to iterate, check for the single zip file case. + // + if (zipEntries.size() == 1 && firstZipEntry.toLowerCase().endsWith(".zip")) { + if (!StringUtils.isEmpty(deprecationKey)) { + LOGGER.warning(deprecationKey, getArchiveFileName(), firstZipEntry, extractPath); + } + unzipZippedArchiveFileEntry(firstZipEntry, fullExtractPath); + } else { + for (String zipEntry : zipEntries) { + checkForZipSlip(domainHome, zipEntry); + File extractToLocation = domainHome; + if (!StringUtils.isEmpty(deprecationKey)) { + extractToLocation = new File(domainHome, WLSDPLY_ARCHIVE_BINARY_DIR); + LOGGER.warning(deprecationKey, getArchiveFileName(), zipEntry, extractPath); + } + extractFileFromZip(zipEntry, extractToLocation); + } + } + } + LOGGER.exiting(CLASS, METHOD); + } + + protected void unzipZippedArchiveFileEntry(String zippedItemToExtract, File extractToLocation) + throws WLSDeployArchiveIOException { + final String METHOD = "unzipZippedArchiveFileEntry"; + LOGGER.entering(CLASS, METHOD, zippedItemToExtract, extractToLocation); + + File tempDir; + try { + tempDir = Files.createTempDirectory("tempzip").toFile(); + tempDir.deleteOnExit(); + } catch (IOException ioe) { + WLSDeployArchiveIOException ex = new WLSDeployArchiveIOException("WLSDPLY-01428", ioe, zippedItemToExtract, + ioe.getLocalizedMessage()); + LOGGER.throwing(CLASS, METHOD, ex); + throw ex; + } + + String zippedEntryPath = extractFile(zippedItemToExtract, tempDir); + + try (FileInputStream fis = new FileInputStream(zippedEntryPath); + ZipInputStream zis = new ZipInputStream(fis)) { + + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + String zipEntryFileName = ze.getName(); + checkForZipSlip(extractToLocation, zipEntryFileName); + + File zipEntryFile = new File(extractToLocation, ze.getName()); + if (!zipEntryFile.getParentFile().exists() && !zipEntryFile.getParentFile().mkdirs()) { + WLSDeployArchiveIOException ex = new WLSDeployArchiveIOException("WLSDPLY-01429", zipEntryFileName, + extractToLocation.getAbsolutePath()); + LOGGER.throwing(CLASS, METHOD, ex); + throw ex; + } + + try (FileOutputStream fos = new FileOutputStream(zipEntryFile)) { + byte[] buffer = new byte[4096]; + int len = zis.read(buffer); + while (len > 0) { + fos.write(buffer, 0, len); + len = zis.read(buffer); + } + } + zis.closeEntry(); + ze = zis.getNextEntry(); + } + } catch (IOException ioe) { + WLSDeployArchiveIOException ex = new WLSDeployArchiveIOException("WLSDPLY-01432", ioe, zippedEntryPath, + zippedItemToExtract, extractToLocation, ioe.getLocalizedMessage()); + LOGGER.throwing(CLASS, METHOD, ex); + throw ex; + } + LOGGER.exiting(CLASS, METHOD); + } + protected void extractDirectoryFromZip(String directoryName, File extractToLocation) throws WLSDeployArchiveIOException { extractDirectoryFromZip(directoryName, directoryName, extractToLocation); @@ -1697,6 +1833,11 @@ protected void extractFileFromZip(String itemToExtract, String fromDir, String t if (!targetDirectory.exists() && !targetDirectory.mkdirs()) { WLSDeployArchiveIOException wdaioe = new WLSDeployArchiveIOException("WLSDPLY-01414", getArchiveFileName(), targetDirectory.getAbsolutePath()); + try { + inputStream.close(); + } catch (IOException ignore) { + // best effort + } LOGGER.throwing(CLASS, METHOD, wdaioe); throw wdaioe; } @@ -1788,6 +1929,29 @@ private String addSingleFileToZip(File itemToAdd, String preferredName, String c return newName; } + private String walkDownFolders(String zipPrefix, File zipPath) throws WLSDeployArchiveIOException { + String newSourceName = null; + if (zipPath != null) { + File[] fileList = zipPath.listFiles(); + if (fileList != null) { + for (File item : fileList) { + newSourceName = addItemToZip(zipPrefix, item); + } + } + } + return newSourceName; + } + + private void checkForZipSlip(File extractLocation, String zipEntry) throws WLSDeployArchiveIOException { + String canonicalExtractLocation = FileUtils.getCanonicalPath(extractLocation); + String canonicalZipEntry = FileUtils.getCanonicalPath(new File(extractLocation, zipEntry)); + + if (!canonicalZipEntry.startsWith(canonicalExtractLocation)) { + throw new WLSDeployArchiveIOException("WLSDPLY-01431", getArchiveFileName(), zipEntry, canonicalZipEntry, + canonicalExtractLocation); + } + } + /////////////////////////////////////////////////////////////////////////// // Private Static Helper Methods // /////////////////////////////////////////////////////////////////////////// @@ -1884,18 +2048,4 @@ private static FileInputStream getFileInputStream(File f, String itemName, Strin } return inputStream; } - - private String walkDownFolders(String zipPrefix, File zipPath) throws WLSDeployArchiveIOException { - String newSourceName = null; - if (zipPath != null) { - File[] fileList = zipPath.listFiles(); - if (fileList != null) { - for (File item : fileList) { - newSourceName = addItemToZip(zipPrefix, item); - } - } - } - return newSourceName; - } - } diff --git a/core/src/main/python/discover.py b/core/src/main/python/discover.py index 26c24f19a..3de132213 100644 --- a/core/src/main/python/discover.py +++ b/core/src/main/python/discover.py @@ -140,7 +140,6 @@ def __process_archive_filename_arg(argument_map): _method_name = '__process_archive_filename_arg' if CommandLineArgUtil.SKIP_ARCHIVE_FILE_SWITCH in argument_map or CommandLineArgUtil.REMOTE_SWITCH in argument_map: - archive_file = WLSDeployArchive.noArchiveFile() if CommandLineArgUtil.ARCHIVE_FILE_SWITCH in argument_map: ex = exception_helper.create_cla_exception(ExitCode.ARG_VALIDATION_ERROR, 'WLSDPLY-06033') @@ -162,8 +161,7 @@ def __process_archive_filename_arg(argument_map): ie.getLocalizedMessage(), error=ie) __logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex - argument_map[CommandLineArgUtil.ARCHIVE_FILE] = archive_file - + argument_map[CommandLineArgUtil.ARCHIVE_FILE] = archive_file def __process_variable_filename_arg(optional_arg_map): @@ -352,16 +350,16 @@ def __clear_archive_file(model_context): archive_file = model_context.get_archive_file() - if archive_file is None: - de = exception_helper.create_discover_exception('WLSDPLY-06004', model_context.get_archive_file_name()) - __logger.throwing(class_name=_class_name, method_name=_method_name, error=de) - raise de - if not model_context.skip_archive() and not model_context.is_remote(): - try: - archive_file.removeAllBinaries() - except WLSDeployArchiveIOException, wioe: - de = exception_helper.create_discover_exception('WLSDPLY-06005', wioe.getLocalizedMessage()) + if archive_file is not None: + try: + archive_file.removeAllBinaries() + except WLSDeployArchiveIOException, wioe: + de = exception_helper.create_discover_exception('WLSDPLY-06005', wioe.getLocalizedMessage()) + __logger.throwing(class_name=_class_name, method_name=_method_name, error=de) + raise de + else: + de = exception_helper.create_discover_exception('WLSDPLY-06004', model_context.get_archive_file_name()) __logger.throwing(class_name=_class_name, method_name=_method_name, error=de) raise de @@ -377,7 +375,8 @@ def __close_archive(model_context): __logger.entering(_class_name=_class_name, method_name=_method_name) archive_file = model_context.get_archive_file() - archive_file.close() + if archive_file is not None: + archive_file.close() __logger.exiting(class_name=_class_name, method_name=_method_name) diff --git a/core/src/main/python/wlsdeploy/tool/util/archive_helper.py b/core/src/main/python/wlsdeploy/tool/util/archive_helper.py index 196c212c2..6af2f1744 100644 --- a/core/src/main/python/wlsdeploy/tool/util/archive_helper.py +++ b/core/src/main/python/wlsdeploy/tool/util/archive_helper.py @@ -414,12 +414,8 @@ def extract_atp_wallet(self): wallet_path = None for archive_file in self.__archive_files[::-1]: - atp_wallet_zipentry = archive_file.getATPWallet() - if atp_wallet_zipentry: - wallet_dir = File(self.__domain_home, 'atpwallet') - wallet_dir.mkdirs() - wallet_path = wallet_dir.getPath() - FileUtils.extractZipFileContent(archive_file, atp_wallet_zipentry, wallet_path) + wallet_path = archive_file.extractATPWallet(self.__domain_home) + if wallet_path is not None: break self.__logger.exiting(class_name=self.__class_name, method_name=_method_name, result=wallet_path) @@ -436,12 +432,8 @@ def extract_opss_wallet(self): wallet_path = None for archive_file in self.__archive_files[::-1]: - atp_wallet_zipentry = archive_file.getOPSSWallet() - if atp_wallet_zipentry: - wallet_dir = File(self.__domain_home, 'opsswallet') - wallet_dir.mkdirs() - wallet_path = wallet_dir.getPath() - FileUtils.extractZipFileContent(archive_file, atp_wallet_zipentry, wallet_path) + wallet_path = archive_file.extractOPSSWallet(self.__domain_home) + if wallet_path is not None: break self.__logger.exiting(class_name=self.__class_name, method_name=_method_name, result=wallet_path) diff --git a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties index a8f71f417..6b1756102 100644 --- a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties +++ b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties @@ -200,6 +200,13 @@ WLSDPLY-01423=WLSDeployArchive {0} unable to add/extract binaries because the di WLSDPLY-01424=WLSDeployArchive {0} unable to add/extract binaries because the directory {1} is not a directory WLSDPLY-01425=Failed to add entry {2} for file {1} to zip file {0}: {3} WLSDPLY-01426=Unable to open the manifest for path {0} in archive file {1}: {2} +WLSDPLY-01427=Archive file {0} contains the ATP wallet in a deprecated location {1}. Please move to the new location {2}. +WLSDPLY-01428=Failed to extract archive file entry {0} due to an error creating a temporary directory: {1} +WLSDPLY-01429=Unable to extract zip entry {0} because the target directory {1} does not exist and could not be created +WLSDPLY-01430=Failed to extract wallet file {0} from archive file {1} because the target directory {2} does not exist and could not be created +WLSDPLY-01431=Zip slip security vulnerability detected in archive file {0} entry {1} because entry extract location {2} is not under the specified extract path {3} +WLSDPLY-01432=Failed to extract zip file {0} originating from archive file entry {1} to directory {2}: {3} +WLSDPLY-01433=Archive file {0} contains the OPSS wallet in a deprecated location {1}. Please move to the new location {2}. # oracle.weblogic.deploy.util.WLSDeployZipFile.java WLSDPLY-01500=The zip file {0} has the saved entry {1} diff --git a/core/src/test/java/oracle/weblogic/deploy/util/FileUtilsTest.java b/core/src/test/java/oracle/weblogic/deploy/util/FileUtilsTest.java index 69818d7a8..0c0555ec3 100644 --- a/core/src/test/java/oracle/weblogic/deploy/util/FileUtilsTest.java +++ b/core/src/test/java/oracle/weblogic/deploy/util/FileUtilsTest.java @@ -4,21 +4,15 @@ */ package oracle.weblogic.deploy.util; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.nio.file.attribute.PosixFilePermission; import java.text.MessageFormat; import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.function.Executable; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class FileUtilsTest { @@ -125,58 +119,6 @@ void testHashing() throws Exception { assertEquals(appHash, archiveHash); } - @Test - /* A wallet zip inside the archive must not contain an entry such as ../info.txt, - since this creates a file overwrite security vulnerability (zip slip). - */ - void testZipVulnerability() throws Exception { - final String extractPath = UNIT_TEST_TARGET_DIR.getPath(); - - // an entry with a simple name or path works fine - File zipFile = buildWalletArchiveZip("info.txt"); - WLSDeployArchive deployArchive = new WLSDeployArchive(zipFile.getPath()); - FileUtils.extractZipFileContent(deployArchive, WALLET_PATH, extractPath); - - // an entry with parent directory notation should throw an exception - zipFile = buildWalletArchiveZip("../info.txt"); - final WLSDeployArchive deployArchive2 = new WLSDeployArchive(zipFile.getPath()); - assertThrows(IllegalArgumentException.class, - new Executable() { - @Override - public void execute() throws Throwable { - FileUtils.extractZipFileContent(deployArchive2, WALLET_PATH, extractPath); - } - }, - "Exception not thrown for zip entry outside extract directory"); - } - - /* Build an archive zip containing a wallet zip. - The wallet contains a single entry with the name of the contentName argument. - */ - private File buildWalletArchiveZip(String contentName) throws Exception { - - // create the wallet zip content - ByteArrayOutputStream walletBytes = new ByteArrayOutputStream(); - try (ZipOutputStream zipStream = new ZipOutputStream(walletBytes)) { - ZipEntry zipEntry = new ZipEntry(contentName); - zipStream.putNextEntry(zipEntry); - byte[] data = "info".getBytes(); - zipStream.write(data, 0, data.length); - zipStream.closeEntry(); - } - - File archiveFile = new File(UNIT_TEST_TARGET_DIR, "archive.zip"); - - try (ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream(archiveFile))) { - ZipEntry zipEntry = new ZipEntry(WALLET_PATH); - zipStream.putNextEntry(zipEntry); - zipStream.write(walletBytes.toByteArray()); - zipStream.closeEntry(); - } - - return archiveFile; - } - private void assertMatch(String name, String got, String expected) { assertEquals(expected, got, MessageFormat.format(FILE_ERR_FORMAT, name, got, expected)); } diff --git a/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java b/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java index 7a0549469..0d3437563 100644 --- a/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java +++ b/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java @@ -5,14 +5,19 @@ package oracle.weblogic.deploy.util; import java.io.File; +import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static oracle.weblogic.deploy.util.WLSDeployArchive.ARCHIVE_ATP_WALLET_PATH; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class WLSDeployArchiveTest { @@ -39,6 +44,27 @@ public class WLSDeployArchiveTest { private static final String BINARIES_MODEL_ZIP_TARGET_NAME = WLSDeployZipFileTest.UNIT_TEST_TARGET_DIR + '/' + ZIP_FILE_EXISTING_BINARIES_FILE; + private static final String ATP_EMPTY_ARCHIVE = "src/test/resources/atp-empty-archive.zip"; + private static final String ATP_EXPANDED_ARCHIVE = "src/test/resources/atp-expanded-archive.zip"; + private static final String ATP_ZIPPED_ARCHIVE = "src/test/resources/atp-zipped-archive.zip"; + + private static final String ATP_DEPRECATED_EMPTY_ARCHIVE = "src/test/resources/atp-deprecated-empty-archive.zip"; + private static final String ATP_DEPRECATED_EXPANDED_ARCHIVE = + "src/test/resources/atp-deprecated-expanded-archive.zip"; + private static final String ATP_DEPRECATED_ZIPPED_ARCHIVE = "src/test/resources/atp-deprecated-zipped-archive.zip"; + + private static final List ATP_EXPECTED_CONTENT = Arrays.asList( + ARCHIVE_ATP_WALLET_PATH + "/cwallet.sso", + ARCHIVE_ATP_WALLET_PATH + "/ewallet.p12", + ARCHIVE_ATP_WALLET_PATH + "/ewallet.pem", + ARCHIVE_ATP_WALLET_PATH + "/keystore.jks", + ARCHIVE_ATP_WALLET_PATH + "/ojdbc.properties", + ARCHIVE_ATP_WALLET_PATH + "/README", + ARCHIVE_ATP_WALLET_PATH + "/sqlnet.ora", + ARCHIVE_ATP_WALLET_PATH + "/tnsnames.ora", + ARCHIVE_ATP_WALLET_PATH + "/truststore.jks" + ); + @BeforeAll static void setup() throws Exception { File unitTestDir = new File(WLSDeployZipFileTest.UNIT_TEST_TARGET_DIR).getCanonicalFile(); @@ -137,4 +163,116 @@ void testClearAllBinariesWithEmptyZip() throws Exception { assertFalse(StringUtils.isEmpty(appName), "expected appName to be not empty"); archive.close(); } + + @Test + void testATPZippedWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_ZIPPED_ARCHIVE); + File domainHome = new File("target/unit-tests/atp-zipped"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertEquals(atpWalletDir.getAbsolutePath(), path, "expected extractATPWallet to return correct path"); + assertTrue(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to exist"); + assertTrue(atpWalletDir.isDirectory(), "expected " + ARCHIVE_ATP_WALLET_PATH + " to be a directory"); + + for (String atpExpectedFile : ATP_EXPECTED_CONTENT) { + File walletFile = new File(domainHome, atpExpectedFile); + assertTrue(walletFile.exists(), "expected " + atpExpectedFile + " to exist"); + } + } + + @Test + void testATPExpandedWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_EXPANDED_ARCHIVE); + File domainHome = new File("target/unit-tests/atp-unzipped"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertEquals(atpWalletDir.getAbsolutePath(), path, "expected extractATPWallet to return correct path"); + assertTrue(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to exist"); + assertTrue(atpWalletDir.isDirectory(), "expected " + ARCHIVE_ATP_WALLET_PATH + " to be a directory"); + + for (String atpExpectedFile : ATP_EXPECTED_CONTENT) { + File walletFile = new File(domainHome, atpExpectedFile); + assertTrue(walletFile.exists(), "expected " + atpExpectedFile + " to exist"); + } + } + + @Test + void testATPEmptyWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_EMPTY_ARCHIVE); + File domainHome = new File("target/unit-tests/atp-empty"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + assertNull(path, "expected extractATPWallet to return null"); + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertFalse(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to not exist"); + } + + @Test + void testDeprecatedATPZippedWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_DEPRECATED_ZIPPED_ARCHIVE); + File domainHome = new File("target/unit-tests/deprecated-atp-zipped"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertEquals(atpWalletDir.getAbsolutePath(), path, "expected extractATPWallet to return correct path"); + assertTrue(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to exist"); + assertTrue(atpWalletDir.isDirectory(), "expected " + ARCHIVE_ATP_WALLET_PATH + " to be a directory"); + + for (String atpExpectedFile : ATP_EXPECTED_CONTENT) { + File walletFile = new File(domainHome, atpExpectedFile); + assertTrue(walletFile.exists(), "expected " + atpExpectedFile + " to exist"); + } + } + + @Test + void testDeprecatedATPExpandedWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_DEPRECATED_EXPANDED_ARCHIVE); + File domainHome = new File("target/unit-tests/deprecated-atp-unzipped"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertEquals(atpWalletDir.getAbsolutePath(), path, "expected extractATPWallet to return correct path"); + assertTrue(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to exist"); + assertTrue(atpWalletDir.isDirectory(), "expected " + ARCHIVE_ATP_WALLET_PATH + " to be a directory"); + + for (String atpExpectedFile : ATP_EXPECTED_CONTENT) { + File walletFile = new File(domainHome, atpExpectedFile); + assertTrue(walletFile.exists(), "expected " + atpExpectedFile + " to exist"); + } + } + + @Test + void testDeprecatedATPEmptyWalletExtract() throws Exception { + WLSDeployArchive archive = new WLSDeployArchive(ATP_DEPRECATED_EMPTY_ARCHIVE); + File domainHome = new File("target/unit-tests/deprecated-atp-empty"); + if (!domainHome.exists() && !domainHome.mkdirs()) { + fail("Failed to create test domain home directory " + domainHome.getAbsolutePath()); + } + + String path = archive.extractATPWallet(domainHome); + assertNull(path, "expected extractATPWallet to return null"); + File atpWalletDir = new File(domainHome, ARCHIVE_ATP_WALLET_PATH).getCanonicalFile(); + assertFalse(atpWalletDir.exists(), "expected " + ARCHIVE_ATP_WALLET_PATH + " directory to not exist"); + } } diff --git a/core/src/test/resources/atp-deprecated-empty-archive.zip b/core/src/test/resources/atp-deprecated-empty-archive.zip new file mode 100644 index 0000000000000000000000000000000000000000..a3d877294ec301946f0555884720c3a7590057a8 GIT binary patch literal 170 zcmWIWW@h1H0D-y5Gef})D8a=b!;n}~P@b5RlUkx58p6rIoHcDlaxoB>R&X;gvV3J^ wU|>^#l%; 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 P`QC?xg3>bl>)-zaK68^Q literal 0 HcmV?d00001 diff --git a/core/src/test/resources/atp-zipped-archive.zip b/core/src/test/resources/atp-zipped-archive.zip new file mode 100644 index 0000000000000000000000000000000000000000..966bd5fde1b63b546d58633c6bd4934444614b3a GIT binary patch literal 25803 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 literal 0 HcmV?d00001 From be84f8cb152a2ca43c98471614485274e99e9be9 Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Sun, 25 Dec 2022 15:12:11 -0600 Subject: [PATCH 2/3] cleanup and tightening zip slip detection --- .../weblogic/deploy/util/WLSDeployArchive.java | 12 ++++++++---- .../weblogic/deploy/util/WLSDeployArchiveTest.java | 6 ++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java b/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java index 8ddcb7873..b2e4ef571 100644 --- a/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java +++ b/core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java @@ -13,7 +13,6 @@ import java.net.URL; import java.nio.file.Files; import java.security.NoSuchAlgorithmException; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.jar.JarFile; @@ -1682,7 +1681,6 @@ protected void extractWallet(File domainHome, String extractPath, List z unzipZippedArchiveFileEntry(firstZipEntry, fullExtractPath); } else { for (String zipEntry : zipEntries) { - checkForZipSlip(domainHome, zipEntry); File extractToLocation = domainHome; if (!StringUtils.isEmpty(deprecationKey)) { extractToLocation = new File(domainHome, WLSDPLY_ARCHIVE_BINARY_DIR); @@ -1729,7 +1727,7 @@ protected void unzipZippedArchiveFileEntry(String zippedItemToExtract, File extr throw ex; } - try (FileOutputStream fos = new FileOutputStream(zipEntryFile)) { + try (FileOutputStream fos = new FileOutputStream(zipEntryFile, false)) { byte[] buffer = new byte[4096]; int len = zis.read(buffer); while (len > 0) { @@ -1771,6 +1769,7 @@ protected void extractDirectoryFromZip(String fromDirectoryName, String toDirect for (Map.Entry zipEntry : zipEntries.entrySet()) { String entryName = zipEntry.getKey(); String targetFileName = entryName.replace(fromDirectoryName + ZIP_SEP, toDirectoryName + SEP); + checkForZipSlip(extractToLocation, targetFileName); targetFile = new File(extractToLocation, targetFileName); File targetDirectory; if (entryName.endsWith(ZIP_SEP)) { @@ -1819,6 +1818,12 @@ protected void extractFileFromZip(String itemToExtract, String fromDir, String t final String METHOD = "extractFileFromZip"; LOGGER.entering(CLASS, METHOD, itemToExtract, fromDir, toDir, extractToLocation); + String targetFileName = itemToExtract; + if (fromDir != null && toDir != null) { + targetFileName = itemToExtract.replace(fromDir + ZIP_SEP, toDir + SEP); + } + checkForZipSlip(extractToLocation, targetFileName); + InputStream inputStream = getZipFile().getZipEntry(itemToExtract); if (inputStream == null) { WLSDeployArchiveIOException wdaioe = @@ -1827,7 +1832,6 @@ protected void extractFileFromZip(String itemToExtract, String fromDir, String t throw wdaioe; } - String targetFileName = itemToExtract.replace(fromDir + ZIP_SEP, toDir + SEP); File targetFile = new File(extractToLocation, targetFileName); File targetDirectory = targetFile.getParentFile(); if (!targetDirectory.exists() && !targetDirectory.mkdirs()) { diff --git a/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java b/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java index 0d3437563..60cb94a4b 100644 --- a/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java +++ b/core/src/test/java/oracle/weblogic/deploy/util/WLSDeployArchiveTest.java @@ -7,7 +7,10 @@ import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.logging.Level; +import oracle.weblogic.deploy.logging.PlatformLogger; +import oracle.weblogic.deploy.logging.WLSDeployLogFactory; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -74,6 +77,9 @@ static void setup() throws Exception { if (appsArchiveFile.exists()) { appsArchiveFile.delete(); } + + PlatformLogger logger = WLSDeployLogFactory.getLogger("wlsdeploy.archive"); + logger.setLevel(Level.OFF); } @Test From ae96063f5836c60a76b43114137ccc6e5efb7d96 Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Sun, 25 Dec 2022 15:52:29 -0600 Subject: [PATCH 3/3] removing unused imports --- core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java b/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java index bfa9427fd..9b0b12da1 100644 --- a/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java +++ b/core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java @@ -8,7 +8,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; @@ -24,8 +23,6 @@ import java.util.List; import java.util.Locale; import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import javax.xml.bind.DatatypeConverter; import oracle.weblogic.deploy.exception.ExceptionHelper;