Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Scout » LDAPAuthenticator - example
LDAPAuthenticator - example [message #1828672] Tue, 16 June 2020 10:45 Go to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
This is PoC version, it has been functionally tested (mostly). Performance and stability has not been tested.
This was created as part of my Scout research. Any comments are welcomed.

Disclaimer: some use of Scout name in this post is not part of Scout framework. Probably I should have named it differently... sorry for that.

My requirements for this LDAPAuthenticator were:
* current security features (StartTLS, configurable: protocol (TLS1.3), ciphers, PKCS12 keystore and TrustManager)
* connection pool
* some flexibility on the LDAP schema
* querying LDAP is done on fixed account (bind_dn), and not on user accounts (regular users have minimal access - they are not authorized to lookup LDAP objects)
* authentication based not only on username/password, but also on group membership (only members of specified group are allowed to authenticate)
* optional caching for group members. Group membership do not change that often (at least in my environment)
* LDAP bypass admin account (superadmin)

Tested against OpenLDAP (osixia docker-openldap)
Below used LDAP structure. Each application has its own account for LDAP communication (in ou=services). Each application has its own set of groups (in ou=groups) that will be mapped to roles.
dc=example,dc=net
	ou=groups
		ou=scout
			cn=admin
			cn=login
			cn=simple_user
			cn=power_user
	ou=services
		uid=scout
	ou=users
		uid=bolek
		uid=user1
		uid=user2


dependencies:
		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-ext -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-ext</artifactId>
			<version>${version.slf4j.ext}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-collections4</artifactId>
			<version>${version.commons.collections4}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.apache.directory.api/api-all -->
		<dependency>
			<groupId>org.apache.directory.api</groupId>
			<artifactId>api-all</artifactId>
			<version>${version.apache.ds}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcpkix-jdk15on</artifactId>
			<version>${version.bouncycastle}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
			<version>${version.commons.pool2}</version>
		</dependency>	


properties:
### LDAP configuration
scout.auth.ldap.host=192.168.0.1
scout.auth.ldap.port=389

# local admin account, to bypass LDAP as a last resort workaround
# if LDAP authentication fails, it is extra checked against following user/pass
scout.auth.ldap.superadmin=1
scout.auth.ldap.superadmin.login=superadmin
scout.auth.ldap.superadmin.password=changeit

# 0 - no security (TODO)
# 1 - StartTLS
# 2 - LDAPS (TODO)
# https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#sslcontext-algorithms
# https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#jsse-cipher-suite-names
scout.auth.ldap.connection.type=1
scout.auth.ldap.connection.protocol=TLSv1.3,TLSv1.2
scout.auth.ldap.connection.ciphers=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
scout.auth.ldap.connection.timeout=10000

scout.auth.ldap.connection.pool.maxtotal=10
scout.auth.ldap.connection.pool.minidle=2

# LDAP authentication
# simple - anonymous - (TODO)
#          unauthenticated - (TODO)
#          user/pass authenticated - (provide bind_DN and bind_password)
# SASL-External - SASL External (TODO) 
scout.auth.ldap.auth=simple

# LDAP credentials for simple LDAP authentication
scout.auth.ldap.bind_dn=uid=scout,ou=services,dc=example,dc=net
scout.auth.ldap.bind_password=pass1234

# LDAP client side certificate
scout.auth.ldap.security.keystore.type=PKCS12
scout.auth.ldap.security.keystore.provider=SUN
scout.auth.ldap.security.keystore.file=src/main/resources/ks.p12
scout.auth.ldap.security.keystore.password=pass123
scout.auth.ldap.security.keystore.cert.alias=scout_test
scout.auth.ldap.security.keystore.cert.password=pass345

scout.auth.ldap.security.truststore.type=PKCS12
scout.auth.ldap.security.truststore.provider=SunJSSE
scout.auth.ldap.security.truststore.file=src/main/resources/ts.p12
scout.auth.ldap.security.truststore.password=pass678

# TODO
# 0 - trust any
# 1 - exact certificate match required
# 2 - trust all certificates from included CA
scout.auth.ldap.security.truststore.trustlevel=0

# OCSP certificate validation (TODO)
# 0 - OCSP query disabled
# 1 - OCSP query mandatory
# 2 - OCSP query only if present in certificate details
scout.auth.ldap.security.truststore.ocsp=0

# Only members can authenticate (if empty - anyone can authenticate - TODO)
scout.auth.ldap.user_group=cn=login,ou=scout,ou=groups,dc=example,dc=net

# attribute name for group members
scout.auth.ldap.group_fields=member,uniqueMember,memberUid

# uid or cn ?
scout.auth.ldap.user.uid_attr=uid

# where are users
scout.auth.ldap.user.dn=ou=users,dc=example,dc=net

# 0 - disabled, number - time in minutes to keep cache values
scout.auth.ldap.cache.groups=60


# future
scout.auth.ldap.group_classes=groupOfUniqueNames,groupOfNames
scout.auth.ldap.base_dn=ou=user,dc=example,dc=net
scout.auth.ldap.group_mapping=ScoutAdminGroup=cn=admin,ou=scout,ou=groups,dc=example,dc=net|\
                              ScoutPowerUserGroup=cn=power_user,ou=scout,ou=groups,dc=example,dc=net|\
                              ScoutSimpleUserGroup=cn=simple_user,ou=scout,ou=groups,dc=example,dc=net



In shared module
package io.poc.scout.ldap;

import org.eclipse.scout.rt.platform.service.IService;
import org.eclipse.scout.rt.shared.TunnelToServer;

@TunnelToServer
public interface ILDAPAuthService extends IService {

	public int verify(String username, char[] password);
}


In ui.html module:
package io.poc.scout.ldap;

import java.io.IOException;
import java.util.concurrent.Callable;

import javax.security.auth.Subject;

import org.eclipse.scout.rt.client.context.ClientRunContexts;
import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.context.RunContext;
import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
import org.eclipse.scout.rt.platform.security.SimplePrincipal;
import org.eclipse.scout.rt.platform.util.StringUtility;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

public class LDAPCredentialVerifier implements ICredentialVerifier {

	private static final XLogger LOG = XLoggerFactory.getXLogger(LDAPCredentialVerifier.class);
	
	@Override
	public int verify(String username, char[] password) throws IOException {
		LOG.entry(username, "***");
		int result = AUTH_FORBIDDEN;
		
		LOG.debug("Attempting LDAP authentication for user: {}", username);
		if ( StringUtility.isNullOrEmpty(username) || password == null || password.length == 0 ) {
			result = AUTH_CREDENTIALS_REQUIRED;
			
		} else {
			Subject subject = new Subject();
			subject.getPrincipals().add( new SimplePrincipal("system_ldap_auth") );
			subject.setReadOnly();
			RunContext runContext = ClientRunContexts.copyCurrent(true).withSubject(subject);
			
			result = runContext.call(new Callable<Integer>() {
				@Override
				public Integer call() throws Exception {
					return BEANS.get(ILDAPAuthService.class).verify(username, password);
				}
			});
		} // else
		
		return LOG.exit(result);
	}
}


In ui.html module alter class org.eclipse.scout.apps.helloworld.ui.html.UiServletFilter to use the LDAPCredentialVerifier.class
	...
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		LOG.entry();
		
		m_trivialAccessController = BEANS.get(TrivialAccessController.class).init(new TrivialAuthConfig()
				.withExclusionFilter(filterConfig.getInitParameter("filter-exclude")).withLoginPageInstalled(true));
		m_formBasedAccessController = BEANS.get(FormBasedAccessController.class)
				.init(new FormBasedAuthConfig().withCredentialVerifier(BEANS.get(LDAPCredentialVerifier.class)));
		m_developmentAccessController = BEANS.get(DevelopmentAccessController.class).init();
		
		LOG.exit();
	}
	
	...


Principal "system_ldap_auth" needs to have following permission.
In server module alter org.eclipse.scout.apps.helloworld.server.security.ServerAccessControlService add:
		permissions.add(new RemoteServiceAccessPermission("io.poc.scout.ldap.ILDAPAuthService", "verify"), PermissionLevel.ALL);


In server module:
package io.poc.scout.ldap;

import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.exception.VetoException;
import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
import org.eclipse.scout.rt.security.ACCESS;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

import io.poc.scout.ldap.ILDAPAuthService;

public class LDAPAuthServiceImpl implements ILDAPAuthService {
	
	private static final XLogger LOG = XLoggerFactory.getXLogger(LDAPAuthServiceImpl.class);
	
	
	public LDAPAuthServiceImpl() {
		LOG.entry();
		
		// enable security without restrictions
		Security.setProperty("crypto.policy", "unlimited");
		// register Bouncy Castle security provider
		Security.addProvider( new BouncyCastleProvider() );
		
		LOG.exit();
	}
	
	@Override
	public int verify(String username, char[] password) {
		LOG.entry(username, "***");
		int result = ICredentialVerifier.AUTH_FORBIDDEN;
//		AUTH_OK
//		AUTH_FORBIDDEN
//		AUTH_FAILED
//		AUTH_CREDENTIALS_REQUIRED
		
		LDAPConnectorMK2 ldap_connector = BEANS.get(LDAPConnectorMK2.class);
		if ( ldap_connector.authenticate(username, password) ) {
			result = ICredentialVerifier.AUTH_OK;
			LOG.info("LDAP authentication OK for user: {}", username);
			
		} else {
			result = ICredentialVerifier.AUTH_FAILED;
			LOG.info("LDAP authentication FAILED for user: {}", username);
		}
		
		return LOG.exit(result);
	}
	
}


package io.poc.scout.ldap.property;

import org.eclipse.scout.rt.platform.config.AbstractIntegerConfigProperty;
import org.eclipse.scout.rt.platform.config.AbstractStringConfigProperty;

public final class LDAPProperties {

	public static final String AUTH_LDAP_PROPERTIES_NS = "scout.auth.ldap";
	
	// not used
	public static final String AUTH_LDAP_PROPERTY = AUTH_LDAP_PROPERTIES_NS;
	public static final String AUTH_LDAP_PROPERTY_DESC = "Enable LDAP authentication";
	public static final String AUTH_LDAP_PROPERTY_DEFAULT = "0";
	
	public static final String AUTH_LDAP_HOST_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".host";
	public static final String AUTH_LDAP_HOST_PROPERTY_DESC = "LDAP hostname or IP";
	
	public static final String AUTH_LDAP_PORT_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".port";
	public static final String AUTH_LDAP_PORT_PROPERTY_DESC = "LDAP server port number";
	public static final Integer AUTH_LDAP_PORT_PROPERTY_DEFAULT = Integer.valueOf(389);
	
	public static final String AUTH_LDAP_SUPERADMIN_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".superadmin";
	public static final String AUTH_LDAP_SUPERADMIN_PROPERTY_DESC = "Enable local superadmin account";
	public static final String AUTH_LDAP_SUPERADMIN_PROPERTY_DEFAULT = "0";

	public static final String AUTH_LDAP_SUPERADMIN_LOGIN_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".superadmin.login";
	public static final String AUTH_LDAP_SUPERADMIN_LOGIN_PROPERTY_DESC = "Superadmin account name";

	public static final String AUTH_LDAP_SUPERADMIN_PASS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".superadmin.password";
	public static final String AUTH_LDAP_SUPERADMIN_PASS_PROPERTY_DESC = "Superadmin account password";

	public static final String AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.timeout";
	public static final String AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY_DESC = "Connection timeout";
	public static final Integer AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY_DEFAULT = Integer.valueOf(1000);
	
	public static final String AUTH_LDAP_CONNECTION_TYPE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.type";
	public static final String AUTH_LDAP_CONNECTION_TYPE_PROPERTY_DESC = "Connection type to LDAP server: 0 - insecure, 1 - StartTLS, 2 - LDAPS";
	public static final String AUTH_LDAP_CONNECTION_TYPE_PROPERTY_DEFAULT = "1";
	public static final String AUTH_LDAP_CONNECTION_TYPE_INSECURE = "0";
	public static final String AUTH_LDAP_CONNECTION_TYPE_STARTTLS = "1";
	public static final String AUTH_LDAP_CONNECTION_TYPE_LDAPS = "2";

	public static final String AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.protocol";
	public static final String AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY_DESC = "Connection security protocol";
	public static final String AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY_DEFAULT = "TLSv1.3,TLSv1.2";

	public static final String AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.ciphers";
	public static final String AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY_DESC = "Connection allowed ciphers";
	public static final String AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY_DEFAULT = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";

	public static final String AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.pool.maxtotal";
	public static final String AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY_DESC = "LDAP connection pool maxtotal";
	public static final Integer AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY_DEFAULT = Integer.valueOf(10);
	
	public static final String AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".connection.pool.minidle";
	public static final String AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY_DESC = "LDAP connection pool minidle";
	public static final Integer AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY_DEFAULT = Integer.valueOf(2);
	
	public static final String AUTH_LDAP_AUTH_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".auth";
	public static final String AUTH_LDAP_AUTH_PROPERTY_DESC = "LDAP server authentication method: simple | SASL_External";
	public static final String AUTH_LDAP_AUTH_PROPERTY_DEFAULT = "simple";

	public static final String AUTH_LDAP_BIND_DN_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".bind_dn";
	public static final String AUTH_LDAP_BIND_DN_PROPERTY_DESC = "Bind dn to authenticate against";

	public static final String AUTH_LDAP_BIND_PASS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".bind_password";
	public static final String AUTH_LDAP_BIND_PASS_PROPERTY_DESC = "Password for bind DN object";
	
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.type";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY_DESC = "Keystore type";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY_DEFAULT = "PKCS12";

	public static final String AUTH_LDAP_SECURITY_KEYSTORE_PROVIDER_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.provider";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_PROVIDER_PROPERTY_DESC = "Keystore provider";

	public static final String AUTH_LDAP_SECURITY_KEYSTORE_FILE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.file";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_FILE_PROPERTY_DESC = "Keystore file location";

	public static final String AUTH_LDAP_SECURITY_KEYSTORE_PASS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.password";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_PASS_PROPERTY_DESC = "Keystore password";

	public static final String AUTH_LDAP_SECURITY_KEYSTORE_CERT_ALIAS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.cert.alias";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_CERT_ALIAS_PROPERTY_DESC = "Alias of the certificate used for identity";

	public static final String AUTH_LDAP_SECURITY_KEYSTORE_CERT_PASS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.keystore.cert.password";
	public static final String AUTH_LDAP_SECURITY_KEYSTORE_CERT_PASS_PROPERTY_DESC = "Password for the private key";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.type";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY_DESC = "Truststore type";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY_DEFAULT = "PKCS12";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_PROVIDER_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.provider";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_PROVIDER_PROPERTY_DESC = "Truststore provider";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.trustlevel";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY_DESC = "Truststore trustlevel";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY_DEFAULT = "0";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.ocsp";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY_DESC = "Truststore ocsp";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY_DEFAULT = "0";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_FILE_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.file";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_FILE_PROPERTY_DESC = "Truststore file location";

	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_PASS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".security.truststore.password";
	public static final String AUTH_LDAP_SECURITY_TRUSTSTORE_PASS_PROPERTY_DESC = "Truststore password";
	
	// You need to be authorized to be authenticated
	public static final String AUTH_LDAP_USER_GROUP_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".user_group";
	public static final String AUTH_LDAP_USER_GROUP_PROPERTY_DESC = "LDAP group of authorized to login accounts";

	public static final String AUTH_LDAP_GROUP_CLASSES_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".group_classes";
	public static final String AUTH_LDAP_GROUP_CLASSES_PROPERTY_DESC = "LDAP object classes of a group";
	public static final String AUTH_LDAP_GROUP_CLASSES_PROPERTY_DEFAULT = "groupOfUniqueNames,groupOfNames";

	public static final String AUTH_LDAP_GROUP_FIELDS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".group_fields";
	public static final String AUTH_LDAP_GROUP_FIELDS_PROPERTY_DESC = "LDAP object classes of a group member";
	public static final String AUTH_LDAP_GROUP_FIELDS_PROPERTY_DEFAULT = "member,uniqueMember,memberUid";
	
	public static final String AUTH_LDAP_USER_UID_ATTR_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".user.uid_attr";
	public static final String AUTH_LDAP_USER_UID_ATTR_PROPERTY_DESC = "LDAP atribute name to verify login against";
	public static final String AUTH_LDAP_USER_UID_ATTR_PROPERTY_DEFAULT = "uid";

	public static final String AUTH_LDAP_USER_DN_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".user.dn";
	public static final String AUTH_LDAP_USER_DN_PROPERTY_DESC = "Location of user objects in LDAP";
	
	public static final String AUTH_LDAP_BASE_DN_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".base_dn";
	public static final String AUTH_LDAP_BASE_DN_PROPERTY_DESC = "LDAP base dn";

	public static final String AUTH_LDAP_GROUP_MAPPING_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".group_mapping";
	public static final String AUTH_LDAP_GROUP_MAPPING_PROPERTY_DESC = "Mapping of security groups between LDAP and Scout";
	
	public static final String AUTH_LDAP_CACHE_GROUPS_PROPERTY = AUTH_LDAP_PROPERTIES_NS + ".cache.groups";
	public static final String AUTH_LDAP_CACHE_GROUPS_PROPERTY_DESC = "cache LDAP groups (in minutes)";
	public static final Integer AUTH_LDAP_CACHE_GROUPS_PROPERTY_DEFAULT = Integer.valueOf(0);
	
	
	private LDAPProperties() {}
	
			
	public static class AuthLDAPHostProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_HOST_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_HOST_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPPortProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_PORT_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_PORT_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_PORT_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSuperadminProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SUPERADMIN_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SUPERADMIN_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_SUPERADMIN_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSuperadminLoginProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SUPERADMIN_LOGIN_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SUPERADMIN_LOGIN_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSuperadminPasswordProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SUPERADMIN_PASS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SUPERADMIN_PASS_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPConnectionTimeoutProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_CONNECTION_TIMEOUT_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPConnectionTypeProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_TYPE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_TYPE_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_CONNECTION_TYPE_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPConnectionProtocolProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPConnectionCiphersProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPConnectionPoolMaxtotalProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_CONNECTION_POOL_MAXTOTAL_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPConnectionPoolMinidleProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_CONNECTION_POOL_MINIDLE_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPAuthProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_AUTH_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_AUTH_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_AUTH_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPBindDNProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_BIND_DN_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_BIND_DN_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPBindPasswordProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_BIND_PASS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_BIND_PASS_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityKeystoreTypeProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSecurityKeystoreProviderProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_PROVIDER_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_PROVIDER_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityKeystoreFileProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_FILE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_FILE_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityKeystorePasswordProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_PASS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_PASS_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityKeystoreCertAliasProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_CERT_ALIAS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_CERT_ALIAS_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityKeystoreCertPasswordProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_KEYSTORE_CERT_PASS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_KEYSTORE_CERT_PASS_PROPERTY_DESC;
		}
	}

	public static class AuthLDAPSecurityTruststoreTypeProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSecurityTruststoreProviderProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_PROVIDER_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_PROVIDER_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityTruststoreTrustlevelProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSecurityTruststoreOcspProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPSecurityTruststoreFileProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_FILE_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_FILE_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPSecurityTruststorePasswordProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_PASS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_SECURITY_TRUSTSTORE_PASS_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPUserGroupProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_USER_GROUP_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_USER_GROUP_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPGroupClassesProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_GROUP_CLASSES_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_GROUP_CLASSES_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_GROUP_CLASSES_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPGroupFieldsProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_GROUP_FIELDS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_GROUP_FIELDS_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_GROUP_FIELDS_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPUserUidAttrProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_USER_UID_ATTR_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_USER_UID_ATTR_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_USER_UID_ATTR_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPUserDNProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_USER_DN_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_USER_DN_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPBaseDNProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_BASE_DN_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_BASE_DN_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPGroupMappingProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_GROUP_MAPPING_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_GROUP_MAPPING_PROPERTY_DESC;
		}
	}
	
	public static class AuthLDAPBruteforcePreventionProperty extends AbstractStringConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_BRUTEFORCE_PREVENTION_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_BRUTEFORCE_PREVENTION_PROPERTY_DESC;
		}
		
		@Override
		public String getDefaultValue() {
			return AUTH_LDAP_BRUTEFORCE_PREVENTION_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPBruteforceLockoutProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_BRUTEFORCE_LOCKOUT_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_BRUTEFORCE_LOCKOUT_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_BRUTEFORCE_LOCKOUT_PROPERTY_DEFAULT;
		}
	}
	
	public static class AuthLDAPCacheGroupsProperty extends AbstractIntegerConfigProperty {

		@Override
		public String getKey() {
			return AUTH_LDAP_CACHE_GROUPS_PROPERTY;
		}

		@Override
		public String description() {
			return AUTH_LDAP_CACHE_GROUPS_PROPERTY_DESC;
		}
		
		@Override
		public Integer getDefaultValue() {
			return AUTH_LDAP_CACHE_GROUPS_PROPERTY_DEFAULT;
		}
	}
	
}


package io.poc.scout.ldap.property;

import org.eclipse.scout.rt.platform.config.IConfigurationValidator;
import org.eclipse.scout.rt.platform.exception.InitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LDAPPropertyValidator implements IConfigurationValidator {

	private static final Logger LOG = LoggerFactory.getLogger(LDAPPropertyValidator.class);
	
	@Override
	public boolean isValid(String key, String value) {
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_PROPERTY) ) {
			
			if (value != null && value.length() == 1 && "01".indexOf(value) >= 0) {
				LOG.debug("Property: [{}] value: [{}] is valid", key, value);
				return true;
			} else {
				LOG.error("Incorrect value for property: {}", key);
				throw new InitializationException("Incorrect value for property: " + key);
			}
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_HOST_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
			return true;
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_PORT_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
			return true;
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SUPERADMIN_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SUPERADMIN_LOGIN_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SUPERADMIN_PASS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_CONNECTION_TYPE_PROPERTY) ) {
			
			if (value != null && value.length() == 1 && "012".indexOf(value) >= 0) {
				LOG.debug("Property: [{}] value: [{}] is valid", key, value);
				return true;
			} else {
				LOG.error("Incorrect value for property: {}", key);
				throw new InitializationException("Incorrect value for property: " + key);
			}
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_CONNECTION_PROTOCOL_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_CONNECTION_CIPHERS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_AUTH_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_BIND_DN_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_BIND_PASS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_TYPE_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_PROVIDER_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_FILE_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_PASS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_CERT_ALIAS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_KEYSTORE_CERT_PASS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_TYPE_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_PROVIDER_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_FILE_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_PASS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_TRUSTLEVEL_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_SECURITY_TRUSTSTORE_OCSP_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_USER_GROUP_PROPERTY) ) {
			if (value != null) {
				LOG.debug("Property: [{}] value: [{}] is valid", key, value);
				return true;
			} else {
				LOG.error("Incorrect value for property: {}", key);
				throw new InitializationException("Incorrect value for property: " + key);
			}
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_GROUP_CLASSES_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_GROUP_FIELDS_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_USER_UID_ATTR_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_USER_DN_PROPERTY) ) {
			if (value != null) {
				LOG.debug("Property: [{}] value: [{}] is valid", key, value);
				return true;
			} else {
				LOG.error("Incorrect value for property: {}", key);
				throw new InitializationException("Incorrect value for property: " + key);
			}
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_BASE_DN_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		if ( key.equalsIgnoreCase(LDAPProperties.AUTH_LDAP_GROUP_MAPPING_PROPERTY) ) {
			LOG.debug("Property: [{}] value: [{}]", key, value);
		}
		
		return false;
	}

}


package io.poc.scout.ldap;

import org.eclipse.scout.rt.platform.config.CONFIG;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

import io.poc.scout.ldap.property.LDAPProperties;

public class LDAPConnectorProperties {
	
	private static final XLogger LOG = XLoggerFactory.getXLogger(LDAPConnectorProperties.class);
	
	
	private String conn_type = null;
	private String conn_protocol = null;
	private String conn_ciphers = null;
	private Integer conn_timeout = null;
	private String conn_host = null;
	private Integer conn_port = null;
	private String conn_auth = null;
	private Integer conn_pool_maxtotal = null;
	private Integer conn_pool_minidle = null;
	
	private String conn_bind_dn = null;
	private String conn_bind_pass = null;
	
	private String ks_type = null;
	private String ks_provider = null;
	private String ks_file = null;
	private String ks_pass = null;
	private String ks_cert_alias = null;
	private String ks_cert_pass = null;
	
	private String ts_type = null;
	private String ts_provider = null;
	private String ts_file = null;
	private String ts_pass = null;
	private String ts_trustlevel = null;
	private String ts_ocsp = null;
	
	private String superadmin = null;
	private String superadmin_login = null;
	private String superadmin_pass = null;
	
	private String user_group = null;
	private String group_classes = null;
	private String group_fields = null;
	private String user_uid_attr = null;
	private String user_dn = null;
	private String base_dn = null;
	private String group_mapping = null;
	private Integer cache_groups = null;
	
	
	public LDAPConnectorProperties() {
		LOG.entry();
		
		conn_type = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionTypeProperty.class);
		conn_protocol = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionProtocolProperty.class);
		conn_ciphers = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionCiphersProperty.class);
		conn_timeout = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionTimeoutProperty.class);
		conn_host = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPHostProperty.class);
		conn_port = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPPortProperty.class);
		conn_auth = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPAuthProperty.class);
		conn_pool_maxtotal = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionPoolMaxtotalProperty.class);
		conn_pool_minidle = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPConnectionPoolMinidleProperty.class);
		
		conn_bind_dn = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPBindDNProperty.class);
		conn_bind_pass = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPBindPasswordProperty.class);
		
		ks_type = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystoreTypeProperty.class);
		ks_provider = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystoreProviderProperty.class);
		ks_file = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystoreFileProperty.class);
		ks_pass = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystorePasswordProperty.class);
		ks_cert_alias = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystoreCertAliasProperty.class);
		ks_cert_pass = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityKeystoreCertPasswordProperty.class);
		ts_type = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststoreTypeProperty.class);
		ts_provider = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststoreProviderProperty.class);
		ts_file = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststoreFileProperty.class);
		ts_pass = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststorePasswordProperty.class);
		ts_trustlevel = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststoreTrustlevelProperty.class);
		ts_ocsp = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSecurityTruststoreOcspProperty.class);
		
		superadmin = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSuperadminProperty.class);
		superadmin_login = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSuperadminLoginProperty.class);
		superadmin_pass = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPSuperadminPasswordProperty.class);
		
		user_group = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPUserGroupProperty.class);
		group_classes = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPGroupClassesProperty.class);
		group_fields = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPGroupFieldsProperty.class);
		user_uid_attr = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPUserUidAttrProperty.class);
		user_dn = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPUserDNProperty.class);
		base_dn = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPBaseDNProperty.class);
		group_mapping = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPGroupMappingProperty.class);
		cache_groups = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPCacheGroupsProperty.class);
		
		LOG.debug("conn_type: {}", conn_type);
		LOG.debug("conn_protocol: {}", conn_protocol);
		LOG.debug("conn_ciphers: {}", conn_ciphers);
		LOG.debug("conn_timeout: {}", conn_timeout.intValue());
		LOG.debug("conn_host: {}", conn_host);
		LOG.debug("conn_port: {}", conn_port.intValue());
		LOG.debug("conn_auth: {}", conn_auth);
		LOG.debug("conn_pool_maxtotal: {}", conn_pool_maxtotal.intValue());
		LOG.debug("conn_pool_minidle: {}", conn_pool_minidle.intValue());
		
		LOG.debug("conn_bind_DN: {}", conn_bind_dn);
		LOG.debug("conn_bind_pass: {}", conn_bind_pass);
		
		LOG.debug("ks_type: {}", ks_type);
		LOG.debug("ks_provider: {}", ks_provider);
		LOG.debug("ks_file: {}", ks_file);
		LOG.debug("ks_pass: {}", ks_pass);
		LOG.debug("ks_cert_alias: {}", ks_cert_alias);
		LOG.debug("ks_cert_pass: {}", ks_cert_pass);
		LOG.debug("ts_type: {}", ts_type);
		LOG.debug("ts_provider: {}", ts_provider);
		LOG.debug("ts_file: {}", ts_file);
		LOG.debug("ts_pass: {}", ts_pass);
		LOG.debug("ts_trustlevel: {}", ts_trustlevel);
		LOG.debug("ts_ocsp: {}", ts_ocsp);
		
		LOG.debug("superadmin: {}", superadmin);
		LOG.debug("superadmin_login: {}", superadmin_login);
		LOG.debug("superadmin_pass: {}", superadmin_pass);
		
		LOG.debug("user_group: {}", user_group);
		LOG.debug("group_classes: {}", group_classes);
		LOG.debug("group_fields: {}", group_fields);
		LOG.debug("user_uid_attr: {}", user_uid_attr);
		LOG.debug("user_DN: {}", user_dn);
		LOG.debug("base_DN: {}", base_dn);
		LOG.debug("group_mapping: {}", group_mapping);
		LOG.debug("cache_groups: {}", cache_groups);
				
		LOG.exit();
	}


	public String getConn_type() {
		return conn_type;
	}


	public String getConn_protocol() {
		return conn_protocol;
	}


	public String getConn_ciphers() {
		return conn_ciphers;
	}


	public Integer getConn_timeout() {
		return conn_timeout;
	}


	public String getConn_host() {
		return conn_host;
	}


	public Integer getConn_port() {
		return conn_port;
	}


	public String getConn_auth() {
		return conn_auth;
	}


	public Integer getConn_pool_maxtotal() {
		return conn_pool_maxtotal;
	}


	public Integer getConn_pool_minidle() {
		return conn_pool_minidle;
	}


	public String getConn_bind_dn() {
		return conn_bind_dn;
	}


	public String getConn_bind_pass() {
		return conn_bind_pass;
	}


	public String getKs_type() {
		return ks_type;
	}


	public String getKs_provider() {
		return ks_provider;
	}


	public String getKs_file() {
		return ks_file;
	}


	public String getKs_pass() {
		return ks_pass;
	}


	public String getKs_cert_alias() {
		return ks_cert_alias;
	}


	public String getKs_cert_pass() {
		return ks_cert_pass;
	}


	public String getTs_type() {
		return ts_type;
	}


	public String getTs_provider() {
		return ts_provider;
	}


	public String getTs_file() {
		return ts_file;
	}


	public String getTs_pass() {
		return ts_pass;
	}


	public String getTs_trustlevel() {
		return ts_trustlevel;
	}


	public String getTs_ocsp() {
		return ts_ocsp;
	}


	public String getSuperadmin() {
		return superadmin;
	}


	public String getSuperadmin_login() {
		return superadmin_login;
	}


	public String getSuperadmin_pass() {
		return superadmin_pass;
	}


	public String getUser_group() {
		return user_group;
	}


	public String getGroup_classes() {
		return group_classes;
	}


	public String getGroup_fields() {
		return group_fields;
	}


	public String getUser_uid_attr() {
		return user_uid_attr;
	}


	public String getUser_dn() {
		return user_dn;
	}


	public String getBase_dn() {
		return base_dn;
	}


	public String getGroup_mapping() {
		return group_mapping;
	}


	public Integer getCache_groups() {
		return cache_groups;
	}
}


package io.poc.scout.ldap;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory;
import org.apache.directory.ldap.client.api.LdapConnectionPool;
import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory;
import org.apache.directory.ldap.client.template.EntryMapper;
import org.apache.directory.ldap.client.template.LdapConnectionTemplate;
import org.apache.directory.ldap.client.template.exception.PasswordException;
import org.eclipse.scout.rt.platform.ApplicationScoped;
import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.cache.CacheRegistryService;
import org.eclipse.scout.rt.platform.cache.ICache;
import org.eclipse.scout.rt.platform.cache.ICacheBuilder;
import org.eclipse.scout.rt.platform.cache.ICacheValueResolver;
import org.eclipse.scout.rt.platform.util.Assertions;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

@ApplicationScoped
public class LDAPConnectorMK2 {
	
	private static final XLogger LOG = XLoggerFactory.getXLogger(LDAPConnectorMK2.class);
	
	public static final String GROUP_CACHE_CACHE_ID = LDAPConnectorMK2.class.getName() + ".GROUP_CACHE";
	
	
	protected final LDAPConnectorProperties p = new LDAPConnectorProperties();
	protected LdapConnectionPool pool = null;
	protected boolean groupCacheEnabled = false;
	
	
	public LDAPConnectorMK2() {
		LOG.entry();
		
		DefaultLdapConnectionFactory factory = new DefaultLdapConnectionFactory(LDAPUtil.getLdapConnectionConfig(p));
		factory.setTimeOut(p.getConn_timeout());
		pool = new LdapConnectionPool(new ValidatingPoolableLdapConnectionFactory(factory), LDAPUtil.getLdapPoolConfig(p) );
		
		if (p.getCache_groups() > 0) {
			groupCacheEnabled = true;
		}
		
		LOG.exit();
	}
	
	public boolean authenticate(String username, char[] password) {
		LOG.entry(username, "***");
		boolean result = false;
		
		Dn userDn = LDAPUtil.prepareUserDN(username);
		if ( validateGroupMembership(userDn) && authenticateWithUsernamePassword(userDn, password) ) {
			result = true;
		}
		
		// if LDAP authentication failed, attempt superadmin access
		if (!result) {
			result = superadminAuthentication(username, password);
		}
		
		return LOG.exit(result);
	}
	
	
	protected boolean authenticateWithUsernamePassword(Dn userDn, char[] password) {
		LOG.entry(userDn, "***");
		boolean result = false;
		
		Assertions.assertNotNull(userDn);
		Assertions.assertNotNullOrEmpty(new String(password));
		
		LdapConnectionTemplate con = new LdapConnectionTemplate(pool);
		try {
			con.authenticate(userDn, password);
			result = true;
			
		} catch (PasswordException e) {
			LOG.debug("LDAP authentication unsuccessful for: " + userDn.toString(), e);
		}
		
		return LOG.exit(result);
	}
	
	protected boolean validateGroupMembership(Dn userDn) {
		LOG.entry(userDn);
		boolean result = false;
		
		Set<String> users = getLdapGroupMembers( p.getUser_group() );
		
		if ( users.contains( userDn.getName().toLowerCase() ) ) {
			result = true;
		}
		
		return LOG.exit(result);
	}
	
	protected boolean superadminAuthentication(String username, char[] password) {
		LOG.entry();
		boolean result = false;
		
		if ( p.getSuperadmin().equals("1") 
				&& p.getSuperadmin_login().equals(username)
				&& p.getSuperadmin_pass().equals( new String(password) ) ) {
			
			LOG.warn("superadmin access granted");
			result = true;
		}
		
		return LOG.exit(result);
	}
	
	public Set<String> getLdapGroupMembers(String ldapGroup) {
		LOG.entry(ldapGroup);
		Set<String> result = null;
		
		Assertions.assertNotNull(ldapGroup);
		
		if (groupCacheEnabled) {
			LOG.debug("attempting to get values from cache");
			result = getCache().get(ldapGroup);
			
		} else {
			result = getLdapGroupMembersNoCache(ldapGroup);
		}
		result.stream().forEach(x -> LOG.debug("member: {}", x));
		
		return LOG.exit(result);
	}
	
	public Set<String> getLdapGroupMembersNoCache(String ldapGroup) {
		LOG.entry(ldapGroup);
		Set<String> result = null;
		
		LdapConnectionTemplate con = new LdapConnectionTemplate(pool);
		result = con.lookup(LDAPUtil.getDn(ldapGroup), groupMembersEntryMapper);
		
		return LOG.exit(result);
	}
	
	private final EntryMapper<Set<String>> groupMembersEntryMapper = new EntryMapper<Set<String>>() {

		@Override
		public Set<String> map(Entry entry) throws LdapException {
			LOG.entry(entry);
			Set<String> result = new HashSet<String>();
			
			// checking groups for attributes: scout.auth.ldap.group_fields=member,uniqueMember,memberUid
//			String group_fields = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPGroupFieldsProperty.class);
			String group_fields = p.getGroup_fields();
			Set<String> group_fields_set = Stream.of(group_fields.split(",")).map(x -> x.toLowerCase()).collect(Collectors.toSet());
			group_fields_set.stream().forEach(x -> LOG.debug("group_field: {}", x));
			
			Collection<Attribute> c_attr = entry.getAttributes();
			
			c_attr.stream()
				.filter(y -> group_fields_set.contains(y.getId().toLowerCase()))
				.forEach(d -> d.forEach(e -> result.add(e.getString())));
			
			result.stream().forEach(x -> LOG.debug("user: {}", x));
			
			return LOG.exit(result);
		}

	};
	
	private ICache<String, Set<String>> getCache() {
		LOG.entry();
		ICache<String, Set<String>> result = null;
		
		CacheRegistryService crs = BEANS.get(CacheRegistryService.class);
		result = crs.opt(GROUP_CACHE_CACHE_ID);
		
		if (result == null) {
			result = createCache();
		}
		
		return LOG.exit(result);
	}
	
	private ICache<String, Set<String>> createCache() {
		LOG.entry();
		ICache<String, Set<String>> result = null;
		
		@SuppressWarnings("unchecked")
		ICacheBuilder<String, Set<String>> cacheBuilder = BEANS.get(ICacheBuilder.class);
		result = cacheBuilder
				.withCacheId(GROUP_CACHE_CACHE_ID)
				.withTimeToLive(Long.valueOf(p.getCache_groups()), TimeUnit.MINUTES, false)
				.withValueResolver(new ICacheValueResolver<String, Set<String>>() {
					@Override
					public Set<String> resolve(String key) {
						LOG.entry(key);
						Set<String> result = getLdapGroupMembersNoCache(key);
						return LOG.exit(result);
					}
				})
				.withThreadSafe(true)
				.build();
		
		return LOG.exit(result);
	}
	
}

[Updated on: Tue, 16 June 2020 10:56]

Report message to a moderator

Re: LDAPAuthenticator - example [message #1828673 is a reply to message #1828672] Tue, 16 June 2020 10:57 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
package io.poc.scout.ldap;

import java.security.KeyStore;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;

import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.eclipse.scout.rt.platform.config.CONFIG;
import org.eclipse.scout.rt.platform.exception.PlatformException;
import org.eclipse.scout.rt.platform.exception.ProcessingException;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

import io.poc.scout.ldap.FullVerificationTrustManager;
import io.poc.scout.ldap.property.LDAPProperties;

public class LDAPUtil {
	
	private static final XLogger LOG = XLoggerFactory.getXLogger(LDAPUtil.class);
	
	
	public LDAPUtil() {
		LOG.entry();
		LOG.exit();
	}
	
	
	public static Dn prepareUserDN(String userId) {
		LOG.entry(userId);
		Dn result = null;
		
		String user_uid_attr = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPUserUidAttrProperty.class);
		String user_DN = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPUserDNProperty.class);
		
		String tmpDN = user_uid_attr + "=" + userId + "," + user_DN;
		LOG.debug("tmpDN: {}", tmpDN);
		
		result = getDn(tmpDN);
		
		return LOG.exit(result);
	}
	
	public static Dn getDn(String stringDn) {
		LOG.entry(stringDn);
		Dn result = null;
		
		try {
			result = new Dn(stringDn);
			
		} catch (LdapInvalidDnException e) {
			String msg = "Cannot create Dn for: " + stringDn;
			LOG.error(msg, e);
			throw new PlatformException(msg, e).withContextInfo("dn", stringDn);
		}
		
		return LOG.exit(result);
	}
	
	public static BidiMap<String, String> getGroupMappings() {
		LOG.entry();
		BidiMap<String, String> result =  new DualHashBidiMap<String, String>();
		
		String group_mapping = CONFIG.getPropertyValue(LDAPProperties.AuthLDAPGroupMappingProperty.class);
		Set<String> x_group_mapping_set = Stream.of(group_mapping.split("\\|")).collect(Collectors.toSet());
		x_group_mapping_set.stream().forEach(x -> LOG.debug("mapping: {}", x) );
		
		Pattern pattern = Pattern.compile("([^=]*)=(.*)");
		
		for (String str : x_group_mapping_set) {
			LOG.debug("processing: {}", str);
			Matcher m = pattern.matcher(str);
			if ( m.find() ) {
				String group = m.group(1);
				String ldap = m.group(2);
				LOG.debug("group: {} ldap: {}", group, ldap);
				result.put(group, ldap);
				
			} else {
				String msg = "Incorrect LDAP group mapping: " + str;
				LOG.error(msg);
				throw new PlatformException(msg)
					.withContextInfo("group mapping", str)
					.withContextInfo("system property", LDAPProperties.AUTH_LDAP_GROUP_MAPPING_PROPERTY);
			}
		} // for
		
		return LOG.exit(result);
	}
	
	public static LdapConnectionConfig getLdapConnectionConfig(LDAPConnectorProperties p) {
		LOG.entry();
		LdapConnectionConfig result = new LdapConnectionConfig();
		
		result.setLdapHost(p.getConn_host());
		result.setLdapPort(p.getConn_port());
		result.setTimeout(p.getConn_timeout());
		result.setName(p.getConn_bind_dn());
		result.setCredentials(p.getConn_bind_pass());
		
		String[] enabledCipherSuites = getEnabledCiphers(p.getConn_ciphers());
		if (enabledCipherSuites != null) {
			result.setEnabledCipherSuites( enabledCipherSuites );
		}
		
		String[] enabledSecurityProtocols = getEnabledProtocols(p.getConn_protocol());
		if (enabledSecurityProtocols != null) {
			result.setEnabledProtocols( enabledSecurityProtocols );
			result.setSslProtocol(enabledSecurityProtocols[0]);
		}
		
		result.setTrustManagers( getTrustManager(p) );
		result.setKeyManagers( getKeyManagers(p) );
		
		result.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );
		
		switch (p.getConn_type()) {
		case LDAPProperties.AUTH_LDAP_CONNECTION_TYPE_INSECURE : {
			// 0
			// insecure
			LOG.debug("Preparing insecure connection");
			break;
		}
		case LDAPProperties.AUTH_LDAP_CONNECTION_TYPE_STARTTLS : {
			// 1
			// StartTLS
			LOG.debug("Preparing StartTLS connection");
			result.setUseTls(true);
			break;
		}
		case LDAPProperties.AUTH_LDAP_CONNECTION_TYPE_LDAPS : {
			// 2
			// LDAPS
			LOG.debug("Preparing LDAPS connection");
			result.setUseSsl(true);
			break;
		}
		default : {
			throw new ProcessingException("Unknown value for configuration property: " 
					+ LDAPProperties.AUTH_LDAP_CONNECTION_TYPE_PROPERTY + " : " + p.getConn_type());
		}
		
		} // switch
		
		return LOG.exit(result);
	}
	
	protected static String[] getEnabledCiphers(String enabledCiphers) {
		LOG.entry(enabledCiphers);
		String[] result = null;
		
		Set<String> tmpSet =  Stream.of(enabledCiphers.split(",")).collect(Collectors.toSet());
		tmpSet.stream().forEach(x -> LOG.debug("enabled cipher: {}", x));
		result = tmpSet.stream().toArray(x -> new String[x]);
		
		return LOG.exit(result);
	}
	
	protected static String[] getEnabledProtocols(String protocols) {
		LOG.entry(protocols);
		String[] result = null;
		
		Set<String> tmpSet =  Stream.of(protocols.split(",")).collect(Collectors.toSet());
		tmpSet.stream().forEach(x -> LOG.debug("enabled protocol: {}", x));
		result = tmpSet.stream().toArray(x -> new String[x]);
		
		return LOG.exit(result);
	}
	
	protected static KeyManager[] getKeyManagers(LDAPConnectorProperties p) {
		LOG.entry();
		KeyManager[] result = null;
		
		KeyStore ks = PKIHelper.getKeystore(p.getKs_type(), p.getKs_provider(), p.getKs_file(), p.getKs_pass());
		result = PKIHelper.prepareKeyManagers(ks, p.getKs_pass(), p.getKs_cert_alias(), p.getKs_cert_pass());
		
		return LOG.exit(result);
	}
	
	protected static TrustManager getTrustManager(LDAPConnectorProperties p) {
		LOG.entry();
		TrustManager result = null;
		
		KeyStore ts = null;
		if (p.getTs_file() != null) {
			// open truststore
			ts = PKIHelper.getKeystore(p.getTs_type(), p.getTs_provider(), p.getTs_file(), p.getTs_pass());
		}
		
		result = new FullVerificationTrustManager(ts, p.getTs_ocsp(), p.getTs_trustlevel());
//		result = new NoVerificationTrustManager();
		
		return LOG.exit(result);
	}
	
	public static GenericObjectPoolConfig<LdapConnection> getLdapPoolConfig(LDAPConnectorProperties p) {
		LOG.entry();
		GenericObjectPoolConfig<LdapConnection> result = new GenericObjectPoolConfig<LdapConnection>();
		
		result.setLifo(GenericObjectPoolConfig.DEFAULT_LIFO);
		result.setMaxTotal(p.getConn_pool_maxtotal());
		result.setMinIdle(p.getConn_pool_minidle());
		result.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE);
		result.setMaxWaitMillis(GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS);
		result.setMinEvictableIdleTimeMillis(GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
		result.setNumTestsPerEvictionRun(GenericObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN);
		result.setSoftMinEvictableIdleTimeMillis(GenericObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
		result.setTestOnBorrow(GenericObjectPoolConfig.DEFAULT_TEST_ON_BORROW);
		result.setTestOnReturn(GenericObjectPoolConfig.DEFAULT_TEST_ON_RETURN);
		result.setTestWhileIdle(GenericObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE);
		result.setTimeBetweenEvictionRunsMillis(GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
		result.setBlockWhenExhausted(GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED);
		
		return LOG.exit(result);
	}
	
}


package io.poc.scout.ldap;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.stream.Stream;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

public class PKIHelper {

	private static final XLogger LOG = XLoggerFactory.getXLogger(PKIHelper.class);
	
	
	private static PKIHelper instance = null;
	
	
	public static PKIHelper getInstance() {
		LOG.entry();
		
		if (instance == null) {
			instance = new PKIHelper();
		}
		
		return LOG.exit(instance);
	}
	
	
	public PKIHelper() {
		LOG.entry();
		
		Security.setProperty("crypto.policy", "unlimited");
		Security.addProvider( new BouncyCastleProvider() );
		
		LOG.exit();
	}
	
	
	public static KeyManager[] prepareKeyManagers(KeyStore ks, String password, String cert_label, String cert_password) {
		LOG.entry(ks, "***", cert_label, "***");
		KeyManager[] result = null;
		
		try {
			// prepare cert_password
			LOG.debug("preparing password");
			char[] cert_password_char = null;
			if (cert_password != null) {
				cert_password_char = cert_password.toCharArray();
			} else {
				cert_password_char = new char[0];
			}
			
			// get certificate key and chain
			LOG.debug("getting key and chain");
			if (ks.getCertificate(cert_label) == null) {
				throw new UnrecoverableKeyException("No certificate found with alias: " + cert_label);
			}
			Certificate[] cert_chain = ks.getCertificateChain(cert_label);
			Key cert_priv_key = ks.getKey(cert_label, cert_password_char);
			
			Stream.of(cert_chain).forEach( x -> LOG.debug("cert: {}", ((X509Certificate) x).getSubjectDN() ) );
			LOG.debug("priv key alg: {} format: {}", cert_priv_key.getAlgorithm(), cert_priv_key.getFormat());
			
			// create new KeyStore and add extracted certificate and key
			LOG.debug("creating new keystore");
			KeyStore newKeystore = getKeystore(ks.getType(), ks.getProvider().getName(), null, password);
			LOG.debug("adding cert to new keystore");
			newKeystore.setKeyEntry(cert_label, cert_priv_key, cert_password_char, cert_chain);
			
			// prepare KeyManagers
			LOG.debug("getting default KeyManagerFactory algorithm");
			String defaultAlg = KeyManagerFactory.getDefaultAlgorithm();
			LOG.debug("default KeyManagerFactory algorithm: {}", defaultAlg);
			KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultAlg);
//			KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
			
			keyManagerFactory.init(newKeystore, cert_password_char);
			result = keyManagerFactory.getKeyManagers();
			
			
		} catch (KeyStoreException e) {
			String msg = "Error preparing KeyManagers";
			LOG.error(msg, e);
			
		} catch (UnrecoverableKeyException e) {
			String msg = "Error preparing KeyManagers";
			LOG.error(msg, e);
			
		} catch (NoSuchAlgorithmException e) {
			String msg = "Error preparing KeyManagers";
			LOG.error(msg, e);
		}
		
		return LOG.exit(result);
	}
	
	
	public static KeyStore getKeystore(String type, String provider, String location, String password) {
		LOG.entry(type, provider, location, "***");
		KeyStore result = null;
		
		try {
			KeyStore ks = null;
			if (provider == null) {
				// use default provider
				ks = KeyStore.getInstance(type);
				
			} else {
				// use specified provider
				ks = KeyStore.getInstance(type, provider);
			}

			if (location != null) {
				// we will load keystore from file
				Path path = Paths.get(location).normalize().toAbsolutePath();
				LOG.debug("keystore absolute normalized path: {}", path.toString());
				
				try (InputStream readStream = Files.newInputStream(path, StandardOpenOption.READ)) {
					if (password != null) {
						ks.load(readStream, password.toCharArray());
						
					} else {
						ks.load(readStream, new char[0]);
					}
				}
				LOG.debug("keystore successfully opened");
				
			} else {
				// we will create new keystore
				if (password != null) {
					ks.load(null, password.toCharArray());
					
				} else {
					ks.load(null, null);
				}
				LOG.debug("keystore successfully created");
			}
			
			result = ks;
			
		} catch (KeyStoreException e) {
			String msg = "Cannot open keystore: " + location;
			LOG.error(msg, e);
			
		} catch (NoSuchProviderException e) {
			String msg = "Cannot open keystore: " + location;
			LOG.error(msg, e);
			
		} catch (IOException e) {
			String msg = "Cannot open keystore: " + location;
			LOG.error(msg, e);
			
		} catch (NoSuchAlgorithmException e) {
			String msg = "Cannot open keystore: " + location;
			LOG.error(msg, e);
			
		} catch (CertificateException e) {
			String msg = "Cannot open keystore: " + location;
			LOG.error(msg, e);
		}
		
		return LOG.exit(result);
	}
	
	
	public static boolean isCertificatePresent(X509Certificate cert, KeyStore ks) {
		LOG.entry( (cert!=null) ? cert.getSubjectDN() : cert, ks);
		boolean result = false;
		
		if (ks != null && cert != null)
		try {
			Enumeration<String> aliases = ks.aliases();
			
			while (aliases.hasMoreElements()) {
				String alias = aliases.nextElement();
				
				if (ks.isCertificateEntry(alias)) {
					X509Certificate tmpCert = (X509Certificate) ks.getCertificate(alias);
					LOG.debug("tmpCert: {} signed by: {} sn: {}", tmpCert.getSubjectDN().toString(), tmpCert.getIssuerDN(), tmpCert.getSerialNumber());
					if (cert.equals(tmpCert)) {
						LOG.debug("found equal certificate");
						result = true;
						break;
					}
				} // if
				
			} // while
			
		} catch (KeyStoreException e) {
			LOG.error("Problems", e);
		}
		
		return LOG.exit(result);
	}
	
}


package io.poc.scout.ldap;

import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.stream.Stream;

import javax.net.ssl.X509TrustManager;

import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

public class FullVerificationTrustManager implements X509TrustManager {

	private static final XLogger LOG = XLoggerFactory.getXLogger(FullVerificationTrustManager.class);
	
	
	private KeyStore ks = null;
	private String ocsp = null;
	private String trustlevel = null;
	
	
	public FullVerificationTrustManager(KeyStore ks, String ocsp, String trustlevel) {
		LOG.entry(ks, ocsp, trustlevel);
		
//		if (ks == null)
//			throw new IllegalArgumentException("TrustStore cannot be null");
		
		this.ks = ks;
		this.ocsp = ocsp;
		this.trustlevel = trustlevel;
		
		LOG.exit();
	}
	
	/**
	 * Method called on the server-side for establishing trust with a client.
	 */
	@Override
	public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		LOG.entry(chain, authType);
		
		Stream.of(chain).forEach(x -> LOG.debug("client cert: {} issued by: {} sn: {}", 
				x.getSubjectDN(), x.getIssuerDN(), x.getSerialNumber()) );
		
		LOG.exit();
	}
	
	/**
	 * Method called on the client-side for establishing trust with a server.
	 */
	@Override
	public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		LOG.entry(chain, authType);
		
		for (X509Certificate cert: chain) {
			LOG.debug("server cert: {} issued by: {} sn: {}", cert.getSubjectDN(), cert.getIssuerDN(), cert.getSerialNumber());
			verifyCertificate(cert);
			verifyOCSP(cert);
		}
		
		LOG.exit();
	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		LOG.entry();
		
		return LOG.exit(null);
	}
	
	
	private void verifyCertificate(X509Certificate cert) throws CertificateException {
		LOG.entry( (cert != null) ? cert.getSubjectDN() : cert);
		
		if (ks != null) {
			if (!PKIHelper.isCertificatePresent(cert, ks)) {
				String msg = "Certificate not trusted: " + cert.getSubjectDN();
				LOG.warn(msg);
				throw new CertificateException(msg);
			} else {
				LOG.debug("Certificate trusted: " + cert.getSubjectDN());
			}
			
		} else {
			String msg = "Cannot confirm trust";
			throw new CertificateException(msg);
		}
		
		LOG.exit();
	}
	
	private void verifyOCSP(X509Certificate cert) throws CertificateException {
		LOG.entry( (cert != null) ? cert.getSubjectDN() : cert);
		
		switch (ocsp) {
		case "0" : {
			// do nothing
			break;
		}
		
		case "1" : {
			// mandatory check
			if (!verifyOCSPCertificate(cert)) {
				String msg = "OCSP verification failure for certificate: " + cert.getSubjectDN();
				LOG.error(msg);
				throw new CertificateException(msg);
			}
			break;
		}
		
		case "2" : {
			// check if present in certificate details
			
			break;
		}
		
		default : {
			String msg = "Unrecognized ocsp verification mode: " + ocsp;
			LOG.error(msg);
			throw new CertificateException(msg);
		}
		} // switch
		
		LOG.exit();
	}
	
	private boolean verifyOCSPCertificate(X509Certificate cert) {
		LOG.entry( (cert != null) ? cert.getSubjectDN() : cert);
		boolean result = false;
		
		//TODO
		
		result = true;
		return LOG.exit(result);
	}
	
}

Re: LDAPAuthenticator - example [message #1828674 is a reply to message #1828672] Tue, 16 June 2020 11:05 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Thank you very much for the PoC.
Yes we will review it and check back with you how to continue.
Re: LDAPAuthenticator - example [message #1833394 is a reply to message #1828673] Mon, 12 October 2020 08:36 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Hi Darth ,

Sorry for the delay, I finally went through your code. I like the structure and your clean code.

We would appreciate to include your code into eclipse scout.

As a suggestion, is it possible that you create a new maven module as a git merge request so we can easily integrate into the next release?

Name of that new module: org.eclipse.scout.rt.ldap ?

Documentation in scout is done using asciidoc. So your general comments and usage examples could go into
git/org.eclipse.scout.docs/docs/adoc/technicalGuide/Ldap.adoc

Please let me know if you need any assistance.
Re: LDAPAuthenticator - example [message #1834345 is a reply to message #1833394] Sun, 08 November 2020 12:06 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Is there any further interest in this?
Re: LDAPAuthenticator - example [message #1834681 is a reply to message #1834345] Sun, 15 November 2020 19:21 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
Hi Ivan,

Sorry for delay... When I am not involved/working on something here there might be considerable delay to get in touch with me. (Until this topic is closed, I should be more responsive)

I am very happy you like the code, and yes I will help.
I expect to experience some troubles with build/test process, and I am very happy that you will assist :)

So, lets start: (please correct if my assumptions are wrong)

1. git repos to use
Scout RT: git://git.eclipse.org/gitroot/scout/org.eclipse.scout.rt.git
Scout Docs: https://github.com/BSI-Business-Systems-Integration-AG/org.eclipse.scout.docs.git


2. Which branch should I use as a source?
releases/10.0 * (currently using)
releases/11.0
other?

3. Which version should I use in pom files?
10.0.0-SNAPSHOT * (currently using)
11.0.0-SNAPSHOT
other?

4. dev/test environment. Is it OK, or are there other requirements I am not aware of?
I will use:
Fedora 32
openjdk 11.0.9 2020-10-20
eclipse-java-2020-09-R-linux-gtk-x86_64 (module dev)
eclipse-scout-2020-09-R-linux-gtk-x86_64 (module test)
maven 3.6.1 (external to eclipse)
node v12.19.0


5. Are there any other places that needs to be updated?
roughly module setup (I basicly copied structure from org.eclipse.scout.rt.mail module):
org.eclipse.scout.rt
    pom.xml <- add new entries, specific for org.eclipse.scout.rt.ldap and org.eclipse.scout.rt.ldap.test
    
org.eclipse.scout.rt.ldap
    src/main/java
        org.eclipse.scout.rt.ldap
            ILDAPAuthService.java
            ILDAPConnector.java
            LDAPAuthServiceImpl.java
            LDAPConnectorMK2.java
            LDAPConnectorMK3.java
            LDAPConnectorProperties.java
            LDAPCredentialsVerifier.java
        org.eclipse.scout.rt.ldap.property
            LDAPProperties.java
            LDAPPropertyValidator.java
        org.eclipse.scout.rt.ldap.security
            AuthenticateLDAPPermission.java
        org.eclipse.scout.rt.ldap.util
            FullVerificationTrustManager.java
            LDAPUtil.java
            PKIHelper.java
    pom.xml
    
org.eclipse.scout.rt.ldap.test
    src/main/java
        org.eclipse.scout.rt.ldap.util
            LDAPUtilTest.java
    pom.xml
Re: LDAPAuthenticator - example [message #1834686 is a reply to message #1834681] Mon, 16 November 2020 00:41 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
6. Build procedure - please confirm this is correct one

It took me a while to figure out that there is a root pom file (it does not show in eclipse). This wasn't meant to be build from eclipse, was it?
It is also strange that eclipse pulled code to ~/git and not to the workspace... (or I did something very stupid)

I did run:
rm ~/.m2/repository
cd ~/git/org.eclipse.scout.rt
mvn install 2>&1 | tee /tmp/mvn.txt


result:
...
[INFO] org.eclipse.scout.rt:org.eclipse.scout.rt.ldap ..... SUCCESS [  3.167 s]
[INFO] org.eclipse.scout.rt:org.eclipse.scout.rt.ldap.test  SUCCESS [  2.522 s]
...
[INFO] Eclipse Scout RT ROOT Module ....................... SUCCESS [  0.089 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  14:22 min
...

The mvn.txt file size is almost 8MB - I checked only the end...
now I have scout RT 10.0.0-SNAPSHOT in local repository

7. testing - problem with runtime

step 1. In new workspace I created new scout helloworld.
step 2. In helloworld/pom.xml I changed scout version to 10.0.0-SNAPSHOT (was 10.0.33)
  <properties>
  ...
    <org.eclipse.scout.rt.version>10.0.0-SNAPSHOT</org.eclipse.scout.rt.version>
  ...
  </properties>


step 3. Alter the code - there are no errors in eclipse GUI
in helloworld.server: 
org.eclipse.scout.apps.helloworld.server.security.ServerAccessControlService (add permissions)

in helloworld.ui.html:
org.eclipse.scout.apps.helloworld.ui.html.UiServletFilter (update to LDAPCredentialVerifier)

add dependency to poms in:
helloworld.server, helloworld.server.app.dev, helloworld.ui.html, helloworld.ui.html.app.dev

    <dependency>
      <groupId>org.eclipse.scout.rt</groupId>
      <artifactId>org.eclipse.scout.rt.ldap</artifactId>
    </dependency>



step 4. start jetty webserver from: helloworld.server.app.dev and helloworld.ui.html.app.dev

server fails on recognizing ldap properties (it is not aware of LDAPProperties class)
ui fails on: Assertion error: no instance found for query: class org.eclipse.scout.rt.ldap.LDAPCredentialVerifier

So, clearly org.eclipse.scout.rt.ldap module is missing from runtime environment.

It is probably good time to mention that this is my first maven project...

Where should I attempt to fix it?
* in helloworld poms? and force it somewhere during runtime
* in org.eclipse.scout.rt? have I forgot about something to make this work? (point 5 from post above)
* in org.eclipse.scout.dev.jetty?

Re: LDAPAuthenticator - example [message #1834739 is a reply to message #1834686] Tue, 17 November 2020 08:48 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Hi Darth, thank you!
I will go through all of this and then we start getting it into the code.

For administration sake here is the documentation about doing a gerrit commit https://wiki.eclipse.org/Scout/Contribution#Source_Code_Contribution
However I will assist you with this much bigger piece in any step.

Also it would be preferrable to create an eclipse bug for this change in order to better track it than in a forum blog post. We wil target 11.0 and can the cherry pick back to 10.x.

Would you mind creating a bug in https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Scout
Component: Scout
Version: 11.0
Severity: Enhancement

Re: LDAPAuthenticator - example [message #1834760 is a reply to message #1834739] Tue, 17 November 2020 13:24 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
Done.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=568886
Re: LDAPAuthenticator - example [message #1834915 is a reply to message #1834760] Fri, 20 November 2020 13:22 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Aaah now its me being so lazy. Sorry for the delay.

Most important thing to us is that your name appears on this contribtion starting at action zero. That's why the bugzilla is important. Thanks for creating it.

Is there any chance you can push your contribution to the eclipse git/gerrit? So we can go through it for example in a skype session. This would be most efficient.
The benefit of pushing your git branch to gerrit (gerrit commit) would be that I can look at it before we talk and share screens.

BTW: Is your preferred language english? or german, or french, or italian?
Re: LDAPAuthenticator - example [message #1834944 is a reply to message #1834915] Sat, 21 November 2020 13:37 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
We may have a problem...

I went through documentation for contribution process, and if I understand correctly agreeing to ECA is not optional (for pushing to gerrit).

I am afraid I do not agree with ECA Developer Certificate of Origin. In particular question D:
I do not agree that my contribution is kept on public record together with my personal details.
I do not agree to disclose my personal details in the first place. I wish to remain anonymous.

Is there any way we can continue this without me agreeing to ECA?

For the record:
I consider my contributions public domain. (no copyright, no restrictions, anyone can do anything with it - even submit to eclipse as their own...)

English is the only language I am able to communicate with on the topic of IT.
Re: LDAPAuthenticator - example [message #1835326 is a reply to message #1834944] Mon, 30 November 2020 18:07 Go to previous messageGo to next message
Beat Schwarzentrub is currently offline Beat SchwarzentrubFriend
Messages: 214
Registered: November 2010
Senior Member
IANAL, but this shouldn't pose a problem.

From https://www.eclipse.org/legal/ECA.php:
d. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my signoff) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

(emphasis mine)

Each git commit contains the name and e-mail address of its author, along with a comment that describes the change. I think the ECA just wants to make you aware of the fact that whatever information you submit with these meta data attributes will forever be part of this commit and cannot be removed (that's just the way git works). However, it is entirely your choice what information you provide. You can set the author name and e-mail address to anything you like. Likewise, the Signed-off-by line in the commit message will appear just like you enter it.

Regards,
Beat
Re: LDAPAuthenticator - example [message #1835549 is a reply to message #1835326] Sun, 06 December 2020 18:41 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
Hi Beat,

Extract from ECA signing page
You represent that the information provided below is accurate
Your full name as written in your passport 
Your physical mailing address
Type "I AGREE" to accept the terms above

I do not think there is room for interpretation of what Eclipse Foundation wants...

However there is "loophole": B* and C* (someone who already agreed to ECA is allowed to make submission of the contribution)
from ECA:
Question A*
The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file or 

Question B*
The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file or 

Question C*
The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. 


So, the question is: Is the code worth it for someone else to get involved and and do admistrative work (the actual submission of contribution to Eclipse Foundation)?
Re: LDAPAuthenticator - example [message #1835550 is a reply to message #1835549] Sun, 06 December 2020 18:42 Go to previous messageGo to next message
Darth Bolek is currently offline Darth BolekFriend
Messages: 25
Registered: August 2019
Junior Member
current status:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=568886
Re: LDAPAuthenticator - example [message #1836138 is a reply to message #1835550] Tue, 22 December 2020 11:29 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
I get your point.
However this turns out, during xmas time I will have some time to go through it. I will take care of your code.

By saying "I want to make sure that all contribution of that code is yours" I did not mean that you have to disclose any of your private information. Normally people require and claim that they want their name and email in all of their contributed code. I guess this is true here.

If not, another option would be that I as an eclipse committer commit your code with (a) only your name in the copyright header stating that you created the initial work or (b) not naming you at all if that is what you want.

You dont basically need and ECA just to contribute some code -> as long as you can live with the fact that then another eclipse commiter committed the source code and you agree that that committer appears in the commit with his own email, not yours.

What do you think about this?
Re: LDAPAuthenticator - example [message #1839135 is a reply to message #1836138] Mon, 15 March 2021 14:24 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Updates in https://bugs.eclipse.org/bugs/show_bug.cgi?id=568886
Re: LDAPAuthenticator - example [message #1840055 is a reply to message #1839135] Tue, 06 April 2021 08:11 Go to previous message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 154
Registered: March 2010
Senior Member
Hi Darth, good news, the committer concept changed as in https://bugs.eclipse.org/bugs/show_bug.cgi?id=558653

If you find some time can you please answer my questions in https://bugs.eclipse.org/bugs/show_bug.cgi?id=568886 if we should continue here.
Previous Topic:REST Client: fetching data and populating a table
Next Topic:Filechooser: how to get the directory containing the file(s)
Goto Forum:
  


Current Time: Thu Dec 26 10:03:56 GMT 2024

Powered by FUDForum. Page generated in 0.05289 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top