Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User XML configuration persistence #380

Merged
merged 15 commits into from
Apr 18, 2019
Merged
Show file tree
Hide file tree
Changes from 13 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
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,16 @@ webcore/lib/
.idea
.vscode/
*.iml


#MacOS
.DS_Store
.AppleDouble
.LSOverride
._*

.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
142 changes: 71 additions & 71 deletions dicoogle/src/main/java/pt/ua/dicoogle/server/users/UserFileHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,31 @@
*/
package pt.ua.dicoogle.server.users;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pt.ua.dicoogle.sdk.Utils.Platform;

import javax.crypto.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import org.slf4j.LoggerFactory;

import pt.ua.dicoogle.core.settings.ServerSettingsManager;
import pt.ua.dicoogle.sdk.Utils.Platform;

/**
* This class provides encryptation to the file that saves users information
* Uses the AES algorithim with 128 bit key
* This class provides encryption to the file that saves users information
* Uses the AES algorithm with 128 bit key
*
* @author Samuel Campos <[email protected]>
*/
public class UserFileHandle {

private static final Logger logger = LoggerFactory.getLogger(UserFileHandle.class);

private String filenamePath;
private String filename;
private String keyFile;

Expand All @@ -58,11 +51,12 @@ public class UserFileHandle {
private boolean encrypt;

public UserFileHandle() throws IOException {
filename = Platform.homePath() + "users.xml";
filename = "users.xml";
filenamePath = Platform.homePath() + filename;
encrypt = true; //ServerSettingsManager.getSettings().isEncryptUsersFile();
try {

if(encrypt){
if (encrypt) {
keyFile = "users.key";

try {
Expand All @@ -85,77 +79,83 @@ public UserFileHandle() throws IOException {
}

} catch (NoSuchAlgorithmException | ClassNotFoundException | NoSuchPaddingException ex) {
LoggerFactory.getLogger(UserFileHandle.class).error(ex.getMessage(), ex);
logger.error(ex.getMessage(), ex);
}
}

/**
* Print one byte array in File
* Encrypt that file with the key
*
* @param bytes
*/
public void printFile(byte[] bytes) throws Exception {
InputStream in;

if(encrypt){
cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] encryptedBytes = cipher.doFinal(bytes);
in = new ByteArrayInputStream(encryptedBytes);
}
else
in = new ByteArrayInputStream(bytes);

FileOutputStream out = new FileOutputStream(filename);

public void printFile(byte[] bytes) throws IOException {
if (encrypt) {
byte[] encryptedBytes = new byte[0];

try {
cipher.init(Cipher.ENCRYPT_MODE, key);

encryptedBytes = cipher.doFinal(bytes);
} catch (BadPaddingException e) {
logger.error("Invalid Key to decrypt users file.", e);
} catch (IllegalBlockSizeException e) {
logger.error("Users file \"{}\" is corrupted.", filename, e);
} catch (InvalidKeyException e) {
logger.error("Invalid Key to decrypt users file.", e);
}

byte[] input = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(input)) != -1) {
out.write(input, 0, bytesRead);
out.flush();
printFileAux(encryptedBytes);
} else {
printFileAux(bytes);
}

out.close();
in.close();
}

/** Retrieve the contents of the users configuration file.
/**
* Retrieve the contents of the users configuration file.
*
* @return a byte array, or null if the configuration file is not available or corrupted
* @throws IOException on a failed attempt to read the file
*/
public byte[] getFileContent() throws IOException {
try {
try (FileInputStream fin = new FileInputStream(filename);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] data = new byte[1024];
int bytesRead;

while ((bytesRead = fin.read(data)) != -1) {
out.write(data, 0, bytesRead);
out.flush();
}
public byte[] getFileContent() {
try (FileInputStream fin = new FileInputStream(filename);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] data = new byte[1024];
int bytesRead;

while ((bytesRead = fin.read(data)) != -1) {
out.write(data, 0, bytesRead);
out.flush();
}

if(encrypt){
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] Bytes = cipher.doFinal(out.toByteArray());
return Bytes;
}

return out.toByteArray();
if (encrypt) {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] Bytes = cipher.doFinal(out.toByteArray());
return Bytes;
}

return out.toByteArray();

} catch (FileNotFoundException ex) {
LoggerFactory.getLogger(UserFileHandle.class).info("No such users file \"{}\", will create one with default settings.", filename);
logger.info("No such users file \"{}\", will create one with default settings.", filename);
} catch (IllegalBlockSizeException ex) {
LoggerFactory.getLogger(UserFileHandle.class).error("Users file \"{}\" is corrupted, will override it with default settings.", filename, ex);
logger.error("Users file \"{}\" is corrupted, will override it with default settings.", filename, ex);
} catch (InvalidKeyException ex) {
LoggerFactory.getLogger(UserFileHandle.class).error("Invalid Key to decrypt users file! Please contact your system administator.");
logger.error("Invalid Key to decrypt users file! Please contact your system administator.");
System.exit(1); // FIXME this is too dangerous
}
catch(BadPaddingException ex){
LoggerFactory.getLogger(UserFileHandle.class).error("Invalid Key to decrypt users file! Please contact your system administator.");
} catch (BadPaddingException ex) {
logger.error("Invalid Key to decrypt users file! Please contact your system administator.");
System.exit(2); // FIXME this is too dangerous
} catch (IOException ex) {
logger.error("Error writing file \"{}\".", filename, ex);
}

return null;
}

private void printFileAux(byte[] bytes) throws IOException {
try (InputStream in = new ByteArrayInputStream(bytes)) {
Files.copy(in, Paths.get(filename), StandardCopyOption.REPLACE_EXISTING);
}
}
}
79 changes: 44 additions & 35 deletions dicoogle/src/main/java/pt/ua/dicoogle/server/users/UsersStruct.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,22 @@
*/
package pt.ua.dicoogle.server.users;

import java.util.Collection;
import java.util.HashMap;

import java.util.Set;
import java.util.*;

/**
* This class stores the list of users of Dicoogle
*
* @author Samuel Campos <[email protected]>
* @author Rui Lebre <[email protected]>
*/
public class UsersStruct {
private HashMap<String, User> users;

private static UsersStruct instance = null ;
private static UsersStruct instance = null;

// count the number of administrators
private int numberOfAdmins;
private UsersXML usersXML;

public static synchronized UsersStruct getInstance() {
if (instance == null) {
Expand All @@ -45,94 +44,104 @@ public static synchronized UsersStruct getInstance() {
}


private UsersStruct() {
reset();

usersXML = new UsersXML();
Collection<User> userList = usersXML.getXML();

for (User user : userList) {
users.put(user.getUsername(), user);
if(user.isAdmin()) {
numberOfAdmins++;
}
}

private UsersStruct(){
reset();
}


/**
* Insert one default user
* Username: "dicoogle"
* Password: "DCpassword" (hashed)
* Password: "dicoogle" (hashed)
*
* This user is administrator
*/
public void setDefaults(){
//DebugManager.getSettings().debug("Setting default user settings");

public static Collection<User> getDefaults() {
String username = "dicoogle";
boolean admin = true;
String passPlainText = "dicoogle";

String passHash = HashService.getSHA1Hash(passPlainText); //password Hash
String Hash = HashService.getSHA1Hash(username + admin + passHash); //user Hash
String hash = HashService.getSHA1Hash(username + admin + passHash); //user Hash

users = new HashMap<String, User>();
users.put("dicoogle", new User(username, Hash, admin));
return Collections.singleton(new User(username, hash, admin));
}

/**
* Used only by UsersXML to reset User Settings
*/
protected void reset(){
users = new HashMap<String, User>();
protected void reset() {
users = new HashMap<>();
numberOfAdmins = 0;
}


/**
* Insert user in the List of users
*
* @param user
* @return true - if succeeded. false - if the username already exists
* @return true - if succeeded. false - if the username already exists
*/
public boolean addUser(User user){
if(users.containsKey(user.getUsername()))
public boolean addUser(User user) {
if (users.containsKey(user.getUsername()))
return false;

users.put(user.getUsername(), user);

if(user.isAdmin())
if (user.isAdmin())
numberOfAdmins++;


usersXML.printXML(this.getUsers());
return true;
}

/**
* Removes one user from de list
* Maintains at least one administrator in the list
* (refuses to remove the last one)
*
* Removes one user from de list
* Maintains at least one administrator in the list
* (refuses to remove the last one)
*
* @param username
* @return
*/
public boolean removeUser(String username){
if(username == null)
public boolean removeUser(String username) {
if (username == null)
return false;

User user = users.get(username);
if (user == null)
return false;

if(user.isAdmin() && numberOfAdmins == 1)
if (user.isAdmin() && numberOfAdmins == 1)
return false;
else if(user.isAdmin())
else if (user.isAdmin())
numberOfAdmins--;

users.remove(username);
usersXML.printXML(users.values());

return true;
}

public Collection<User> getUsers(){
public Collection<User> getUsers() {
return users.values();
}

public Set<String> getUsernames(){
public Set<String> getUsernames() {
return users.keySet();
}

public User getUser(String username){
public User getUser(String username) {
return users.get(username);
}
}
Loading