mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
ensure config, wallet dirs and wallets are owner read/write only
This commit is contained in:
parent
438c13fe2d
commit
a0d3f3b745
3 changed files with 73 additions and 17 deletions
|
@ -936,8 +936,13 @@ public class AppController implements Initializable {
|
||||||
Optional<SecureString> password = dlg.showAndWait();
|
Optional<SecureString> password = dlg.showAndWait();
|
||||||
if(password.isPresent()) {
|
if(password.isPresent()) {
|
||||||
if(password.get().length() == 0) {
|
if(password.get().length() == 0) {
|
||||||
storage.setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
|
try {
|
||||||
addWalletTabOrWindow(storage, wallet, null, false);
|
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 {
|
} else {
|
||||||
Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(storage, password.get());
|
Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(storage, password.get());
|
||||||
keyDerivationService.setOnSucceeded(workerStateEvent -> {
|
keyDerivationService.setOnSucceeded(workerStateEvent -> {
|
||||||
|
@ -950,7 +955,10 @@ public class AppController implements Initializable {
|
||||||
key = new Key(encryptionFullKey.getPrivKeyBytes(), storage.getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
key = new Key(encryptionFullKey.getPrivKeyBytes(), storage.getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
||||||
wallet.encrypt(key);
|
wallet.encrypt(key);
|
||||||
storage.setEncryptionPubKey(encryptionPubKey);
|
storage.setEncryptionPubKey(encryptionPubKey);
|
||||||
|
storage.storeWallet(wallet);
|
||||||
addWalletTabOrWindow(storage, wallet, null, false);
|
addWalletTabOrWindow(storage, wallet, null, false);
|
||||||
|
} catch(IOException e) {
|
||||||
|
log.error("Error saving imported wallet", e);
|
||||||
} finally {
|
} finally {
|
||||||
encryptionFullKey.clear();
|
encryptionFullKey.clear();
|
||||||
if(key != null) {
|
if(key != null) {
|
||||||
|
|
|
@ -11,6 +11,8 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.attribute.PosixFilePermissions;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -67,10 +69,6 @@ public class Config {
|
||||||
|
|
||||||
private static File getConfigFile() {
|
private static File getConfigFile() {
|
||||||
File sparrowDir = Storage.getSparrowDir();
|
File sparrowDir = Storage.getSparrowDir();
|
||||||
if(!sparrowDir.exists()) {
|
|
||||||
sparrowDir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new File(sparrowDir, CONFIG_FILENAME);
|
return new File(sparrowDir, CONFIG_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +443,10 @@ public class Config {
|
||||||
Gson gson = getGson();
|
Gson gson = getGson();
|
||||||
try {
|
try {
|
||||||
File configFile = getConfigFile();
|
File configFile = getConfigFile();
|
||||||
|
if(!configFile.exists()) {
|
||||||
|
Files.createFile(configFile.toPath(), PosixFilePermissions.asFileAttribute(Storage.getFileOwnerOnlyFilePermissions()));
|
||||||
|
}
|
||||||
|
|
||||||
Writer writer = new FileWriter(configFile);
|
Writer writer = new FileWriter(configFile);
|
||||||
gson.toJson(this, writer);
|
gson.toJson(this, writer);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.sparrowwallet.drongo.ExtendedKey;
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
import com.sparrowwallet.drongo.Network;
|
import com.sparrowwallet.drongo.Network;
|
||||||
|
@ -23,6 +22,9 @@ import java.io.*;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
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.SecureRandom;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
@ -153,7 +155,7 @@ public class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
File parent = walletFile.getParentFile();
|
File parent = walletFile.getParentFile();
|
||||||
if(!parent.exists() && !parent.mkdirs()) {
|
if(!parent.exists() && !createOwnerOnlyDirectory(parent)) {
|
||||||
throw new IOException("Could not create folder " + parent);
|
throw new IOException("Could not create folder " + parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +169,10 @@ public class Storage {
|
||||||
walletFile = jsonFile;
|
walletFile = jsonFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!walletFile.exists()) {
|
||||||
|
Files.createFile(walletFile.toPath(), PosixFilePermissions.asFileAttribute(getFileOwnerOnlyFilePermissions()));
|
||||||
|
}
|
||||||
|
|
||||||
Writer writer = new FileWriter(walletFile);
|
Writer writer = new FileWriter(walletFile);
|
||||||
gson.toJson(wallet, writer);
|
gson.toJson(wallet, writer);
|
||||||
writer.close();
|
writer.close();
|
||||||
|
@ -174,7 +180,7 @@ public class Storage {
|
||||||
|
|
||||||
private void storeWallet(ECKey encryptionPubKey, Wallet wallet) throws IOException {
|
private void storeWallet(ECKey encryptionPubKey, Wallet wallet) throws IOException {
|
||||||
File parent = walletFile.getParentFile();
|
File parent = walletFile.getParentFile();
|
||||||
if(!parent.exists() && !parent.mkdirs()) {
|
if(!parent.exists() && !createOwnerOnlyDirectory(parent)) {
|
||||||
throw new IOException("Could not create folder " + parent);
|
throw new IOException("Could not create folder " + parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +194,10 @@ public class Storage {
|
||||||
walletFile = noJsonFile;
|
walletFile = noJsonFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!walletFile.exists()) {
|
||||||
|
Files.createFile(walletFile.toPath(), PosixFilePermissions.asFileAttribute(getFileOwnerOnlyFilePermissions()));
|
||||||
|
}
|
||||||
|
|
||||||
OutputStream outputStream = new FileOutputStream(walletFile);
|
OutputStream outputStream = new FileOutputStream(walletFile);
|
||||||
writeBinaryHeader(outputStream);
|
writeBinaryHeader(outputStream);
|
||||||
|
|
||||||
|
@ -238,7 +248,10 @@ public class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
File backupFile = new File(backupDir, backupName);
|
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() {
|
public void deleteBackups() {
|
||||||
|
@ -259,7 +272,7 @@ public class Storage {
|
||||||
private File[] getBackups(String extension, String notExtension) {
|
private File[] getBackups(String extension, String notExtension) {
|
||||||
File backupDir = getWalletsBackupDir();
|
File backupDir = getWalletsBackupDir();
|
||||||
File[] backups = backupDir.listFiles((dir, name) -> {
|
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 &&
|
getBackupDate(name) != null &&
|
||||||
(extension == null || name.endsWith("." + extension)) &&
|
(extension == null || name.endsWith("." + extension)) &&
|
||||||
(notExtension == null || !name.endsWith("." + notExtension));
|
(notExtension == null || !name.endsWith("." + notExtension));
|
||||||
|
@ -372,7 +385,7 @@ public class Storage {
|
||||||
public static File getWalletsBackupDir() {
|
public static File getWalletsBackupDir() {
|
||||||
File walletsBackupDir = new File(getWalletsDir(), WALLETS_BACKUP_DIR);
|
File walletsBackupDir = new File(getWalletsDir(), WALLETS_BACKUP_DIR);
|
||||||
if(!walletsBackupDir.exists()) {
|
if(!walletsBackupDir.exists()) {
|
||||||
walletsBackupDir.mkdirs();
|
createOwnerOnlyDirectory(walletsBackupDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return walletsBackupDir;
|
return walletsBackupDir;
|
||||||
|
@ -381,7 +394,7 @@ public class Storage {
|
||||||
public static File getWalletsDir() {
|
public static File getWalletsDir() {
|
||||||
File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
|
File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
|
||||||
if(!walletsDir.exists()) {
|
if(!walletsDir.exists()) {
|
||||||
walletsDir.mkdirs();
|
createOwnerOnlyDirectory(walletsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return walletsDir;
|
return walletsDir;
|
||||||
|
@ -390,7 +403,7 @@ public class Storage {
|
||||||
public static File getCertificateFile(String host) {
|
public static File getCertificateFile(String host) {
|
||||||
File certsDir = getCertsDir();
|
File certsDir = getCertsDir();
|
||||||
File[] certs = certsDir.listFiles((dir, name) -> name.equals(host));
|
File[] certs = certsDir.listFiles((dir, name) -> name.equals(host));
|
||||||
if(certs.length > 0) {
|
if(certs != null && certs.length > 0) {
|
||||||
return certs[0];
|
return certs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,18 +425,25 @@ public class Storage {
|
||||||
static File getCertsDir() {
|
static File getCertsDir() {
|
||||||
File certsDir = new File(getSparrowDir(), CERTS_DIR);
|
File certsDir = new File(getSparrowDir(), CERTS_DIR);
|
||||||
if(!certsDir.exists()) {
|
if(!certsDir.exists()) {
|
||||||
certsDir.mkdirs();
|
createOwnerOnlyDirectory(certsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return certsDir;
|
return certsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File getSparrowDir() {
|
static File getSparrowDir() {
|
||||||
|
File sparrowDir;
|
||||||
if(Network.get() != Network.MAINNET) {
|
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() {
|
public static File getSparrowHome() {
|
||||||
|
@ -446,6 +466,32 @@ public class Storage {
|
||||||
return new File(System.getProperty("user.home"));
|
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> {
|
private static class ExtendedPublicKeySerializer implements JsonSerializer<ExtendedKey> {
|
||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(ExtendedKey src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(ExtendedKey src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
|
Loading…
Reference in a new issue