mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
Ticket #269: Continuing work, more work on UserMapping and UserDirectory
This commit is contained in:
@@ -94,6 +94,17 @@
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.collections</groupId>
|
||||
<artifactId>google-collections</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-mysql</artifactId>
|
||||
<version>0.8.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
@@ -52,6 +52,10 @@ import net.sourceforge.guacamole.net.auth.mysql.dao.guacamole.SystemPermissionMa
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.guacamole.UserMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.guacamole.UserPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.PasswordEncryptionUtility;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.SaltUtility;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.SecureRandomSaltUtility;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.Sha256PasswordEncryptionUtility;
|
||||
import net.sourceforge.guacamole.properties.GuacamoleProperties;
|
||||
import org.mybatis.guice.MyBatisModule;
|
||||
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
|
||||
@@ -105,6 +109,9 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
|
||||
addMapperClass(UserMapper.class);
|
||||
addMapperClass(UserPermissionMapper.class);
|
||||
bind(MySQLUserContext.class);
|
||||
bind(MySQLUser.class);
|
||||
bind(SaltUtility.class).to(SecureRandomSaltUtility.class);
|
||||
bind(PasswordEncryptionUtility.class).to(Sha256PasswordEncryptionUtility.class);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -35,65 +35,116 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.sourceforge.guacamole.GuacamoleException;
|
||||
import net.sourceforge.guacamole.net.auth.Credentials;
|
||||
import net.sourceforge.guacamole.net.auth.User;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.guacamole.UserMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.guacamole.UserExample;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.PasswordEncryptionUtility;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.utility.SaltUtility;
|
||||
import net.sourceforge.guacamole.net.auth.permission.Permission;
|
||||
|
||||
/**
|
||||
*
|
||||
* A MySQL based implementation of the User object.
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class MySQLUser implements User {
|
||||
|
||||
private String username;
|
||||
private String userID;
|
||||
private String salt;
|
||||
private net.sourceforge.guacamole.net.auth.mysql.model.guacamole.User user;
|
||||
|
||||
MySQLUser(Credentials credentials) {
|
||||
//TODO: load the user from the DB if the credentials are correct,
|
||||
// otherwise, throw some kind of exception
|
||||
@Inject
|
||||
UserMapper userDao;
|
||||
|
||||
@Inject
|
||||
PasswordEncryptionUtility passwordUtility;
|
||||
|
||||
@Inject
|
||||
SaltUtility saltUtility;
|
||||
|
||||
Set<Permission> permissions;
|
||||
|
||||
MySQLUser() {
|
||||
user = new net.sourceforge.guacamole.net.auth.mysql.model.guacamole.User();
|
||||
permissions = new HashSet<Permission>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the user, throwing an exception if the credentials do not match what's in the database.
|
||||
* @param credentials
|
||||
* @throws GuacamoleException
|
||||
*/
|
||||
void init (Credentials credentials) throws GuacamoleException {
|
||||
UserExample userExample = new UserExample();
|
||||
userExample.createCriteria().andUsernameEqualTo(credentials.getUsername());
|
||||
List<net.sourceforge.guacamole.net.auth.mysql.model.guacamole.User> users = userDao.selectByExample(userExample);
|
||||
if(users.size() > 1) // the unique constraint on the table should prevent this
|
||||
throw new GuacamoleException("Multiple users found with the same username: " + credentials.getUsername());
|
||||
if(users.isEmpty())
|
||||
throw new GuacamoleException("No user found with the supplied credentials");
|
||||
user = users.get(0);
|
||||
// check password
|
||||
if(!passwordUtility.checkCredentials(credentials, user.getPassword_hash(), user.getUsername(), user.getPassword_salt()))
|
||||
throw new GuacamoleException("No user found with the supplied credentials");
|
||||
}
|
||||
|
||||
void init (User user) {
|
||||
this.setPassword(user.getPassword());
|
||||
this.setUsername(user.getUsername());
|
||||
}
|
||||
|
||||
public net.sourceforge.guacamole.net.auth.mysql.model.guacamole.User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
user.setUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
try {
|
||||
return new String(user.getPassword_hash(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
throw new RuntimeException(ex); // should not happen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassword(String password) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
String salt = saltUtility.generateSalt();
|
||||
user.setPassword_salt(salt);
|
||||
byte[] hash = passwordUtility.createPasswordHash(password, salt);
|
||||
user.setPassword_hash(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Permission> getPermissions() throws GuacamoleException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) throws GuacamoleException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
return permissions.contains(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(Permission permission) throws GuacamoleException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
permissions.add(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermission(Permission permission) throws GuacamoleException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
permissions.remove(permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -53,13 +53,16 @@ public class MySQLUserContext implements UserContext {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(MySQLUserContext.class);
|
||||
|
||||
void init(Credentials credentials) {
|
||||
// load the required data with the provided credentials
|
||||
@Inject
|
||||
private MySQLUser user;
|
||||
|
||||
void init(Credentials credentials) throws GuacamoleException {
|
||||
user.init(credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User self() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.sourceforge.guacamole.GuacamoleException;
|
||||
import net.sourceforge.guacamole.net.auth.Directory;
|
||||
import net.sourceforge.guacamole.net.auth.User;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.guacamole.UserMapper;
|
||||
|
||||
/**
|
||||
* A MySQL based implementation of the User Directory.
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class UserDirectory implements Directory<String, User> {
|
||||
|
||||
private Map<String, User> userMap = new HashMap<String, User>();
|
||||
|
||||
@Inject
|
||||
UserMapper userDAO;
|
||||
|
||||
@Inject
|
||||
Provider<MySQLUser> mySQLUserProvider;
|
||||
|
||||
private MySQLUser getMySQLUser(User user) {
|
||||
MySQLUser mySQLUser = mySQLUserProvider.get();
|
||||
mySQLUser.init(user);
|
||||
return mySQLUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User get(String identifier) throws GuacamoleException {
|
||||
return userMap.get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
return userMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(User object) throws GuacamoleException {
|
||||
MySQLUser mySQLUser = getMySQLUser(object);
|
||||
userDAO.insert(mySQLUser.getUser());
|
||||
userMap.put(mySQLUser.getUsername(), mySQLUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(User object) throws GuacamoleException {
|
||||
if(!userMap.containsKey(object.getUsername()))
|
||||
throw new GuacamoleException("User not found in Directory.");
|
||||
MySQLUser mySQLUser = getMySQLUser(object);
|
||||
userDAO.updateByPrimaryKey(mySQLUser.getUser());
|
||||
userMap.put(object.getUsername(), mySQLUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
User user = userMap.get(identifier);
|
||||
if(user == null)
|
||||
throw new GuacamoleException("User not found in Directory.");
|
||||
MySQLUser mySQLUser = getMySQLUser(user);
|
||||
userDAO.deleteByPrimaryKey(mySQLUser.getUser().getUser_id());
|
||||
userMap.remove(user.getUsername());
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is guacamole-auth-mysql.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* James Muehlner.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
package net.sourceforge.guacamole.net.auth.mysql.utility;
|
||||
|
||||
import net.sourceforge.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public interface PasswordEncryptionUtility {
|
||||
|
||||
/**
|
||||
* Checks if the provided Credentials are correct, compared with what the values from the database.
|
||||
* @param credentials
|
||||
* @param dbPasswordHash
|
||||
* @param dbUsername
|
||||
* @param dbSalt
|
||||
* @return true if the provided credentials match what's in the database for that user.
|
||||
*/
|
||||
public boolean checkCredentials(Credentials credentials, byte[] dbPasswordHash, String dbUsername, String dbSalt);
|
||||
|
||||
/**
|
||||
* Creates a password hash based on the provided username, password, and salt.
|
||||
* @param username
|
||||
* @param password
|
||||
* @param salt
|
||||
* @return the generated password hash.
|
||||
*/
|
||||
public byte[] createPasswordHash(String password, String salt);
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is guacamole-auth-mysql.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* James Muehlner.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
package net.sourceforge.guacamole.net.auth.mysql.utility;
|
||||
|
||||
import net.sourceforge.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public interface SaltUtility {
|
||||
/**
|
||||
* Generates a new String that can be used as a password salt.
|
||||
* @return a new salt for password encryption.
|
||||
*/
|
||||
public String generateSalt();
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package net.sourceforge.guacamole.net.auth.mysql.utility;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* Generates password salts via the SecureRandom utility.
|
||||
* @author dagger10k
|
||||
*/
|
||||
public class SecureRandomSaltUtility implements SaltUtility {
|
||||
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
byte[] salt = new byte[32];
|
||||
secureRandom.nextBytes(salt);
|
||||
try {
|
||||
return new String(salt, "UTF-8");
|
||||
} catch (UnsupportedEncodingException ex) { // should not happen
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is guacamole-auth-mysql.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* James Muehlner.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
package net.sourceforge.guacamole.net.auth.mysql.utility;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import net.sourceforge.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
* Provides a SHA-256 based implementation of the password encryption functionality.
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class Sha256PasswordEncryptionUtility implements PasswordEncryptionUtility {
|
||||
|
||||
@Override
|
||||
public boolean checkCredentials(Credentials credentials, byte[] dbPasswordHash, String dbUsername, String dbSalt) {
|
||||
Preconditions.checkNotNull(credentials);
|
||||
Preconditions.checkNotNull(dbPasswordHash);
|
||||
Preconditions.checkNotNull(dbUsername);
|
||||
Preconditions.checkNotNull(dbSalt);
|
||||
byte[] passwordBytes = createPasswordHash(credentials.getPassword(), dbSalt);
|
||||
return Arrays.equals(passwordBytes, dbPasswordHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] createPasswordHash(String password, String salt) {
|
||||
Preconditions.checkNotNull(password);
|
||||
Preconditions.checkNotNull(salt);
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(password);
|
||||
builder.append(salt);
|
||||
md.update(builder.toString().getBytes("UTF-8"));
|
||||
return md.digest();
|
||||
} catch (UnsupportedEncodingException ex) { // should not happen
|
||||
throw new RuntimeException(ex);
|
||||
} catch (NoSuchAlgorithmException ex) { // should not happen
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user