/**
* (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
*
* 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
*/
package org.jabylon.security.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.eclipse.emf.cdo.view.CDOView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jabylon.cdo.server.ServerConstants;
import org.jabylon.security.CommonPermissions;
import org.jabylon.security.JabylonSecurityBundle;
import org.jabylon.security.SubjectAttribute;
import org.jabylon.users.Permission;
import org.jabylon.users.User;
import org.jabylon.users.UserManagement;
import org.jabylon.users.UsersPackage;
public class DBLoginModule implements LoginModule {
static final String EMPTY_STRING = "";
Subject subj;
CallbackHandler cbHandler;
boolean authenticated = false;
String user;
String pw;
List<Permission> permissions = new ArrayList<Permission>();
private static final Logger logger = LoggerFactory.getLogger(DBLoginModule.class);
public DBLoginModule() {
}
@Override
public boolean abort() throws LoginException {
this.authenticated = false;
return true;
}
@Override
public boolean commit() throws LoginException {
if (this.authenticated) {
subj.getPublicCredentials().add(user);
addPermissions(subj.getPrivateCredentials());
} else {
subj.getPublicCredentials().remove(user);
subj.getPrivateCredentials().removeAll(permissions);
permissions = new ArrayList<Permission>();
return false;
}
return true;
}
private void addPermissions(Set<Object> privateCredentials) {
for (Permission permission : permissions) {
privateCredentials.add(permission);
}
}
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
this.subj = subject;
this.cbHandler = callbackHandler;
}
@Override
public boolean login() throws LoginException {
NameCallback nameCallback = new NameCallback("User:");
PasswordCallback passwordCallback = new PasswordCallback("Password:", false);
try {
cbHandler.handle(new Callback[] { nameCallback, passwordCallback });
} catch (Exception e) {
logger.error("Login failed", e);
}
user = nameCallback.getName();
pw = EMPTY_STRING;
if (passwordCallback.getPassword() != null) {
pw = String.valueOf(passwordCallback.getPassword());
}
this.authenticated = checkLogin(user, pw);
return this.authenticated;
}
private boolean checkLogin(String userName, String pw) {
if (JabylonSecurityBundle.getRepositoryConnector() == null)
return false;
CDOView view = JabylonSecurityBundle.getRepositoryConnector().openView();
try {
boolean valid = false;
User user = null;
UserManagement userManagement = (UserManagement) view.getResource(ServerConstants.USERS_RESOURCE).getContents().get(0);
if (userName == null || userName.isEmpty()) {
// it's an auth token
user = userManagement.findUserByToken(pw);
if (user != null) {
this.user = user.getName();
valid = true;
}
} else {
user = userManagement.findUserByName(userName);
valid = pw != null && !pw.isEmpty() && user!=null && pw.equals(user.getPassword());
if(valid && !CommonPermissions.AUTH_TYPE_DB.equals(user.getType())) {
logger.warn("User {} does not have the auth type DB set");
subj.getPublicCredentials().add(new SubjectAttribute(UsersPackage.Literals.USER__TYPE, CommonPermissions.AUTH_TYPE_DB));
}
}
if (user == null || !valid) {
logger.info("DB Login failed for user {}", userName);
return false;
}
permissions = user.getAllPermissions();
logger.info("DB Login for user {} successful", userName);
return true;
} catch (Exception e) {
logger.error("Login failed", e);
return false;
} finally {
view.close();
}
}
@Override
public boolean logout() throws LoginException {
this.authenticated = false;
return true;
}
}