use of com.novell.ldapchai.provider.DirectoryVendor in project pwm by pwm-project.
the class LDAPAuthenticationRequest method authenticateUserImpl.
private AuthenticationResult authenticateUserImpl(final PasswordData password) throws ChaiUnavailableException, PwmUnrecoverableException, PwmOperationalException {
if (startTime == null) {
startTime = new Date();
}
log(PwmLogLevel.DEBUG, "preparing to authenticate user using authenticationType=" + this.requestedAuthType + " using strategy " + this.strategy);
final StatisticsManager statisticsManager = pwmApplication.getStatisticsManager();
final IntruderManager intruderManager = pwmApplication.getIntruderManager();
intruderManager.convenience().checkUserIdentity(userIdentity);
intruderManager.check(RecordType.ADDRESS, sessionLabel.getSrcAddress());
// verify user is not account disabled
AuthenticationUtility.checkIfUserEligibleToAuthentication(pwmApplication, userIdentity);
boolean allowBindAsUser = true;
if (strategy == AuthenticationStrategy.ADMIN_PROXY) {
allowBindAsUser = false;
}
if (allowBindAsUser) {
try {
testCredentials(userIdentity, password);
} catch (PwmOperationalException e) {
boolean permitAuthDespiteError = false;
final DirectoryVendor vendor = pwmApplication.getProxyChaiProvider(userIdentity.getLdapProfileID()).getDirectoryVendor();
if (PwmError.PASSWORD_NEW_PASSWORD_REQUIRED == e.getError()) {
if (vendor == DirectoryVendor.ACTIVE_DIRECTORY) {
if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.AD_ALLOW_AUTH_REQUIRE_NEW_PWD)) {
log(PwmLogLevel.INFO, "auth bind failed, but will allow login due to 'must change password on next login AD error', error: " + e.getErrorInformation().toDebugStr());
allowBindAsUser = false;
permitAuthDespiteError = true;
}
} else if (vendor == DirectoryVendor.ORACLE_DS) {
if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.ORACLE_DS_ALLOW_AUTH_REQUIRE_NEW_PWD)) {
log(PwmLogLevel.INFO, "auth bind failed, but will allow login due to 'pwdReset' user attribute, error: " + e.getErrorInformation().toDebugStr());
allowBindAsUser = false;
permitAuthDespiteError = true;
}
}
} else if (PwmError.PASSWORD_EXPIRED == e.getError()) {
// handle ad case where password is expired
if (vendor == DirectoryVendor.ACTIVE_DIRECTORY) {
if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.AD_ALLOW_AUTH_REQUIRE_NEW_PWD)) {
if (!pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.AD_ALLOW_AUTH_EXPIRED)) {
throw e;
}
log(PwmLogLevel.INFO, "auth bind failed, but will allow login due to 'password expired AD error', error: " + e.getErrorInformation().toDebugStr());
allowBindAsUser = false;
permitAuthDespiteError = true;
}
}
}
if (!permitAuthDespiteError) {
// auth failed, presumably due to wrong password.
statisticsManager.incrementValue(Statistic.AUTHENTICATION_FAILURES);
throw e;
}
}
}
statisticsManager.incrementValue(Statistic.AUTHENTICATIONS);
statisticsManager.updateEps(EpsStatistic.AUTHENTICATION, 1);
statisticsManager.updateAverageValue(Statistic.AVG_AUTHENTICATION_TIME, TimeDuration.fromCurrent(startTime).getTotalMilliseconds());
final AuthenticationType returnAuthType;
if (!allowBindAsUser) {
returnAuthType = AuthenticationType.AUTH_BIND_INHIBIT;
} else {
if (requestedAuthType == null) {
returnAuthType = AuthenticationType.AUTHENTICATED;
} else {
if (requestedAuthType == AuthenticationType.AUTH_WITHOUT_PASSWORD) {
returnAuthType = AuthenticationType.AUTHENTICATED;
} else if (requestedAuthType == AuthenticationType.AUTH_FROM_PUBLIC_MODULE) {
returnAuthType = AuthenticationType.AUTH_FROM_PUBLIC_MODULE;
} else {
returnAuthType = requestedAuthType;
}
}
}
final boolean useProxy = determineIfLdapProxyNeeded(returnAuthType, password);
final ChaiProvider returnProvider = useProxy ? makeProxyProvider() : userProvider;
final AuthenticationResult authenticationResult = new AuthenticationResult(returnProvider, returnAuthType, password);
final StringBuilder debugMsg = new StringBuilder();
debugMsg.append("successful ldap authentication for ").append(userIdentity);
debugMsg.append(" (").append(TimeDuration.fromCurrent(startTime).asCompactString()).append(")");
debugMsg.append(" type: ").append(returnAuthType).append(", using strategy ").append(strategy);
debugMsg.append(", using proxy connection: ").append(useProxy);
debugMsg.append(", returning bind dn: ").append(returnProvider == null ? "none" : returnProvider.getChaiConfiguration().getSetting(ChaiSetting.BIND_DN));
log(PwmLogLevel.INFO, debugMsg);
final MacroMachine macroMachine = MacroMachine.forUser(pwmApplication, PwmConstants.DEFAULT_LOCALE, sessionLabel, userIdentity);
final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication, macroMachine).createUserAuditRecord(AuditEvent.AUTHENTICATE, this.userIdentity, makeAuditLogMessage(returnAuthType), sessionLabel.getSrcAddress(), sessionLabel.getSrcHostname());
pwmApplication.getAuditManager().submit(auditRecord);
pwmApplication.getSessionTrackService().addRecentLogin(userIdentity);
return authenticationResult;
}
use of com.novell.ldapchai.provider.DirectoryVendor in project pwm by pwm-project.
the class SchemaManager method implForChaiProvider.
protected static SchemaExtender implForChaiProvider(final ChaiProvider chaiProvider) throws PwmUnrecoverableException {
if (!chaiProvider.isConnected()) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, "provider is not connected"));
}
try {
if (chaiProvider.getDirectoryVendor() != DirectoryVendor.EDIRECTORY) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, "directory vendor is not supported"));
}
final List<String> urls = chaiProvider.getChaiConfiguration().bindURLsAsList();
if (urls.size() > 1) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, "provider used for schema extension must have only a single ldap url defined"));
}
final DirectoryVendor vendor = chaiProvider.getDirectoryVendor();
final Class<? extends SchemaExtender> implClass = IMPLEMENTATIONS.get(vendor);
final SchemaExtender schemaExtenderImpl = implClass.newInstance();
schemaExtenderImpl.init(chaiProvider);
return schemaExtenderImpl;
} catch (ChaiUnavailableException e) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, e.getMessage()));
} catch (Exception e) {
final String errorMsg = "error instantiating schema extender: " + e.getMessage();
LOGGER.error(errorMsg);
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg));
}
}
use of com.novell.ldapchai.provider.DirectoryVendor in project pwm by pwm-project.
the class TelemetryService method generatePublishableBean.
public TelemetryPublishBean generatePublishableBean() throws URISyntaxException, IOException, PwmUnrecoverableException {
final StatisticsBundle bundle = pwmApplication.getStatisticsManager().getStatBundleForKey(StatisticsManager.KEY_CUMULATIVE);
final Configuration config = pwmApplication.getConfig();
final Map<PwmAboutProperty, String> aboutPropertyStringMap = PwmAboutProperty.makeInfoBean(pwmApplication);
final Map<String, String> statData = new TreeMap<>();
for (final Statistic loopStat : Statistic.values()) {
statData.put(loopStat.getKey(), bundle.getStatistic(loopStat));
}
final List<String> configuredSettings = new ArrayList<>();
for (final PwmSetting pwmSetting : config.nonDefaultSettings()) {
if (!pwmSetting.getCategory().hasProfiles() && !config.isDefaultValue(pwmSetting)) {
configuredSettings.add(pwmSetting.getKey());
}
}
String ldapVendorName = null;
for (final LdapProfile ldapProfile : config.getLdapProfiles().values()) {
if (ldapVendorName == null) {
try {
final DirectoryVendor directoryVendor = ldapProfile.getProxyChaiProvider(pwmApplication).getDirectoryVendor();
final PwmLdapVendor pwmLdapVendor = PwmLdapVendor.fromChaiVendor(directoryVendor);
if (pwmLdapVendor != null) {
ldapVendorName = pwmLdapVendor.name();
}
} catch (Exception e) {
LOGGER.trace(SessionLabel.TELEMETRY_SESSION_LABEL, "unable to read ldap vendor type for stats publication: " + e.getMessage());
}
}
}
final Map<String, String> aboutStrings = new TreeMap<>();
{
for (final Map.Entry<PwmAboutProperty, String> entry : aboutPropertyStringMap.entrySet()) {
final PwmAboutProperty pwmAboutProperty = entry.getKey();
aboutStrings.put(pwmAboutProperty.name(), entry.getValue());
}
aboutStrings.remove(PwmAboutProperty.app_instanceID.name());
aboutStrings.remove(PwmAboutProperty.app_siteUrl.name());
}
final TelemetryPublishBean.TelemetryPublishBeanBuilder builder = TelemetryPublishBean.builder();
builder.timestamp(Instant.now());
builder.id(makeId(pwmApplication));
builder.instanceHash(pwmApplication.getSecureService().hash(pwmApplication.getInstanceID()));
builder.installTime(pwmApplication.getInstallTime());
builder.siteDescription(config.readSettingAsString(PwmSetting.PUBLISH_STATS_SITE_DESCRIPTION));
builder.versionBuild(PwmConstants.BUILD_NUMBER);
builder.versionVersion(PwmConstants.BUILD_VERSION);
builder.ldapVendorName(ldapVendorName);
builder.statistics(Collections.unmodifiableMap(statData));
builder.configuredSettings(Collections.unmodifiableList(configuredSettings));
builder.about(aboutStrings);
return builder.build();
}
use of com.novell.ldapchai.provider.DirectoryVendor in project pwm by pwm-project.
the class LDAPStatusChecker method checkVendorSameness.
private List<HealthRecord> checkVendorSameness(final PwmApplication pwmApplication) {
final Map<HealthMonitor.HealthMonitorFlag, Serializable> healthProperties = pwmApplication.getHealthMonitor().getHealthProperties();
if (healthProperties.containsKey(HealthMonitor.HealthMonitorFlag.LdapVendorSameCheck)) {
return (List<HealthRecord>) healthProperties.get(HealthMonitor.HealthMonitorFlag.LdapVendorSameCheck);
}
LOGGER.trace(SessionLabel.HEALTH_SESSION_LABEL, "beginning check for replica vendor sameness");
boolean errorReachingServer = false;
final Map<String, DirectoryVendor> replicaVendorMap = new HashMap<>();
try {
for (final LdapProfile ldapProfile : pwmApplication.getConfig().getLdapProfiles().values()) {
final ChaiConfiguration profileChaiConfiguration = LdapOperationsHelper.createChaiConfiguration(pwmApplication.getConfig(), ldapProfile);
final Collection<ChaiConfiguration> replicaConfigs = ChaiUtility.splitConfigurationPerReplica(profileChaiConfiguration, Collections.emptyMap());
for (final ChaiConfiguration chaiConfiguration : replicaConfigs) {
final ChaiProvider loopProvider = pwmApplication.getLdapConnectionService().getChaiProviderFactory().newProvider(chaiConfiguration);
replicaVendorMap.put(chaiConfiguration.getSetting(ChaiSetting.BIND_URLS), loopProvider.getDirectoryVendor());
}
}
} catch (Exception e) {
errorReachingServer = true;
LOGGER.error(SessionLabel.HEALTH_SESSION_LABEL, "error during replica vendor sameness check: " + e.getMessage());
}
final ArrayList<HealthRecord> healthRecords = new ArrayList<>();
final Set<DirectoryVendor> discoveredVendors = new HashSet<>(replicaVendorMap.values());
if (discoveredVendors.size() >= 2) {
final StringBuilder vendorMsg = new StringBuilder();
for (final Iterator<Map.Entry<String, DirectoryVendor>> iterator = replicaVendorMap.entrySet().iterator(); iterator.hasNext(); ) {
final Map.Entry<String, DirectoryVendor> entry = iterator.next();
final String key = entry.getKey();
vendorMsg.append(key).append("=").append(entry.getValue().toString());
if (iterator.hasNext()) {
vendorMsg.append(", ");
}
}
healthRecords.add(HealthRecord.forMessage(HealthMessage.LDAP_VendorsNotSame, vendorMsg.toString()));
// cache the error
healthProperties.put(HealthMonitor.HealthMonitorFlag.LdapVendorSameCheck, healthRecords);
LOGGER.warn(SessionLabel.HEALTH_SESSION_LABEL, "multiple ldap vendors found: " + vendorMsg.toString());
} else if (discoveredVendors.size() == 1) {
if (!errorReachingServer) {
// cache the no errors
healthProperties.put(HealthMonitor.HealthMonitorFlag.LdapVendorSameCheck, healthRecords);
}
}
return healthRecords;
}
use of com.novell.ldapchai.provider.DirectoryVendor in project pwm by pwm-project.
the class LDAPStatusChecker method checkBasicLdapConnectivity.
public List<HealthRecord> checkBasicLdapConnectivity(final PwmApplication pwmApplication, final Configuration config, final LdapProfile ldapProfile, final boolean testContextlessRoot) {
final List<HealthRecord> returnRecords = new ArrayList<>();
ChaiProvider chaiProvider = null;
try {
final DirectoryVendor directoryVendor;
try {
final String proxyDN = ldapProfile.readSettingAsString(PwmSetting.LDAP_PROXY_USER_DN);
final PasswordData proxyPW = ldapProfile.readSettingAsPassword(PwmSetting.LDAP_PROXY_USER_PASSWORD);
if (proxyDN == null || proxyDN.length() < 1) {
return Collections.singletonList(new HealthRecord(HealthStatus.WARN, HealthTopic.LDAP, "Missing Proxy User DN"));
}
if (proxyPW == null) {
return Collections.singletonList(new HealthRecord(HealthStatus.WARN, HealthTopic.LDAP, "Missing Proxy User Password"));
}
chaiProvider = LdapOperationsHelper.createChaiProvider(pwmApplication, SessionLabel.HEALTH_SESSION_LABEL, ldapProfile, config, proxyDN, proxyPW);
final ChaiEntry adminEntry = chaiProvider.getEntryFactory().newChaiEntry(proxyDN);
adminEntry.exists();
directoryVendor = chaiProvider.getDirectoryVendor();
} catch (ChaiException e) {
final ChaiError chaiError = ChaiErrors.getErrorForMessage(e.getMessage());
final PwmError pwmError = PwmError.forChaiError(chaiError);
final StringBuilder errorString = new StringBuilder();
final String profileName = ldapProfile.getIdentifier();
errorString.append("error connecting to ldap directory (").append(profileName).append("), error: ").append(e.getMessage());
if (chaiError != null && chaiError != ChaiError.UNKNOWN) {
errorString.append(" (");
errorString.append(chaiError.toString());
if (pwmError != null && pwmError != PwmError.ERROR_UNKNOWN) {
errorString.append(" - ");
errorString.append(pwmError.getLocalizedMessage(PwmConstants.DEFAULT_LOCALE, pwmApplication.getConfig()));
}
errorString.append(")");
}
returnRecords.add(new HealthRecord(HealthStatus.WARN, makeLdapTopic(ldapProfile, config), errorString.toString()));
pwmApplication.getLdapConnectionService().setLastLdapFailure(ldapProfile, new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, errorString.toString()));
return returnRecords;
} catch (Exception e) {
final HealthRecord record = HealthRecord.forMessage(HealthMessage.LDAP_No_Connection, e.getMessage());
returnRecords.add(record);
pwmApplication.getLdapConnectionService().setLastLdapFailure(ldapProfile, new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE, record.getDetail(PwmConstants.DEFAULT_LOCALE, pwmApplication.getConfig())));
return returnRecords;
}
if (directoryVendor != null && directoryVendor == DirectoryVendor.ACTIVE_DIRECTORY) {
returnRecords.addAll(checkAd(pwmApplication, config, ldapProfile));
}
if (testContextlessRoot) {
for (final String loopContext : ldapProfile.readSettingAsStringArray(PwmSetting.LDAP_CONTEXTLESS_ROOT)) {
try {
final ChaiEntry contextEntry = chaiProvider.getEntryFactory().newChaiEntry(loopContext);
final Set<String> objectClasses = contextEntry.readObjectClass();
if (objectClasses == null || objectClasses.isEmpty()) {
final String errorString = "ldap context setting '" + loopContext + "' is not valid";
returnRecords.add(new HealthRecord(HealthStatus.WARN, makeLdapTopic(ldapProfile, config), errorString));
}
} catch (Exception e) {
final String errorString = "ldap root context '" + loopContext + "' is not valid: " + e.getMessage();
returnRecords.add(new HealthRecord(HealthStatus.WARN, makeLdapTopic(ldapProfile, config), errorString));
}
}
}
} finally {
if (chaiProvider != null) {
try {
chaiProvider.close();
} catch (Exception e) {
/* ignore */
}
}
}
return returnRecords;
}
Aggregations