// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.ldap;
import java.util.Map;
import java.util.UUID;
import javax.inject.Inject;
import org.apache.cloudstack.acl.RoleType;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
public class LdapAuthenticator extends AdapterBase implements UserAuthenticator {
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
@Inject
private LdapManager _ldapManager;
@Inject
private UserAccountDao _userAccountDao;
@Inject
private AccountManager _accountManager;
public LdapAuthenticator() {
super();
}
public LdapAuthenticator(final LdapManager ldapManager, final UserAccountDao userAccountDao) {
super();
_ldapManager = ldapManager;
_userAccountDao = userAccountDao;
}
@Override
public Pair<Boolean, ActionOnFailedAuthentication> authenticate(final String username, final String password, final Long domainId, final Map<String, Object[]> requestParameters) {
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
s_logger.debug("Username or Password cannot be empty");
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
}
boolean result = false;
ActionOnFailedAuthentication action = null;
if (_ldapManager.isLdapEnabled()) {
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
LdapTrustMapVO ldapTrustMapVO = _ldapManager.getDomainLinkedToLdap(domainId);
if(ldapTrustMapVO != null) {
try {
LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName());
if(!ldapUser.isDisabled()) {
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
if(result) {
if(user == null) {
// import user to cloudstack
createCloudStackUserAccount(ldapUser, domainId, ldapTrustMapVO.getAccountType());
} else {
enableUserInCloudStack(user);
}
}
} else {
//disable user in cloudstack
disableUserInCloudStack(user);
}
} catch (NoLdapUserMatchingQueryException e) {
s_logger.debug(e.getMessage());
}
} else {
//domain is not linked to ldap follow normal authentication
if(user != null ) {
try {
LdapUser ldapUser = _ldapManager.getUser(username);
if(!ldapUser.isDisabled()) {
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
} else {
s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
}
} catch (NoLdapUserMatchingQueryException e) {
s_logger.debug(e.getMessage());
}
}
}
if (!result && user != null) {
action = ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT;
}
}
return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
}
private void enableUserInCloudStack(UserAccount user) {
if(user != null && (user.getState().equalsIgnoreCase(Account.State.disabled.toString()))) {
_accountManager.enableUser(user.getId());
}
}
private void createCloudStackUserAccount(LdapUser user, long domainId, short accountType) {
String username = user.getUsername();
_accountManager.createUserAccount(username, "", user.getFirstname(), user.getLastname(), user.getEmail(), null, username,
accountType, RoleType.getByAccountType(accountType).getId(), domainId, null, null,
UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
}
private void disableUserInCloudStack(UserAccount user) {
if (user != null) {
_accountManager.disableUser(user.getId());
}
}
@Override
public String encode(final String password) {
return password;
}
}