927 lines
30 KiB
Java
927 lines
30 KiB
Java
/*
|
|
* Copyright (c) 2010
|
|
*
|
|
* Robert von Burg
|
|
* eitch@eitchnet.ch
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
*/
|
|
|
|
package ch.eitchnet.privilege.handler;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.apache.log4j.Logger;
|
|
|
|
import ch.eitchnet.privilege.i18n.AccessDeniedException;
|
|
import ch.eitchnet.privilege.i18n.PrivilegeException;
|
|
import ch.eitchnet.privilege.model.Certificate;
|
|
import ch.eitchnet.privilege.model.PrivilegeRep;
|
|
import ch.eitchnet.privilege.model.Restrictable;
|
|
import ch.eitchnet.privilege.model.RoleRep;
|
|
import ch.eitchnet.privilege.model.UserRep;
|
|
import ch.eitchnet.privilege.model.UserState;
|
|
import ch.eitchnet.privilege.model.internal.Privilege;
|
|
import ch.eitchnet.privilege.model.internal.Role;
|
|
import ch.eitchnet.privilege.model.internal.Session;
|
|
import ch.eitchnet.privilege.model.internal.User;
|
|
import ch.eitchnet.privilege.policy.PrivilegePolicy;
|
|
|
|
/**
|
|
* <p>
|
|
* This is default implementation of the {@link PrivilegeHandler}
|
|
* </p>
|
|
*
|
|
* The following list describes implementation details:
|
|
* <ul>
|
|
* <li>any methods which change the model are first validated by checking if the certificate is for an admin user by
|
|
* calling {@link #validateIsPrivilegeAdmin(Certificate)}</li>
|
|
* <li>all model requests are delegated to the configured {@link PrivilegeHandler}, except for the session id to
|
|
* {@link Certificate} map, no model data is kept in this implementation. This also means that to return the
|
|
* representation objects, for every new model query, a new representation object is created</li>
|
|
* <li>when creating new users, or editing users then a null password is understood as no password set</li>
|
|
* <li>Password requirements are simple: Non null and non empty/length 0</li>
|
|
* </ul>
|
|
*
|
|
* @author rvonburg
|
|
*
|
|
*/
|
|
public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|
|
|
/**
|
|
* log4j logger
|
|
*/
|
|
private static final Logger logger = Logger.getLogger(DefaultPrivilegeHandler.class);
|
|
|
|
/**
|
|
* last assigned id for the {@link Session}s
|
|
*/
|
|
private static long lastSessionId;
|
|
|
|
/**
|
|
* Map keeping a reference to all active sessions with their certificates
|
|
*/
|
|
private Map<String, CertificateSessionPair> sessionMap;
|
|
|
|
/**
|
|
* The persistence handler is used for getting objects and saving changes
|
|
*/
|
|
private PersistenceHandler persistenceHandler;
|
|
|
|
/**
|
|
* The encryption handler is used for generating hashes and tokens
|
|
*/
|
|
private EncryptionHandler encryptionHandler;
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#getPrivilege(java.lang.String)
|
|
*/
|
|
@Override
|
|
public PrivilegeRep getPrivilege(String privilegeName) {
|
|
return this.persistenceHandler.getPrivilege(privilegeName).asPrivilegeRep();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#getRole(java.lang.String)
|
|
*/
|
|
@Override
|
|
public RoleRep getRole(String roleName) {
|
|
return this.persistenceHandler.getRole(roleName).asRoleRep();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#getUser(java.lang.String)
|
|
*/
|
|
@Override
|
|
public UserRep getUser(String username) {
|
|
return this.persistenceHandler.getUser(username).asUserRep();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#getPolicy(java.lang.String)
|
|
*/
|
|
@Override
|
|
public PrivilegePolicy getPolicy(String policyName) {
|
|
return this.persistenceHandler.getPolicy(policyName);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#addOrReplacePrivilege(ch.eitchnet.privilege.model.Certificate,
|
|
* ch.eitchnet.privilege.model.PrivilegeRep)
|
|
*/
|
|
@Override
|
|
public void addOrReplacePrivilege(Certificate certificate, PrivilegeRep privilegeRep) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// create a new privilege
|
|
Privilege privilege = new Privilege(privilegeRep.getName(), privilegeRep.getPolicy(),
|
|
privilegeRep.isAllAllowed(), privilegeRep.getDenyList(), privilegeRep.getAllowList());
|
|
|
|
// delegate to persistence handler
|
|
this.persistenceHandler.addOrReplacePrivilege(privilege);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#addOrReplaceRole(ch.eitchnet.privilege.model.Certificate,
|
|
* ch.eitchnet.privilege.model.RoleRep)
|
|
*/
|
|
@Override
|
|
public void addOrReplaceRole(Certificate certificate, RoleRep roleRep) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// create new role
|
|
Role role = new Role(roleRep.getName(), roleRep.getPrivileges());
|
|
|
|
// delegate to persistence handler
|
|
this.persistenceHandler.addOrReplaceRole(role);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#addOrReplaceUser(ch.eitchnet.privilege.model.Certificate,
|
|
* ch.eitchnet.privilege.model.UserRep, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void addOrReplaceUser(Certificate certificate, UserRep userRep, String password) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
String passwordHash = null;
|
|
if (password != null) {
|
|
|
|
// validate password meets basic requirements
|
|
validatePassword(password);
|
|
|
|
// hash password
|
|
passwordHash = this.encryptionHandler.convertToHash(password);
|
|
}
|
|
|
|
// create new user
|
|
User user = new User(userRep.getUserId(), userRep.getUsername(), passwordHash, userRep.getFirstname(),
|
|
userRep.getSurname(), userRep.getUserState(), userRep.getRoles(), userRep.getLocale());
|
|
|
|
// delegate to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(user);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#addPrivilegeToRole(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void addPrivilegeToRole(Certificate certificate, String roleName, String privilegeName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get role
|
|
Role role = this.persistenceHandler.getRole(roleName);
|
|
if (role == null) {
|
|
throw new PrivilegeException("Role " + roleName + " does not exist!");
|
|
}
|
|
|
|
// ignore if role already has this privilege
|
|
Set<String> currentPrivileges = role.getPrivileges();
|
|
if (currentPrivileges.contains(roleName)) {
|
|
logger.error("Role " + roleName + " already has privilege " + privilegeName);
|
|
return;
|
|
}
|
|
|
|
// validate that privilege exists
|
|
if (getPrivilege(privilegeName) == null) {
|
|
throw new PrivilegeException("Privilege " + privilegeName + " does not exist and can not be added to role "
|
|
+ roleName);
|
|
}
|
|
|
|
// create new role with the additional privilege
|
|
Set<String> newPrivileges = new HashSet<String>(currentPrivileges);
|
|
newPrivileges.add(roleName);
|
|
|
|
Role newRole = new Role(role.getName(), newPrivileges);
|
|
|
|
// delegate role replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceRole(newRole);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#addRoleToUser(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void addRoleToUser(Certificate certificate, String username, String roleName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get user
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
// ignore if user already has role
|
|
Set<String> currentRoles = user.getRoles();
|
|
if (currentRoles.contains(roleName)) {
|
|
logger.error("User " + username + " already has role " + roleName);
|
|
return;
|
|
}
|
|
|
|
// validate that role exists
|
|
if (getRole(roleName) == null) {
|
|
throw new PrivilegeException("Role " + roleName + " doest not exist!");
|
|
}
|
|
|
|
// create new user
|
|
Set<String> newRoles = new HashSet<String>(currentRoles);
|
|
newRoles.add(roleName);
|
|
|
|
User newUser = new User(user.getUserId(), user.getUsername(), user.getPassword(), user.getFirstname(),
|
|
user.getSurname(), user.getUserState(), newRoles, user.getLocale());
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#removePrivilege(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String)
|
|
*/
|
|
@Override
|
|
public PrivilegeRep removePrivilege(Certificate certificate, String privilegeName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// delegate privilege removal to persistence handler
|
|
Privilege removedPrivilege = this.persistenceHandler.removePrivilege(privilegeName);
|
|
|
|
if (removedPrivilege == null)
|
|
return null;
|
|
|
|
// return privilege rep if it was removed
|
|
return removedPrivilege.asPrivilegeRep();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#removePrivilegeFromRole(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void removePrivilegeFromRole(Certificate certificate, String roleName, String privilegeName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get role
|
|
Role role = this.persistenceHandler.getRole(roleName);
|
|
if (role == null) {
|
|
throw new PrivilegeException("Role " + roleName + " does not exist!");
|
|
}
|
|
|
|
// ignore if role does not have privilege
|
|
Set<String> currentPrivileges = role.getPrivileges();
|
|
if (!currentPrivileges.contains(privilegeName)) {
|
|
logger.error("Role " + roleName + " doest not have privilege " + privilegeName);
|
|
return;
|
|
}
|
|
|
|
// create new role
|
|
Set<String> newPrivileges = new HashSet<String>(currentPrivileges);
|
|
newPrivileges.remove(privilegeName);
|
|
Role newRole = new Role(role.getName(), newPrivileges);
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceRole(newRole);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#removeRole(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String)
|
|
*/
|
|
@Override
|
|
public RoleRep removeRole(Certificate certificate, String roleName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// delegate role removal to persistence handler
|
|
Role removedRole = this.persistenceHandler.removeRole(roleName);
|
|
|
|
if (removedRole == null)
|
|
return null;
|
|
|
|
// return role rep if it was removed
|
|
return removedRole.asRoleRep();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#removeRoleFromUser(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void removeRoleFromUser(Certificate certificate, String username, String roleName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get User
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
// ignore if user does not have role
|
|
Set<String> currentRoles = user.getRoles();
|
|
if (!currentRoles.contains(roleName)) {
|
|
logger.error("User " + user + " does not have role " + roleName);
|
|
return;
|
|
}
|
|
|
|
// create new user
|
|
Set<String> newRoles = new HashSet<String>(currentRoles);
|
|
newRoles.remove(roleName);
|
|
User newUser = new User(user.getUserId(), user.getUsername(), user.getPassword(), user.getFirstname(),
|
|
user.getSurname(), user.getUserState(), newRoles, user.getLocale());
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#removeUser(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String)
|
|
*/
|
|
@Override
|
|
public UserRep removeUser(Certificate certificate, String username) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// delegate user removal to persistence handler
|
|
User removedUser = this.persistenceHandler.removeUser(username);
|
|
|
|
// return user rep if it was removed
|
|
if (removedUser == null)
|
|
return null;
|
|
|
|
// return user rep if it was removed
|
|
return removedUser.asUserRep();
|
|
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setPrivilegeAllAllowed(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, boolean)
|
|
*/
|
|
@Override
|
|
public void setPrivilegeAllAllowed(Certificate certificate, String privilegeName, boolean allAllowed) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get Privilege
|
|
Privilege privilege = this.persistenceHandler.getPrivilege(privilegeName);
|
|
if (privilege == null) {
|
|
throw new PrivilegeException("Privilege " + privilegeName + " does not exist!");
|
|
}
|
|
|
|
// ignore if privilege is already set to argument
|
|
if (privilege.isAllAllowed() == allAllowed) {
|
|
logger.error("Privilege " + privilegeName + " is already set to "
|
|
+ (allAllowed ? "all allowed" : "not all allowed"));
|
|
return;
|
|
}
|
|
|
|
// create new privilege
|
|
Privilege newPrivilege = new Privilege(privilege.getName(), privilege.getPolicy(), allAllowed,
|
|
privilege.getDenyList(), privilege.getAllowList());
|
|
|
|
// delegate privilege replacement to persistence handler
|
|
this.persistenceHandler.addOrReplacePrivilege(newPrivilege);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setPrivilegeAllowList(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.util.Set)
|
|
*/
|
|
@Override
|
|
public void setPrivilegeAllowList(Certificate certificate, String privilegeName, Set<String> allowList) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get Privilege
|
|
Privilege privilege = this.persistenceHandler.getPrivilege(privilegeName);
|
|
if (privilege == null) {
|
|
throw new PrivilegeException("Privilege " + privilegeName + " does not exist!");
|
|
}
|
|
|
|
// create new privilege
|
|
Privilege newPrivilege = new Privilege(privilege.getName(), privilege.getPolicy(), privilege.isAllAllowed(),
|
|
privilege.getDenyList(), allowList);
|
|
|
|
// delegate privilege replacement to persistence handler
|
|
this.persistenceHandler.addOrReplacePrivilege(newPrivilege);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setPrivilegeDenyList(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.util.Set)
|
|
*/
|
|
@Override
|
|
public void setPrivilegeDenyList(Certificate certificate, String privilegeName, Set<String> denyList) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get Privilege
|
|
Privilege privilege = this.persistenceHandler.getPrivilege(privilegeName);
|
|
if (privilege == null) {
|
|
throw new PrivilegeException("Privilege " + privilegeName + " does not exist!");
|
|
}
|
|
|
|
// create new privilege
|
|
Privilege newPrivilege = new Privilege(privilege.getName(), privilege.getPolicy(), privilege.isAllAllowed(),
|
|
denyList, privilege.getAllowList());
|
|
|
|
// delegate privilege replacement to persistence handler
|
|
this.persistenceHandler.addOrReplacePrivilege(newPrivilege);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setPrivilegePolicy(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void setPrivilegePolicy(Certificate certificate, String privilegeName, String policyName) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get Privilege
|
|
Privilege privilege = this.persistenceHandler.getPrivilege(privilegeName);
|
|
if (privilege == null) {
|
|
throw new PrivilegeException("Privilege " + privilegeName + " does not exist!");
|
|
}
|
|
|
|
// validate that the policy exists
|
|
PrivilegePolicy policy = this.persistenceHandler.getPolicy(policyName);
|
|
if (policy == null) {
|
|
throw new PrivilegeException("No privilege policy exists for the name " + policyName);
|
|
}
|
|
|
|
// create new privilege
|
|
Privilege newPrivilege = new Privilege(privilege.getName(), policyName, privilege.isAllAllowed(),
|
|
privilege.getDenyList(), privilege.getAllowList());
|
|
|
|
// delegate privilege replacement to persistence handler
|
|
this.persistenceHandler.addOrReplacePrivilege(newPrivilege);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setUserLocale(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.util.Locale)
|
|
*/
|
|
@Override
|
|
public void setUserLocale(Certificate certificate, String username, Locale locale) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get User
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
// create new user
|
|
User newUser = new User(user.getUserId(), user.getUsername(), user.getPassword(), user.getFirstname(),
|
|
user.getSurname(), user.getUserState(), user.getRoles(), locale);
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setUserName(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void setUserName(Certificate certificate, String username, String firstname, String surname) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get User
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
// create new user
|
|
User newUser = new User(user.getUserId(), user.getUsername(), user.getPassword(), firstname, surname,
|
|
user.getUserState(), user.getRoles(), user.getLocale());
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setUserPassword(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void setUserPassword(Certificate certificate, String username, String password) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get User
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
String passwordHash = null;
|
|
if (password != null) {
|
|
|
|
// validate password meets basic requirements
|
|
validatePassword(password);
|
|
|
|
// hash password
|
|
passwordHash = this.encryptionHandler.convertToHash(password);
|
|
}
|
|
|
|
// create new user
|
|
User newUser = new User(user.getUserId(), user.getUsername(), passwordHash, user.getFirstname(),
|
|
user.getSurname(), user.getUserState(), user.getRoles(), user.getLocale());
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#setUserState(ch.eitchnet.privilege.model.Certificate,
|
|
* java.lang.String, ch.eitchnet.privilege.model.UserState)
|
|
*/
|
|
@Override
|
|
public void setUserState(Certificate certificate, String username, UserState state) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
// get User
|
|
User user = this.persistenceHandler.getUser(username);
|
|
if (user == null) {
|
|
throw new PrivilegeException("User " + username + " does not exist!");
|
|
}
|
|
|
|
// create new user
|
|
User newUser = new User(user.getUserId(), user.getUsername(), user.getPassword(), user.getFirstname(),
|
|
user.getSurname(), state, user.getRoles(), user.getLocale());
|
|
|
|
// delegate user replacement to persistence handler
|
|
this.persistenceHandler.addOrReplaceUser(newUser);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#authenticate(java.lang.String, java.lang.String)
|
|
*
|
|
* @throws AccessDeniedException
|
|
* if the user credentials are not valid
|
|
*/
|
|
@Override
|
|
public Certificate authenticate(String username, String password) {
|
|
|
|
// both username and password must at least have 3 characters in length
|
|
if (username == null || username.length() < 3)
|
|
throw new PrivilegeException("The given username is shorter than 3 characters");
|
|
else if (password == null || password.length() < 3)
|
|
throw new PrivilegeException("The given password is shorter than 3 characters");
|
|
|
|
// we only work with hashed passwords
|
|
String passwordHash = this.encryptionHandler.convertToHash(password);
|
|
|
|
// get user object
|
|
User user = this.persistenceHandler.getUser(username);
|
|
// no user means no authentication
|
|
if (user == null)
|
|
throw new AccessDeniedException("There is no user defined with the credentials: " + username + " / ***...");
|
|
|
|
// validate password
|
|
String pwHash = user.getPassword();
|
|
if (pwHash == null)
|
|
throw new AccessDeniedException("User has no password and may not login!");
|
|
if (!pwHash.equals(passwordHash))
|
|
throw new AccessDeniedException("Password is incorrect for " + username + " / ***...");
|
|
|
|
// validate if user is allowed to login
|
|
if (user.getUserState() != UserState.ENABLED)
|
|
throw new AccessDeniedException("User " + username + " is not ENABLED. State is: " + user.getUserState());
|
|
|
|
// validate user has at least one role
|
|
if (user.getRoles().isEmpty()) {
|
|
throw new PrivilegeException("User " + username + " does not have any roles defined!");
|
|
}
|
|
|
|
// get 2 auth tokens
|
|
String authToken = this.encryptionHandler.nextToken();
|
|
String authPassword = this.encryptionHandler.nextToken();
|
|
|
|
// get next session id
|
|
String sessionId = nextSessionId();
|
|
|
|
// create certificate
|
|
Certificate certificate = new Certificate(sessionId, username, authToken, authPassword, user.getLocale());
|
|
|
|
// create and save a new session
|
|
Session session = new Session(sessionId, authToken, authPassword, user.getUsername(),
|
|
System.currentTimeMillis());
|
|
this.sessionMap.put(sessionId, new CertificateSessionPair(session, certificate));
|
|
|
|
// log
|
|
logger.info("Authenticated: " + session);
|
|
|
|
// return the certificate
|
|
return certificate;
|
|
}
|
|
|
|
/**
|
|
* Checks if the action is allowed by iterating the roles of the certificates user and then delegating to
|
|
* {@link #actionAllowed(Role, Restrictable)}
|
|
*
|
|
* @throws AccessDeniedException
|
|
* if the {@link Certificate} is not for a currently logged in {@link User} or if the user may not
|
|
* perform the action defined by the {@link Restrictable} implementation
|
|
*
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#actionAllowed(ch.eitchnet.privilege.model.Certificate,
|
|
* ch.eitchnet.privilege.model.Restrictable)
|
|
*/
|
|
@Override
|
|
public boolean actionAllowed(Certificate certificate, Restrictable restrictable) {
|
|
|
|
// TODO What is better, validate from {@link Restrictable} to {@link User} or the opposite direction?
|
|
|
|
// first validate certificate
|
|
if (!isCertificateValid(certificate)) {
|
|
logger.info("Certificate is not valid, so action is not allowed: " + certificate + " for restrictable: "
|
|
+ restrictable);
|
|
return false;
|
|
}
|
|
|
|
// restrictable must not be null
|
|
if (restrictable == null)
|
|
throw new PrivilegeException("Restrictable may not be null!");
|
|
|
|
// get user object
|
|
User user = this.persistenceHandler.getUser(certificate.getUsername());
|
|
if (user == null) {
|
|
throw new PrivilegeException(
|
|
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
|
|
}
|
|
|
|
// default is to not allow the action
|
|
// TODO should default deny/allow policy be configurable?
|
|
boolean actionAllowed = false;
|
|
|
|
// now iterate roles and validate on policies
|
|
for (String roleName : user.getRoles()) {
|
|
|
|
Role role = this.persistenceHandler.getRole(roleName);
|
|
if (role == null) {
|
|
logger.error("No role is defined with name " + roleName + " which is configured for user " + user);
|
|
continue;
|
|
}
|
|
|
|
actionAllowed = actionAllowed(role, restrictable);
|
|
|
|
// if action is allowed, then break iteration as a privilege match has been made
|
|
if (actionAllowed)
|
|
break;
|
|
}
|
|
|
|
return actionAllowed;
|
|
}
|
|
|
|
/**
|
|
* Checks if the {@link RoleRep} has access to the {@link Restrictable} by delegating to
|
|
* {@link PrivilegePolicy#actionAllowed(Role, Privilege, Restrictable)}
|
|
*
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#actionAllowed(ch.eitchnet.privilege.model.RoleRep,
|
|
* ch.eitchnet.privilege.model.Restrictable)
|
|
*/
|
|
@Override
|
|
public boolean actionAllowed(RoleRep roleRep, Restrictable restrictable) {
|
|
|
|
// user and restrictable must not be null
|
|
if (roleRep == null)
|
|
throw new PrivilegeException("Role may not be null!");
|
|
else if (restrictable == null)
|
|
throw new PrivilegeException("Restrictable may not be null!");
|
|
|
|
// get role for the roleRep
|
|
Role role = this.persistenceHandler.getRole(roleRep.getName());
|
|
|
|
// validate that the role exists
|
|
if (role == null) {
|
|
throw new PrivilegeException("No Role exists with the name " + roleRep.getName());
|
|
}
|
|
|
|
return actionAllowed(role, restrictable);
|
|
}
|
|
|
|
/**
|
|
* Checks if the {@link Role} has access to the {@link Restrictable} by delegating to
|
|
* {@link PrivilegePolicy#actionAllowed(Role, Privilege, Restrictable)}
|
|
*
|
|
* @param role
|
|
* @param restrictable
|
|
*
|
|
* @return true if the privilege is granted, false otherwise
|
|
*/
|
|
protected boolean actionAllowed(Role role, Restrictable restrictable) {
|
|
|
|
// validate PrivilegeName for this restrictable
|
|
String privilegeName = restrictable.getPrivilegeName();
|
|
if (privilegeName == null || privilegeName.length() < 3) {
|
|
throw new PrivilegeException(
|
|
"The PrivilegeName may not be shorter than 3 characters. Invalid Restrictable "
|
|
+ restrictable.getClass().getName());
|
|
}
|
|
|
|
// If the role does not have this privilege, then stop as another role might have this privilege
|
|
if (!role.hasPrivilege(privilegeName)) {
|
|
return false;
|
|
}
|
|
|
|
// get the privilege for this restrictable
|
|
Privilege privilege = this.persistenceHandler.getPrivilege(privilegeName);
|
|
if (privilege == null) {
|
|
throw new PrivilegeException("No Privilege exists with the name " + privilegeName + " for Restrictable "
|
|
+ restrictable.getClass().getName());
|
|
}
|
|
|
|
// get the policy configured for this privilege
|
|
PrivilegePolicy policy = this.getPolicy(privilege.getPolicy());
|
|
if (policy == null) {
|
|
throw new PrivilegeException("PrivilegePolicy " + privilege.getPolicy() + " does not exist for Privilege "
|
|
+ privilegeName);
|
|
}
|
|
|
|
// delegate checking to privilege policy
|
|
return policy.actionAllowed(role, privilege, restrictable);
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#isCertificateValid(ch.eitchnet.privilege.model.Certificate)
|
|
*/
|
|
@Override
|
|
public boolean isCertificateValid(Certificate certificate) {
|
|
|
|
// certificate must not be null
|
|
if (certificate == null)
|
|
throw new PrivilegeException("Certificate may not be null!");
|
|
|
|
// first see if a session exists for this certificate
|
|
CertificateSessionPair certificateSessionPair = this.sessionMap.get(certificate.getSessionId());
|
|
if (certificateSessionPair == null)
|
|
throw new AccessDeniedException("There is no session information for " + certificate.toString());
|
|
|
|
// validate certificate has not been tampered with
|
|
Certificate sessionCertificate = certificateSessionPair.certificate;
|
|
if (!sessionCertificate.equals(certificate))
|
|
throw new PrivilegeException("Received illegal certificate for session id " + certificate.getSessionId());
|
|
|
|
// TODO is validating authToken overkill since the two certificates have already been checked on equality?
|
|
// validate authToken from certificate using the sessions authPassword
|
|
String authToken = certificate.getAuthToken(certificateSessionPair.session.getAuthPassword());
|
|
if (authToken == null || !authToken.equals(certificateSessionPair.session.getAuthToken()))
|
|
throw new PrivilegeException("Received illegal certificate data for session id "
|
|
+ certificate.getSessionId());
|
|
|
|
// get user object
|
|
User user = this.persistenceHandler.getUser(certificateSessionPair.session.getUsername());
|
|
|
|
// if user exists, then certificate is valid
|
|
if (user == null) {
|
|
throw new PrivilegeException(
|
|
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
|
|
}
|
|
|
|
// everything is ok, so return true as the certificate must be valid
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#validateIsPrivilegeAdmin(ch.eitchnet.privilege.model.Certificate)
|
|
*/
|
|
@Override
|
|
public void validateIsPrivilegeAdmin(Certificate certificate) throws PrivilegeException {
|
|
|
|
// validate certificate
|
|
if (!this.isCertificateValid(certificate)) {
|
|
throw new PrivilegeException("Certificate " + certificate + " is not valid!");
|
|
}
|
|
|
|
// get user object
|
|
User user = this.persistenceHandler.getUser(certificate.getUsername());
|
|
if (user == null) {
|
|
throw new PrivilegeException(
|
|
"Oh boy, how did this happen: No User in user map although the certificate is valid! Certificate: "
|
|
+ certificate);
|
|
}
|
|
|
|
// validate user has PrivilegeAdmin role
|
|
if (!user.hasRole(PrivilegeHandler.PRIVILEGE_ADMIN_ROLE)) {
|
|
throw new AccessDeniedException("User does not have " + PrivilegeHandler.PRIVILEGE_ADMIN_ROLE
|
|
+ " role! Certificate: " + certificate);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This simple implementation validates that the password is not null, and that the password string is not empty
|
|
*
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#validatePassword(java.lang.String)
|
|
*/
|
|
@Override
|
|
public void validatePassword(String password) throws PrivilegeException {
|
|
|
|
if (password == null || password.isEmpty()) {
|
|
throw new PrivilegeException("A password may not be empty!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#persist(ch.eitchnet.privilege.model.Certificate)
|
|
*/
|
|
@Override
|
|
public boolean persist(Certificate certificate) {
|
|
|
|
// validate who is doing this
|
|
validateIsPrivilegeAdmin(certificate);
|
|
|
|
return this.persistenceHandler.persist();
|
|
}
|
|
|
|
/**
|
|
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#initialize(java.util.Map,
|
|
* ch.eitchnet.privilege.handler.EncryptionHandler, ch.eitchnet.privilege.handler.PersistenceHandler)
|
|
*/
|
|
@Override
|
|
public void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
|
PersistenceHandler persistenceHandler) {
|
|
|
|
this.encryptionHandler = encryptionHandler;
|
|
this.persistenceHandler = persistenceHandler;
|
|
|
|
lastSessionId = 0l;
|
|
this.sessionMap = new HashMap<String, CertificateSessionPair>();
|
|
}
|
|
|
|
/**
|
|
* @return a new session id
|
|
*/
|
|
private synchronized String nextSessionId() {
|
|
return Long.toString(++lastSessionId % Long.MAX_VALUE);
|
|
}
|
|
|
|
/**
|
|
* An internal class used to keep a record of sessions with the certificate
|
|
*
|
|
* @author rvonburg
|
|
*/
|
|
private class CertificateSessionPair {
|
|
/**
|
|
* The {@link Session}
|
|
*/
|
|
public final Session session;
|
|
/**
|
|
* The {@link Certificate}
|
|
*/
|
|
public final Certificate certificate;
|
|
|
|
/**
|
|
* Creates a new {@link CertificateSessionPair} with the given session and certificate
|
|
*
|
|
* @param session
|
|
* the session
|
|
* @param certificate
|
|
* the certificate
|
|
*/
|
|
public CertificateSessionPair(Session session, Certificate certificate) {
|
|
this.session = session;
|
|
this.certificate = certificate;
|
|
}
|
|
}
|
|
|
|
}
|