Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,34 @@ protected void addDCValue(Context c, Item i, String schema, Node n)
}
}

/**
* Ensures a file path does not attempt to access files outside the designated parent directory.
*
* @param parentDir The absolute path to the parent directory that should contain the file
* @param fileName The name or path of the file to validate
* @throws IOException If an error occurs while resolving canonical paths, or the file path attempts
* to access a location outside the parent directory
*/
private void validateFilePath(String parentDir, String fileName) throws IOException {
File parent = new File(parentDir);
File file = new File(fileName);

// If the fileName is not an absolute path, we resolve it against the parentDir
if (!file.isAbsolute()) {
file = new File(parent, fileName);
}

String parentCanonicalPath = parent.getCanonicalPath();
String fileCanonicalPath = file.getCanonicalPath();

if (!fileCanonicalPath.startsWith(parentCanonicalPath)) {
log.error("File path outside of canonical root requested: fileCanonicalPath={} does not begin " +
"with parentCanonicalPath={}", fileCanonicalPath, parentCanonicalPath);
throw new IOException("Illegal file path '" + fileName + "' encountered. This references a path " +
"outside of the import package. Please see the system logs for more details.");
}
}

/**
* Read the collections file inside the item directory. If there
* is one and it is not empty return a list of collections in
Expand Down Expand Up @@ -1237,6 +1265,7 @@ protected List<String> processContentsFile(Context c, Item i, String path,
sDescription = sDescription.replaceFirst("description:", "");
}

validateFilePath(path, sFilePath);
registerBitstream(c, i, iAssetstore, sFilePath, sBundle, sDescription);
logInfo("\tRegistering Bitstream: " + sFilePath
+ "\tAssetstore: " + iAssetstore
Expand Down Expand Up @@ -1450,6 +1479,7 @@ protected void processContentFileEntry(Context c, Item i, String path,
return;
}

validateFilePath(path, fileName);
String fullpath = path + File.separatorChar + fileName;

// get an input stream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
Expand Down Expand Up @@ -248,7 +249,15 @@ protected File getFile(Bitstream bitstream) throws IOException {
log.debug("Local filename for " + sInternalId + " is "
+ bufFilename.toString());
}
return new File(bufFilename.toString());
File bitstreamFile = new File(bufFilename.toString());
Path normalizedPath = bitstreamFile.toPath().normalize();
if (!normalizedPath.startsWith(baseDir.getAbsolutePath())) {
log.error("Bitstream path outside of assetstore root requested:" +
"bitstream={}, path={}, assetstore={}",
bitstream.getID(), normalizedPath, baseDir.getAbsolutePath());
throw new IOException("Illegal bitstream path constructed");
}
return bitstreamFile;
}

public boolean isRegisteredBitstream(String internalId) {
Expand Down
Loading