blob: 96cc36be27998f4ef6dc7d1c92f231e32f3ef718 [file] [log] [blame]
/*
* Copyright (c) 2020 Kentyou.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentyou - initial API and implementation
*/
package org.eclipse.sensinact.gateway.core.security.impl;
import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.util.HashMap;
import org.eclipse.sensinact.gateway.common.bundle.Mediator;
import org.eclipse.sensinact.gateway.core.security.AuthenticationService;
import org.eclipse.sensinact.gateway.core.security.Credentials;
import org.eclipse.sensinact.gateway.core.security.InvalidCredentialException;
import org.eclipse.sensinact.gateway.core.security.SecuredAccessException;
import org.eclipse.sensinact.gateway.core.security.SecurityDataStoreService;
import org.eclipse.sensinact.gateway.core.security.User;
import org.eclipse.sensinact.gateway.core.security.UserKey;
import org.eclipse.sensinact.gateway.core.security.UserManager;
import org.eclipse.sensinact.gateway.core.security.UserUpdater;
import org.eclipse.sensinact.gateway.core.security.dao.DAOException;
import org.eclipse.sensinact.gateway.core.security.dao.UserDAO;
import org.eclipse.sensinact.gateway.core.security.entity.UserEntity;
import org.eclipse.sensinact.gateway.datastore.api.DataStoreException;
import org.eclipse.sensinact.gateway.util.CryptoUtils;
import org.osgi.framework.ServiceReference;
/**
*
* @author <a href="mailto:christophe.munilla@cea.fr">Christophe Munilla</a>
*/
public class UserManagerImpl implements UserManager, AuthenticationService {
private Mediator mediator;
private UserDAO userDAO;
private UserEntity anonymous;
/**
*
* @param mediator
* @throws DataStoreException
* @throws DAOException
*
*/
public UserManagerImpl(Mediator mediator) throws SecuredAccessException {
this.mediator = mediator;
try {
ServiceReference<SecurityDataStoreService> reference = this.mediator.getContext()
.getServiceReference(SecurityDataStoreService.class);
this.userDAO = new UserDAO(mediator, this.mediator.getContext().getService(reference));
anonymous = userDAO.find(ANONYMOUS_ID);
} catch (DataStoreException | NullPointerException | IllegalArgumentException e) {
mediator.error(e);
throw new SecuredAccessException(e);
}
}
/**
* @inheritDoc
*
* @see java.lang.Object#finalize()
*/
public void finalize() {
this.userDAO = null;
try {
ServiceReference<SecurityDataStoreService> reference = this.mediator.getContext()
.getServiceReference(SecurityDataStoreService.class);
this.mediator.getContext().ungetService(reference);
} catch (NullPointerException | IllegalArgumentException e) {
mediator.error(e);
}
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#
* loginExists(java.lang.String)
*/
@Override
public boolean loginExists(final String login) throws SecuredAccessException, DataStoreException {
return this.userDAO.select(new HashMap<String, Object>() {
{
this.put("SULOGIN", login);
}
}).size()>0;
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#
* accountExists(java.lang.String, java.lang.String)
*/
@Override
public boolean accountExists(String account) throws SecuredAccessException, DataStoreException {
return this.userDAO.findFromAccount(account) != null;
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#
* getUser(java.lang.String, java.lang.String)
*/
@Override
public User getUser(String login, String password) throws SecuredAccessException, DataStoreException {
return userDAO.find(login, password);
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#
* getUserFromPublicKey(java.lang.String)
*/
@Override
public User getUserFromPublicKey(String publicKey) throws SecuredAccessException, DataStoreException {
if (publicKey == null) {
return anonymous;
}
return userDAO.find(publicKey);
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#
* getUserFromAccount(java.lang.String)
*/
@Override
public User getUserFromAccount(String account) throws SecuredAccessException, DataStoreException {
if (account == null) {
return anonymous;
}
return userDAO.findFromAccount(account);
}
/**
* @inheritDoc
*
* @see AuthenticationService#buildKey(Credentials)
*/
@Override
public UserKey buildKey(Credentials credentials) throws InvalidKeyException, DAOException, InvalidCredentialException, DataStoreException {
if(Credentials.ANONYMOUS_LOGIN.equals(credentials.login) && Credentials.ANONYMOUS_PASSWORD.equals(credentials.password)) {
return null;
}
String md5 = CryptoUtils.cryptWithMD5(credentials.password);
UserEntity userEntity = this.userDAO.find(credentials.login, md5);
if (userEntity == null) {
return null;
} else {
return new UserKey(userEntity.getPublicKey());
}
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#createUser(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public UserUpdater createUser(String token, final String login, final String password, final String account, final String accountType) throws SecuredAccessException {
return new AbstractUserUpdater(mediator, token, "create") {
@Override
public String getAccount() {
return account;
}
@Override
public String getAccountType() {
return accountType;
}
@Override
protected String doUpdate() throws SecuredAccessException {
String publicKey = null;
String publicKeyStr = new StringBuilder().append(login).append(":").append(account
).append(System.currentTimeMillis()).toString();
try {
publicKey = CryptoUtils.cryptWithMD5(publicKeyStr);
UserEntity user = new UserEntity(mediator, login, password, account, accountType,
publicKey);
UserManagerImpl.this.userDAO.create(user);
return new StringBuilder().append("Public Key : ").append(publicKey).toString();
} catch(DAOException | DataStoreException | InvalidKeyException e) {
throw new SecuredAccessException(e);
}
}
};
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#renewUserPassword(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public UserUpdater renewUserPassword(String token, final String account, final String accountType) throws SecuredAccessException {
return new AbstractUserUpdater(mediator, token, "renew") {
static final String ALPHABET = ".!0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@Override
public String getAccount() {
return account;
}
@Override
public String getAccountType() {
return accountType;
}
@Override
protected String doUpdate() throws SecuredAccessException {
try {
User user = UserManagerImpl.this.getUserFromAccount(account);
StringBuilder builder = new StringBuilder();
do {
String millis = String.valueOf(System.currentTimeMillis());
for(int i=millis.length()-1;i>6;i--) {
int val = Integer.parseInt(millis.substring(i-1, i+1));
int hval = Integer.parseInt(millis.substring(i-1, i+1),16);
int index = -1;
if((index = ALPHABET.indexOf(val))>-1){
builder.append(ALPHABET.substring(index, index+1));
} else if((index = ALPHABET.indexOf(hval))>-1){
builder.append(ALPHABET.substring(index, index+1));
} else if(val < millis.length()) {
builder.append(ALPHABET.substring(val, val+1));
}else if(hval < millis.length()) {
builder.append(ALPHABET.substring(hval, hval+1));
}
}
Thread.sleep(345);
}while(builder.length() <= 10);
String password = builder.toString();
String encryptedPassword = CryptoUtils.cryptWithMD5(password);
((UserEntity)user).setPassword(encryptedPassword);
UserManagerImpl.this.userDAO.update((UserEntity) user);
return new StringBuilder().append("Your new password : ").append(password).toString();
} catch(DAOException | DataStoreException | InvalidKeyException | InterruptedException e) {
throw new SecuredAccessException(e);
}
}
};
}
/**
* @inheritDoc
*
* @see org.eclipse.sensinact.gateway.core.security.UserManager#updateField(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void updateField(User user, String fieldName, Object oldValue, Object newValue) throws SecuredAccessException {
try {
Class<? extends User> clazz = user.getClass();
String getPrefix = "get";
String setPrefix = "set";
String suffix = new StringBuilder().append(fieldName.substring(0, 1
).toUpperCase()).append(fieldName.substring(1)).toString();
Method getMethod = clazz.getMethod(new StringBuilder().append(getPrefix).append(suffix
).toString());
Object current = getMethod.invoke(user);
if((current==null && oldValue!=null)||(current!=null && !current.equals(oldValue))){
throw new SecuredAccessException("Invalid current value");
}
Method setMethod = clazz.getMethod(new StringBuilder().append(setPrefix).append(suffix
).toString(), newValue.getClass());
setMethod.invoke(user, newValue);
} catch (Exception e) {
throw new SecuredAccessException(e);
}
}
}