Search in sources :

Example 1 with DirectoryVendor

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;
}
Also used : Date(java.util.Date) PwmOperationalException(password.pwm.error.PwmOperationalException) AuditRecordFactory(password.pwm.svc.event.AuditRecordFactory) StatisticsManager(password.pwm.svc.stats.StatisticsManager) ChaiProvider(com.novell.ldapchai.provider.ChaiProvider) MacroMachine(password.pwm.util.macro.MacroMachine) DirectoryVendor(com.novell.ldapchai.provider.DirectoryVendor) IntruderManager(password.pwm.svc.intruder.IntruderManager) AuditRecord(password.pwm.svc.event.AuditRecord)

Example 2 with DirectoryVendor

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));
    }
}
Also used : ErrorInformation(password.pwm.error.ErrorInformation) ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) DirectoryVendor(com.novell.ldapchai.provider.DirectoryVendor) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException)

Example 3 with DirectoryVendor

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();
}
Also used : Configuration(password.pwm.config.Configuration) ArrayList(java.util.ArrayList) PwmLdapVendor(password.pwm.ldap.PwmLdapVendor) TreeMap(java.util.TreeMap) LdapProfile(password.pwm.config.profile.LdapProfile) URISyntaxException(java.net.URISyntaxException) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) PwmException(password.pwm.error.PwmException) IOException(java.io.IOException) PwmSetting(password.pwm.config.PwmSetting) PwmAboutProperty(password.pwm.PwmAboutProperty) StatisticsBundle(password.pwm.svc.stats.StatisticsBundle) Statistic(password.pwm.svc.stats.Statistic) DirectoryVendor(com.novell.ldapchai.provider.DirectoryVendor) TelemetryPublishBean(password.pwm.bean.TelemetryPublishBean)

Example 4 with DirectoryVendor

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;
}
Also used : Serializable(java.io.Serializable) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) LdapProfile(password.pwm.config.profile.LdapProfile) ChaiConfiguration(com.novell.ldapchai.provider.ChaiConfiguration) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) ChaiException(com.novell.ldapchai.exception.ChaiException) ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException) MalformedURLException(java.net.MalformedURLException) UnknownHostException(java.net.UnknownHostException) ChaiEntry(com.novell.ldapchai.ChaiEntry) ChaiProvider(com.novell.ldapchai.provider.ChaiProvider) List(java.util.List) ArrayList(java.util.ArrayList) DirectoryVendor(com.novell.ldapchai.provider.DirectoryVendor) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 5 with DirectoryVendor

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;
}
Also used : PwmError(password.pwm.error.PwmError) ArrayList(java.util.ArrayList) ChaiEntry(com.novell.ldapchai.ChaiEntry) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) ChaiException(com.novell.ldapchai.exception.ChaiException) ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException) MalformedURLException(java.net.MalformedURLException) UnknownHostException(java.net.UnknownHostException) ErrorInformation(password.pwm.error.ErrorInformation) ChaiProvider(com.novell.ldapchai.provider.ChaiProvider) PasswordData(password.pwm.util.PasswordData) ChaiError(com.novell.ldapchai.exception.ChaiError) DirectoryVendor(com.novell.ldapchai.provider.DirectoryVendor) ChaiException(com.novell.ldapchai.exception.ChaiException)

Aggregations

DirectoryVendor (com.novell.ldapchai.provider.DirectoryVendor)7 ArrayList (java.util.ArrayList)4 PwmUnrecoverableException (password.pwm.error.PwmUnrecoverableException)4 ChaiUnavailableException (com.novell.ldapchai.exception.ChaiUnavailableException)3 ChaiProvider (com.novell.ldapchai.provider.ChaiProvider)3 ChaiEntry (com.novell.ldapchai.ChaiEntry)2 ChaiException (com.novell.ldapchai.exception.ChaiException)2 MalformedURLException (java.net.MalformedURLException)2 UnknownHostException (java.net.UnknownHostException)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Map (java.util.Map)2 LdapProfile (password.pwm.config.profile.LdapProfile)2 ErrorInformation (password.pwm.error.ErrorInformation)2 ChaiError (com.novell.ldapchai.exception.ChaiError)1 ChaiConfiguration (com.novell.ldapchai.provider.ChaiConfiguration)1 IOException (java.io.IOException)1 Serializable (java.io.Serializable)1 URISyntaxException (java.net.URISyntaxException)1