From fefaea49d77508e2329688bb1e9080583d4ccbd5 Mon Sep 17 00:00:00 2001 From: mohammed arib Date: Mon, 6 Jul 2026 11:41:00 +0530 Subject: [PATCH] create message cache temp files with owner-only permissions Signed-off-by: mohammed arib --- .../org/eclipse/angus/mail/mbox/TempFile.java | 29 ++++++++- .../eclipse/angus/mail/mbox/TempFileTest.java | 63 +++++++++++++++++++ .../org/eclipse/angus/mail/pop3/TempFile.java | 29 ++++++++- 3 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 providers/mbox/src/test/java/org/eclipse/angus/mail/mbox/TempFileTest.java diff --git a/providers/mbox/src/main/java/org/eclipse/angus/mail/mbox/TempFile.java b/providers/mbox/src/main/java/org/eclipse/angus/mail/mbox/TempFile.java index b893034d..e3ccea7f 100644 --- a/providers/mbox/src/main/java/org/eclipse/angus/mail/mbox/TempFile.java +++ b/providers/mbox/src/main/java/org/eclipse/angus/mail/mbox/TempFile.java @@ -23,6 +23,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.nio.file.Files; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermissions; /** * A temporary file used to cache messages. @@ -37,12 +40,34 @@ class TempFile { * The file will be deleted when the JVM exits. */ public TempFile(File dir) throws IOException { - file = File.createTempFile("mbox.", ".mbox", dir); - // XXX - need JDK 6 to set permissions on the file to owner-only + file = createTempFile("mbox.", ".mbox", dir); file.deleteOnExit(); sf = new WritableSharedFile(file); } + /** + * Create the cache file with owner-only permissions so that the + * cached message content isn't readable by other local users. On + * file systems without POSIX permissions the platform default is + * used. + */ + private static File createTempFile(String prefix, String suffix, File dir) + throws IOException { + try { + FileAttribute attr = PosixFilePermissions.asFileAttribute( + PosixFilePermissions.fromString("rw-------")); + if (dir != null) + return Files.createTempFile( + dir.toPath(), prefix, suffix, attr).toFile(); + return Files.createTempFile(prefix, suffix, attr).toFile(); + } catch (UnsupportedOperationException ex) { + if (dir != null) + return Files.createTempFile( + dir.toPath(), prefix, suffix).toFile(); + return Files.createTempFile(prefix, suffix).toFile(); + } + } + /** * Return a stream for appending to the temp file. */ diff --git a/providers/mbox/src/test/java/org/eclipse/angus/mail/mbox/TempFileTest.java b/providers/mbox/src/test/java/org/eclipse/angus/mail/mbox/TempFileTest.java new file mode 100644 index 00000000..60d5b61c --- /dev/null +++ b/providers/mbox/src/test/java/org/eclipse/angus/mail/mbox/TempFileTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.eclipse.angus.mail.mbox; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeTrue; + +/** + * Test that the message cache temp file is created owner-only. + */ +public final class TempFileTest { + + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + + @Test + public void testCacheFileIsOwnerOnly() throws Exception { + assumeTrue("requires a POSIX file system", + FileSystems.getDefault().supportedFileAttributeViews() + .contains("posix")); + + File dir = folder.newFolder(); + TempFile tf = new TempFile(dir); + try { + File[] created = dir.listFiles((d, n) -> + n.startsWith("mbox.") && n.endsWith(".mbox")); + assertEquals(1, created.length); + Path p = created[0].toPath(); + Set perms = Files.getPosixFilePermissions(p); + assertEquals("cache file must not be readable by group or others", + Set.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE), + perms); + } finally { + tf.close(); + } + } +} diff --git a/providers/pop3/src/main/java/org/eclipse/angus/mail/pop3/TempFile.java b/providers/pop3/src/main/java/org/eclipse/angus/mail/pop3/TempFile.java index dc76c4ce..913e3961 100644 --- a/providers/pop3/src/main/java/org/eclipse/angus/mail/pop3/TempFile.java +++ b/providers/pop3/src/main/java/org/eclipse/angus/mail/pop3/TempFile.java @@ -18,6 +18,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermissions; /** * A temporary file used to cache POP3 messages. @@ -32,12 +35,34 @@ class TempFile { * The file will be deleted when the JVM exits. */ public TempFile(File dir) throws IOException { - file = File.createTempFile("pop3.", ".mbox", dir); - // XXX - need JDK 6 to set permissions on the file to owner-only + file = createTempFile("pop3.", ".mbox", dir); file.deleteOnExit(); sf = new WritableSharedFile(file); } + /** + * Create the cache file with owner-only permissions so that the + * cached message content isn't readable by other local users. On + * file systems without POSIX permissions the platform default is + * used. + */ + private static File createTempFile(String prefix, String suffix, File dir) + throws IOException { + try { + FileAttribute attr = PosixFilePermissions.asFileAttribute( + PosixFilePermissions.fromString("rw-------")); + if (dir != null) + return Files.createTempFile( + dir.toPath(), prefix, suffix, attr).toFile(); + return Files.createTempFile(prefix, suffix, attr).toFile(); + } catch (UnsupportedOperationException ex) { + if (dir != null) + return Files.createTempFile( + dir.toPath(), prefix, suffix).toFile(); + return Files.createTempFile(prefix, suffix).toFile(); + } + } + /** * Return a stream for appending to the temp file. */