Use Files.createTempFile(...) to ensure the file is created with proper permissions

Motivation:

File.createTempFile(String, String)` will create a temporary file in the system temporary directory if the 'java.io.tmpdir'. The permissions on that file utilize the umask. In a majority of cases, this means that the file that java creates has the permissions: `-rw-r--r--`, thus, any other local user on that system can read the contents of that file.
This can be a security concern if any sensitive data is stored in this file.

This was reported by Jonathan Leitschuh <jonathan.leitschuh@gmail.com> as a security problem.

Modifications:

Use Files.createTempFile(...) which will use safe-defaults when running on java 7 and later. If running on java 6 there isnt much we can do, which is fair enough as java 6 shouldnt be considered "safe" anyway.

Result:

Create temporary files with sane permissions by default.
This commit is contained in:
Norman Maurer 2021-02-08 11:44:05 +01:00
parent 4d3bd06212
commit 9c2de76add
15 changed files with 53 additions and 19 deletions

View File

@ -18,6 +18,7 @@ package io.netty.buffer;
import io.netty.util.ByteProcessor; import io.netty.util.ByteProcessor;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.IllegalReferenceCountException; import io.netty.util.IllegalReferenceCountException;
import io.netty.util.internal.PlatformDependent;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -4534,7 +4535,7 @@ public abstract class AbstractByteBufTest {
@Test @Test
public void testReadBytesAndWriteBytesWithFileChannel() throws IOException { public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
File file = File.createTempFile("file-channel", ".tmp"); File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
RandomAccessFile randomAccessFile = null; RandomAccessFile randomAccessFile = null;
try { try {
randomAccessFile = new RandomAccessFile(file, "rw"); randomAccessFile = new RandomAccessFile(file, "rw");
@ -4573,7 +4574,7 @@ public abstract class AbstractByteBufTest {
@Test @Test
public void testGetBytesAndSetBytesWithFileChannel() throws IOException { public void testGetBytesAndSetBytesWithFileChannel() throws IOException {
File file = File.createTempFile("file-channel", ".tmp"); File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
RandomAccessFile randomAccessFile = null; RandomAccessFile randomAccessFile = null;
try { try {
randomAccessFile = new RandomAccessFile(file, "rw"); randomAccessFile = new RandomAccessFile(file, "rw");

View File

@ -15,6 +15,7 @@
*/ */
package io.netty.buffer; package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -306,7 +307,7 @@ public class ReadOnlyDirectByteBufferBufTest {
@Test @Test
public void testWrapMemoryMapped() throws Exception { public void testWrapMemoryMapped() throws Exception {
File file = File.createTempFile("netty-test", "tmp"); File file = PlatformDependent.createTempFile("netty-test", "tmp", null);
FileChannel output = null; FileChannel output = null;
FileChannel input = null; FileChannel input = null;
ByteBuf b1 = null; ByteBuf b1 = null;

View File

@ -18,6 +18,7 @@ package io.netty.handler.codec.http.multipart;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpConstants; import io.netty.handler.codec.http.HttpConstants;
import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -89,9 +90,9 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData {
File tmpFile; File tmpFile;
if (getBaseDirectory() == null) { if (getBaseDirectory() == null) {
// create a temporary file // create a temporary file
tmpFile = File.createTempFile(getPrefix(), newpostfix); tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, null);
} else { } else {
tmpFile = File.createTempFile(getPrefix(), newpostfix, new File( tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, new File(
getBaseDirectory())); getBaseDirectory()));
} }
if (deleteOnExit()) { if (deleteOnExit()) {

View File

@ -25,6 +25,7 @@ import io.netty.handler.stream.ChunkedNioFile;
import io.netty.handler.stream.ChunkedNioStream; import io.netty.handler.stream.ChunkedNioStream;
import io.netty.handler.stream.ChunkedStream; import io.netty.handler.stream.ChunkedStream;
import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.internal.PlatformDependent;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -46,7 +47,7 @@ public class HttpChunkedInputTest {
FileOutputStream out = null; FileOutputStream out = null;
try { try {
TMP = File.createTempFile("netty-chunk-", ".tmp"); TMP = PlatformDependent.createTempFile("netty-chunk-", ".tmp", null);
TMP.deleteOnExit(); TMP.deleteOnExit();
out = new FileOutputStream(TMP); out = new FileOutputStream(TMP);
out.write(BYTES); out.write(BYTES);

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.http.multipart;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.util.internal.PlatformDependent;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
@ -39,7 +40,7 @@ public class AbstractDiskHttpDataTest {
public void testGetChunk() throws Exception { public void testGetChunk() throws Exception {
TestHttpData test = new TestHttpData("test", UTF_8, 0); TestHttpData test = new TestHttpData("test", UTF_8, 0);
try { try {
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp"); File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tmpFile); FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] bytes = new byte[4096]; byte[] bytes = new byte[4096];

View File

@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.internal.PlatformDependent;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -43,7 +44,7 @@ public class AbstractMemoryHttpDataTest {
public void testSetContentFromFile() throws Exception { public void testSetContentFromFile() throws Exception {
TestHttpData test = new TestHttpData("test", UTF_8, 0); TestHttpData test = new TestHttpData("test", UTF_8, 0);
try { try {
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp"); File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tmpFile); FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] bytes = new byte[4096]; byte[] bytes = new byte[4096];
@ -70,7 +71,7 @@ public class AbstractMemoryHttpDataTest {
public void testRenameTo() throws Exception { public void testRenameTo() throws Exception {
TestHttpData test = new TestHttpData("test", UTF_8, 0); TestHttpData test = new TestHttpData("test", UTF_8, 0);
try { try {
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp"); File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
final int totalByteCount = 4096; final int totalByteCount = 4096;
byte[] bytes = new byte[totalByteCount]; byte[] bytes = new byte[totalByteCount];

View File

@ -21,6 +21,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
@ -272,8 +273,9 @@ public class DiskFileUploadTest {
assertEquals(maxSize, originalFile.length()); assertEquals(maxSize, originalFile.length());
assertEquals(maxSize, f1.length()); assertEquals(maxSize, f1.length());
byte[] bytes = new byte[8]; byte[] bytes = new byte[8];
ThreadLocalRandom.current().nextBytes(bytes); ThreadLocalRandom.current().nextBytes(bytes);
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp"); File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tmpFile); FileOutputStream fos = new FileOutputStream(tmpFile);
try { try {

View File

@ -178,7 +178,7 @@ public final class NativeLibraryLoader {
String prefix = libname.substring(0, index); String prefix = libname.substring(0, index);
String suffix = libname.substring(index); String suffix = libname.substring(index);
tmpFile = File.createTempFile(prefix, suffix, WORKDIR); tmpFile = PlatformDependent.createTempFile(prefix, suffix, WORKDIR);
in = url.openStream(); in = url.openStream();
out = new FileOutputStream(tmpFile); out = new FileOutputStream(tmpFile);

View File

@ -38,6 +38,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.file.Files;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
@ -1288,6 +1289,24 @@ public final class PlatformDependent {
return LINUX_OS_CLASSIFIERS; return LINUX_OS_CLASSIFIERS;
} }
@SuppressJava6Requirement(reason = "Guarded by version check")
public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
if (javaVersion() >= 7) {
if (directory == null) {
return Files.createTempFile(prefix, suffix).toFile();
}
return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
}
if (directory == null) {
return File.createTempFile(prefix, suffix);
}
File file = File.createTempFile(prefix, suffix, directory);
// Try to adjust the perms, if this fails there is not much else we can do...
file.setReadable(false, false);
file.setReadable(true, true);
return file;
}
/** /**
* Adds only those classifier strings to <tt>dest</tt> which are present in <tt>allowed</tt>. * Adds only those classifier strings to <tt>dest</tt> which are present in <tt>allowed</tt>.
* *

View File

@ -20,6 +20,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.base64.Base64;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -29,6 +30,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Files;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -320,7 +322,7 @@ public final class SelfSignedCertificate {
wrappedBuf.release(); wrappedBuf.release();
} }
File keyFile = File.createTempFile("keyutil_" + fqdn + '_', ".key"); File keyFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".key", null);
keyFile.deleteOnExit(); keyFile.deleteOnExit();
OutputStream keyOut = new FileOutputStream(keyFile); OutputStream keyOut = new FileOutputStream(keyFile);
@ -351,7 +353,7 @@ public final class SelfSignedCertificate {
wrappedBuf.release(); wrappedBuf.release();
} }
File certFile = File.createTempFile("keyutil_" + fqdn + '_', ".crt"); File certFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".crt", null);
certFile.deleteOnExit(); certFile.deleteOnExit();
OutputStream certOut = new FileOutputStream(certFile); OutputStream certOut = new FileOutputStream(certFile);

View File

@ -26,6 +26,7 @@ import io.netty.channel.ChannelPromise;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.PlatformDependent;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -55,7 +56,7 @@ public class ChunkedWriteHandlerTest {
FileOutputStream out = null; FileOutputStream out = null;
try { try {
TMP = File.createTempFile("netty-chunk-", ".tmp"); TMP = PlatformDependent.createTempFile("netty-chunk-", ".tmp", null);
TMP.deleteOnExit(); TMP.deleteOnExit();
out = new FileOutputStream(TMP); out = new FileOutputStream(TMP);
out.write(BYTES); out.write(BYTES);

View File

@ -33,6 +33,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -62,7 +63,7 @@ public class FileRegionThrottleTest {
BYTES[i] = (byte) r.nextInt(255); BYTES[i] = (byte) r.nextInt(255);
} }
tmp = File.createTempFile("netty-traffic", ".tmp"); tmp = PlatformDependent.createTempFile("netty-traffic", ".tmp", null);
tmp.deleteOnExit(); tmp.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tmp)) { try (FileOutputStream out = new FileOutputStream(tmp)) {
out.write(BYTES); out.write(BYTES);

View File

@ -26,6 +26,7 @@ import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultFileRegion; import io.netty.channel.DefaultFileRegion;
import io.netty.channel.FileRegion; import io.netty.channel.FileRegion;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.internal.PlatformDependent;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.junit.Test; import org.junit.Test;
@ -101,7 +102,7 @@ public class SocketFileRegionTest extends AbstractSocketTest {
} }
public void testFileRegionCountLargerThenFile(ServerBootstrap sb, Bootstrap cb) throws Throwable { public void testFileRegionCountLargerThenFile(ServerBootstrap sb, Bootstrap cb) throws Throwable {
File file = File.createTempFile("netty-", ".tmp"); File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
file.deleteOnExit(); file.deleteOnExit();
final FileOutputStream out = new FileOutputStream(file); final FileOutputStream out = new FileOutputStream(file);
@ -135,7 +136,7 @@ public class SocketFileRegionTest extends AbstractSocketTest {
cb.option(ChannelOption.AUTO_READ, autoRead); cb.option(ChannelOption.AUTO_READ, autoRead);
final int bufferSize = 1024; final int bufferSize = 1024;
final File file = File.createTempFile("netty-", ".tmp"); final File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
file.deleteOnExit(); file.deleteOnExit();
final FileOutputStream out = new FileOutputStream(file); final FileOutputStream out = new FileOutputStream(file);

View File

@ -17,6 +17,7 @@ package io.netty.channel.unix.tests;
import io.netty.channel.unix.DomainSocketAddress; import io.netty.channel.unix.DomainSocketAddress;
import io.netty.channel.unix.Socket; import io.netty.channel.unix.Socket;
import io.netty.util.internal.PlatformDependent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -26,7 +27,7 @@ public final class UnixTestUtils {
try { try {
File file; File file;
do { do {
file = File.createTempFile("NETTY", "UDS"); file = PlatformDependent.createTempFile("NETTY", "UDS", null);
if (!file.delete()) { if (!file.delete()) {
throw new IOException("failed to delete: " + file); throw new IOException("failed to delete: " + file);
} }

View File

@ -15,6 +15,7 @@
*/ */
package io.netty.channel; package io.netty.channel;
import io.netty.util.internal.PlatformDependent;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -39,7 +40,7 @@ public class DefaultFileRegionTest {
} }
private static File newFile() throws IOException { private static File newFile() throws IOException {
File file = File.createTempFile("netty-", ".tmp"); File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
file.deleteOnExit(); file.deleteOnExit();
final FileOutputStream out = new FileOutputStream(file); final FileOutputStream out = new FileOutputStream(file);