ensure config, wallet dirs and wallets are owner read/write only

This commit is contained in:
Craig Raw 2021-05-05 11:25:25 +02:00
parent 438c13fe2d
commit a0d3f3b745
3 changed files with 73 additions and 17 deletions

View file

@ -936,8 +936,13 @@ public class AppController implements Initializable {
Optional<SecureString> password = dlg.showAndWait();
if(password.isPresent()) {
if(password.get().length() == 0) {
storage.setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
addWalletTabOrWindow(storage, wallet, null, false);
try {
storage.setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
storage.storeWallet(wallet);
addWalletTabOrWindow(storage, wallet, null, false);
} catch(IOException e) {
log.error("Error saving imported wallet", e);
}
} else {
Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(storage, password.get());
keyDerivationService.setOnSucceeded(workerStateEvent -> {
@ -950,7 +955,10 @@ public class AppController implements Initializable {
key = new Key(encryptionFullKey.getPrivKeyBytes(), storage.getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
wallet.encrypt(key);
storage.setEncryptionPubKey(encryptionPubKey);
storage.storeWallet(wallet);
addWalletTabOrWindow(storage, wallet, null, false);
} catch(IOException e) {
log.error("Error saving imported wallet", e);
} finally {
encryptionFullKey.clear();
if(key != null) {

View file

@ -11,6 +11,8 @@ import org.slf4j.LoggerFactory;
import java.io.*;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Arrays;
import java.util.Currency;
import java.util.List;
@ -67,10 +69,6 @@ public class Config {
private static File getConfigFile() {
File sparrowDir = Storage.getSparrowDir();
if(!sparrowDir.exists()) {
sparrowDir.mkdirs();
}
return new File(sparrowDir, CONFIG_FILENAME);
}
@ -445,6 +443,10 @@ public class Config {
Gson gson = getGson();
try {
File configFile = getConfigFile();
if(!configFile.exists()) {
Files.createFile(configFile.toPath(), PosixFilePermissions.asFileAttribute(Storage.getFileOwnerOnlyFilePermissions()));
}
Writer writer = new FileWriter(configFile);
gson.toJson(this, writer);
writer.flush();

View file

@ -1,6 +1,5 @@
package com.sparrowwallet.sparrow.io;
import com.google.common.io.Files;
import com.google.gson.*;
import com.sparrowwallet.drongo.ExtendedKey;
import com.sparrowwallet.drongo.Network;
@ -23,6 +22,9 @@ import java.io.*;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@ -153,7 +155,7 @@ public class Storage {
}
File parent = walletFile.getParentFile();
if(!parent.exists() && !parent.mkdirs()) {
if(!parent.exists() && !createOwnerOnlyDirectory(parent)) {
throw new IOException("Could not create folder " + parent);
}
@ -167,6 +169,10 @@ public class Storage {
walletFile = jsonFile;
}
if(!walletFile.exists()) {
Files.createFile(walletFile.toPath(), PosixFilePermissions.asFileAttribute(getFileOwnerOnlyFilePermissions()));
}
Writer writer = new FileWriter(walletFile);
gson.toJson(wallet, writer);
writer.close();
@ -174,7 +180,7 @@ public class Storage {
private void storeWallet(ECKey encryptionPubKey, Wallet wallet) throws IOException {
File parent = walletFile.getParentFile();
if(!parent.exists() && !parent.mkdirs()) {
if(!parent.exists() && !createOwnerOnlyDirectory(parent)) {
throw new IOException("Could not create folder " + parent);
}
@ -188,6 +194,10 @@ public class Storage {
walletFile = noJsonFile;
}
if(!walletFile.exists()) {
Files.createFile(walletFile.toPath(), PosixFilePermissions.asFileAttribute(getFileOwnerOnlyFilePermissions()));
}
OutputStream outputStream = new FileOutputStream(walletFile);
writeBinaryHeader(outputStream);
@ -238,7 +248,10 @@ public class Storage {
}
File backupFile = new File(backupDir, backupName);
Files.copy(walletFile, backupFile);
if(!backupFile.exists()) {
Files.createFile(backupFile.toPath(), PosixFilePermissions.asFileAttribute(getFileOwnerOnlyFilePermissions()));
}
com.google.common.io.Files.copy(walletFile, backupFile);
}
public void deleteBackups() {
@ -259,7 +272,7 @@ public class Storage {
private File[] getBackups(String extension, String notExtension) {
File backupDir = getWalletsBackupDir();
File[] backups = backupDir.listFiles((dir, name) -> {
return name.startsWith(Files.getNameWithoutExtension(walletFile.getName()) + "-") &&
return name.startsWith(com.google.common.io.Files.getNameWithoutExtension(walletFile.getName()) + "-") &&
getBackupDate(name) != null &&
(extension == null || name.endsWith("." + extension)) &&
(notExtension == null || !name.endsWith("." + notExtension));
@ -372,7 +385,7 @@ public class Storage {
public static File getWalletsBackupDir() {
File walletsBackupDir = new File(getWalletsDir(), WALLETS_BACKUP_DIR);
if(!walletsBackupDir.exists()) {
walletsBackupDir.mkdirs();
createOwnerOnlyDirectory(walletsBackupDir);
}
return walletsBackupDir;
@ -381,7 +394,7 @@ public class Storage {
public static File getWalletsDir() {
File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
if(!walletsDir.exists()) {
walletsDir.mkdirs();
createOwnerOnlyDirectory(walletsDir);
}
return walletsDir;
@ -390,7 +403,7 @@ public class Storage {
public static File getCertificateFile(String host) {
File certsDir = getCertsDir();
File[] certs = certsDir.listFiles((dir, name) -> name.equals(host));
if(certs.length > 0) {
if(certs != null && certs.length > 0) {
return certs[0];
}
@ -412,18 +425,25 @@ public class Storage {
static File getCertsDir() {
File certsDir = new File(getSparrowDir(), CERTS_DIR);
if(!certsDir.exists()) {
certsDir.mkdirs();
createOwnerOnlyDirectory(certsDir);
}
return certsDir;
}
static File getSparrowDir() {
File sparrowDir;
if(Network.get() != Network.MAINNET) {
return new File(getSparrowHome(), Network.get().getName());
sparrowDir = new File(getSparrowHome(), Network.get().getName());
} else {
sparrowDir = getSparrowHome();
}
return getSparrowHome();
if(!sparrowDir.exists()) {
createOwnerOnlyDirectory(sparrowDir);
}
return sparrowDir;
}
public static File getSparrowHome() {
@ -446,6 +466,32 @@ public class Storage {
return new File(System.getProperty("user.home"));
}
private static boolean createOwnerOnlyDirectory(File directory) {
try {
Files.createDirectories(directory.toPath(), PosixFilePermissions.asFileAttribute(getDirectoryOwnerOnlyFilePermissions()));
return true;
} catch(IOException e) {
log.error("Could not create directory " + directory.getAbsolutePath(), e);
}
return false;
}
public static Set<PosixFilePermission> getDirectoryOwnerOnlyFilePermissions() {
Set<PosixFilePermission> ownerOnly = getFileOwnerOnlyFilePermissions();
ownerOnly.add(PosixFilePermission.OWNER_EXECUTE);
return ownerOnly;
}
public static Set<PosixFilePermission> getFileOwnerOnlyFilePermissions() {
Set<PosixFilePermission> ownerOnly = EnumSet.noneOf(PosixFilePermission.class);
ownerOnly.add(PosixFilePermission.OWNER_READ);
ownerOnly.add(PosixFilePermission.OWNER_WRITE);
return ownerOnly;
}
private static class ExtendedPublicKeySerializer implements JsonSerializer<ExtendedKey> {
@Override
public JsonElement serialize(ExtendedKey src, Type typeOfSrc, JsonSerializationContext context) {