Merge branch 'master' of ssh://korap.ids-mannheim.de:29418/private/Kustvakt-core
LDAP Authentication: finished.
diff --git a/.gitignore b/.gitignore
index 213a85f..a5cd534 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@
*.iml
dependency-reduced-pom.xml
admin_token
+/bin/
diff --git a/pom.xml b/pom.xml
index 4594c94..ebbc721 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -151,7 +150,7 @@
</plugin>
<!-- build tests jar, so extensions can use fastjerseytest class to build rest tests -->
- <plugin>
+ <!-- >plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
@@ -163,7 +162,7 @@
</goals>
</execution>
</executions>
- </plugin>
+ </plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@@ -470,6 +469,17 @@
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
+ <dependency>
+ <groupId>com.novell.ldap</groupId>
+ <artifactId>jldap</artifactId>
+ <version>4.3</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/com.unboundid/unboundid-ldapsdk -->
+ <dependency>
+ <groupId>com.unboundid</groupId>
+ <artifactId>unboundid-ldapsdk</artifactId>
+ <version>3.2.1</version>
+ </dependency>
<!--
not part of public release
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index 66c89b5..b30a915 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -27,6 +27,13 @@
public static final int NOT_SUPPORTED = 108;
/**
+ * 300 status codes for query language and serialization
+ */
+
+ public static final int NO_QUERY = 301;
+
+
+ /**
* 400 status codes for authorization and rewrite functions
*/
@@ -72,15 +79,18 @@
public static final int ARGUMENT_VALIDATION_FAILURE = 700;
// public static final int ARGUMENT_VALIDATION_FAILURE = 701;
+ // service status codes
+ public static final int CREATE_ACCOUNT_SUCCESSFUL = 700;
+ public static final int CREATE_ACCOUNT_FAILED = 701;
+ public static final int DELETE_ACCOUNT_SUCCESSFUL = 702;
+ public static final int DELETE_ACCOUNT_FAILED = 703;
+ public static final int UPDATE_ACCOUNT_SUCCESSFUL = 704;
+ public static final int UPDATE_ACCOUNT_FAILED = 705;
- /**
- * 300 status codes for query language and serialization
- */
-
- public static final int NO_QUERY = 301;
-
-
-
+ public static final int GET_ACCOUNT_SUCCESSFUL = 706;
+ public static final int GET_ACCOUNT_FAILED = 707;
+
+
public static final int STATUS_OK = 1000;
public static final int NOTHING_CHANGED = 1001;
public static final int REQUEST_INVALID = 1002;
@@ -90,7 +100,6 @@
* 2000 status and error codes for service level messages and callbacks
*/
-
public static final int ACCOUNT_DEACTIVATED = 2000;
public static final int ACCOUNT_CONFIRMATION_FAILED = 2001;
public static final int ALREADY_LOGGED_IN = 2002;
@@ -110,20 +119,10 @@
public static final int CLIENT_REMOVAL_FAILURE = 2012;
public static final int CLIENT_AUTHORIZATION_FAILURE = 2013;
-
-
- // service status codes
- public static final int CREATE_ACCOUNT_SUCCESSFUL = 700;
- public static final int CREATE_ACCOUNT_FAILED = 701;
- public static final int DELETE_ACCOUNT_SUCCESSFUL = 702;
- public static final int DELETE_ACCOUNT_FAILED = 703;
- public static final int UPDATE_ACCOUNT_SUCCESSFUL = 704;
- public static final int UPDATE_ACCOUNT_FAILED = 705;
-
- public static final int GET_ACCOUNT_SUCCESSFUL = 706;
- public static final int GET_ACCOUNT_FAILED = 707;
-
-
+ // 2020 - 2029 reserviert für LDAP-Fehlercodes - 21.04.17/FB
+ public static final int LDAP_BASE_ERRCODE = 2020;
+
+ /**/
private static StatusCodes codes;
private final Properties props;
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
index b608834..8829064 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -30,6 +30,11 @@
import java.util.List;
import java.util.Map;
+/* WKP: In computer software, a data access object (DAO) is an object that provides an abstract interface to some type
+ * of database or other persistence mechanism. By mapping application calls to the persistence layer, the DAO provides
+ * some specific data operations without exposing details of the database.
+ */
+
/**
* @author hanl
* @date 13/01/2014
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
index 8ddeb33..28e848b 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
@@ -35,8 +35,8 @@
}
- public void authorize (AuthCodeInfo info, User user)
- throws KustvaktException {
+ public void authorize (AuthCodeInfo info, User user) throws KustvaktException {
+
info.setUserId(user.getId());
this.storeInCache(info.getCode(), info);
}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
index 043b322..711e6d8 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
@@ -171,8 +171,7 @@
@Override
public ClientInfo mapRow (ResultSet rs, int rowNum)
throws SQLException {
- ClientInfo info = new ClientInfo(rs.getString("client_id"),
- "*****");
+ ClientInfo info = new ClientInfo(rs.getString("client_id"), "*****");
info.setConfidential(rs.getBoolean("is_confidential"));
info.setUrl(rs.getString("url"));
info.setId(rs.getInt("id"));
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
index c959e5e..483f292 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
@@ -19,8 +19,13 @@
import de.ids_mannheim.korap.user.*;
import de.ids_mannheim.korap.utils.StringUtils;
import de.ids_mannheim.korap.utils.TimeUtils;
+import de.ids_mannheim.korap.security.auth.LdapAuth3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+// import com.novell.ldap.*; search() funktioniert nicht korrekt, ausgewechselt gegen unboundID's Bibliothek 20.04.17/FB
+//Using JAR from unboundID:
+import com.unboundid.ldap.sdk.LDAPException;
+
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -171,6 +176,10 @@
// todo:
user = authenticateShib(attributes);
break;
+ case 2:
+ // IdM/LDAP: (09.02.17/FB)
+ user = authenticateIdM(username, password, attributes);
+ break;
default:
user = authenticate(username, password, attributes);
break;
@@ -232,8 +241,8 @@
//todo: what if attributes null?
- private User authenticate (String username, String password,
- Map<String, Object> attr) throws KustvaktException {
+ private User authenticate (String username, String password, Map<String, Object> attr) throws KustvaktException {
+
Map<String, Object> attributes = validator.validateMap(attr);
User unknown;
// just to make sure that the plain password does not appear anywhere in the logs!
@@ -250,7 +259,8 @@
else {
try {
unknown = entHandler.getAccount(username);
- } catch (EmptyResultException e) {
+ }
+ catch (EmptyResultException e) {
// mask exception to disable user guessing in possible attacks
throw new WrappedException(new KustvaktException(username,
StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
@@ -285,7 +295,7 @@
username);
}
- // bad credentials error has presedence over account locked or unconfirmed codes
+ // bad credentials error has precedence over account locked or unconfirmed codes
// since latter can lead to account guessing of third parties
if (user.isAccountLocked()) {
URIParam param = (URIParam) user.getField(URIParam.class);
@@ -324,6 +334,152 @@
}
+ /**
+ * authenticate using IdM (Identitätsmanagement) accessed by LDAP.
+ * @param username
+ * @param password
+ * @param attr
+ * @return
+ * @throws KustvaktException
+ * @date 09.02.17/FB
+ */
+ //todo: what if attributes null?
+
+ private User authenticateIdM (String username, String password, Map<String, Object> attr) throws KustvaktException {
+
+ Map<String, Object> attributes = validator.validateMap(attr);
+ User unknown = null;
+ // just to make sure that the plain password does not appear anywhere in the logs!
+
+ System.out.printf("Debug: authenticateIdM: entering for '%s'...\n", username);
+
+ /** wozu Apache Validatoren für User/Passwort für IdM/LDAP?
+ * siehe validation.properties. Abgeschaltet 21.04.17/FB
+ try {
+ validator.validateEntry(username, Attributes.USERNAME);
+ }
+ catch (KustvaktException e) {
+ throw new WrappedException(e, StatusCodes.LOGIN_FAILED, username);
+ }
+ */
+ if (username == null || username.isEmpty() || password == null || password.isEmpty() )
+ throw new WrappedException(new KustvaktException(username,
+ StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED);
+
+ // LDAP Access:
+ try {
+ // todo: unknown = ...
+ int ret = LdapAuth3.login(username, password);
+ System.out.printf("Debug: autenticationIdM: Ldap.login(%s) returns: %d.\n", username, ret);
+ if( ret != LdapAuth3.LDAP_AUTH_ROK )
+ {
+ jlog.error("LdapAuth3.login(username='{}') returns '{}'='{}'!", username, ret,
+ LdapAuth3.getErrMessage(ret));
+
+ // mask exception to disable user guessing in possible attacks
+ /* by Hanl
+ throw new WrappedException(new KustvaktException(username,
+ StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
+ username);
+ */
+ throw new WrappedException(
+ new KustvaktException(
+ username,
+ StatusCodes.LDAP_BASE_ERRCODE+ret,
+ LdapAuth3.getErrMessage(ret),
+ null),
+ StatusCodes.LOGIN_FAILED,
+ username);
+ }
+ }
+ catch ( LDAPException e ) {
+
+ jlog.error("Error: username='{}' -> '{}'!", username, e);
+ // mask exception to disable user guessing in possible attacks
+ /* by Hanl:
+ throw new WrappedException(new KustvaktException(username,
+ StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
+ username);
+ */
+ throw new WrappedException(
+ new KustvaktException(
+ username,
+ StatusCodes.LDAP_BASE_ERRCODE+LdapAuth3.LDAP_AUTH_RINTERR,
+ LdapAuth3.getErrMessage(LdapAuth3.LDAP_AUTH_RINTERR),
+ null),
+ StatusCodes.LOGIN_FAILED,
+ username);
+ }
+
+ // Create a User
+ User user = new KorAPUser();
+ user.setUsername(username);
+ unknown = user;
+
+ jlog.trace("Authentication: found username " + unknown.getUsername());
+
+ if (unknown instanceof KorAPUser) {
+ /* password already checked using LDAP:
+ if (password == null || password.isEmpty())
+ throw new WrappedException(new KustvaktException(
+ unknown.getId(), StatusCodes.BAD_CREDENTIALS),
+ StatusCodes.LOGIN_FAILED, username);
+
+ KorAPUser user = (KorAPUser) unknown;
+ boolean check = crypto.checkHash(password, user.getPassword());
+
+ if (!check) {
+ // the fail counter only applies for wrong password
+ jlog.warn("Wrong Password!");
+ processLoginFail(unknown);
+ throw new WrappedException(new KustvaktException(user.getId(),
+ StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
+ username);
+ }
+ */
+ // bad credentials error has precedence over account locked or unconfirmed codes
+ // since latter can lead to account guessing of third parties
+ /*
+ if (user.isAccountLocked()) {
+
+ URIParam param = (URIParam) user.getField(URIParam.class);
+
+ if (param.hasValues()) {
+ jlog.debug("Account is not yet activated for user '{}'",
+ user.getUsername());
+ if (TimeUtils.getNow().isAfter(param.getUriExpiration())) {
+ jlog.error(
+ "URI token is expired. Deleting account for user {}",
+ user.getUsername());
+ deleteAccount(user);
+ throw new WrappedException(new KustvaktException(
+ unknown.getId(), StatusCodes.EXPIRED,
+ "account confirmation uri has expired!",
+ param.getUriFragment()),
+ StatusCodes.LOGIN_FAILED, username);
+ }
+ throw new WrappedException(new KustvaktException(
+ unknown.getId(), StatusCodes.ACCOUNT_NOT_CONFIRMED),
+ StatusCodes.LOGIN_FAILED, username);
+ }
+ jlog.error("ACCESS DENIED: account not active for '{}'",
+ unknown.getUsername());
+ throw new WrappedException(new KustvaktException(
+ unknown.getId(), StatusCodes.ACCOUNT_DEACTIVATED),
+ StatusCodes.LOGIN_FAILED, username);
+ }
+ */
+
+ }
+ else if (unknown instanceof ShibUser) {
+ //todo
+ }
+
+ jlog.debug("Authentication done: " + username);
+ return unknown;
+
+ } // authenticateIdM
+
public boolean isRegistered (String username) {
User user;
if (username == null || username.isEmpty())
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/LdapAuth3.java b/src/main/java/de/ids_mannheim/korap/security/auth/LdapAuth3.java
new file mode 100644
index 0000000..c7f69fd
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/LdapAuth3.java
@@ -0,0 +1,355 @@
+/* - Klasse zum Implementieren einer Benutzer-Authentifikation mittels LDAP
+ * in der IDM-Datenbank (Identit�tsmanagement) von Eric Seubert, IDS.
+ * - externe Bibliothek ist Novel JLDAP.
+ * 27.01.17/FB
+ *
+ * Sourcen:
+ * - https://www.novell.com/documentation/developer/samplecode/jldap_sample/VerifyPassword.java.html
+ * - https://www.novell.com/documentation/developer/samplecode/jldap_sample/LDAPOIDs.java.html
+ * - https://www.novell.com/documentation/developer/jldap/jldapenu/data/a90352e.html
+ * WICHTIG:
+ * - Novell-Bibliothek liefert 0 Treffer, wenn man nacheinander sucht!
+ * Grund daf�r nicht gefunden.
+ *
+ * Version von unboundID - 19.04.17/FB
+ *
+ * UnboundID LDAP SDK For Java � 3.2.1
+ * The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use Java API for
+ * communicating with LDAP directory servers and performing related tasks like reading and writing LDIF,
+ * encoding and decoding data using base64 and ASN.1 BER, and performing secure communication. This package
+ * contains the Standard Edition of the LDAP SDK, which is a complete, general-purpose library for
+ * communicating with LDAPv3 directory servers.
+ * TODO:
+ * - gesichertes Login mit gesch�tztem Passwort.
+ * - Passwort des Admin verschl�sseln.
+ */
+
+package de.ids_mannheim.korap.security.auth;
+
+import com.unboundid.ldap.sdk.*;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * LDAP Login Tests
+ *
+ */
+public class LdapAuth3
+
+{
+ /* For SSL Connection to LDAP, see: https://www.novell.com/documentation/developer/jldap/jldapenu/data/cchcbejj.html.
+ * and use DEFAULT_SSL_PORT.
+ * For now, plain text connection is used.
+ * FB
+ */
+ final static Boolean DEBUGLOG = false; // log debug output.
+ final static String attC2 = "idsC2"; // if value == TRUE: registered for COSMAS II (KorAP) Service.
+ final static String attStatus = "idsStatus"; // value must be 0..2, 3 = locked account.
+ final static int ldapPort = 389; //LDAPConnection.DEFAULT_PORT;
+ // final static int ldapVersion = LDAPConnection.LDAP_V3;
+ final static String ldapHost = "ldap.ids-mannheim.de";
+ final static String ldapBase = "dc=ids-mannheim,dc=de";
+ final static String sLoginDN = "cn=casaling,dc=ids-mannheim,dc=de";
+ static String sPwd = null;
+
+ /**
+ * return : 0 = OK, User Account + Pwd are OK, no restrictions;
+ * 1 = internal error: cannot verify User+Pwd;
+ * 2 = User Account or Pwd unknown;
+ * 3 = User Account locked;
+ * 4 = User known, but has not registered to KorAP/C2 Service yet;
+ */
+
+ public static final int LDAP_AUTH_ROK = 0;
+ public static final int LDAP_AUTH_RINTERR = 1;
+ public static final int LDAP_AUTH_RUNKNOWN = 2;
+ public static final int LDAP_AUTH_RLOCKED = 3;
+ public static final int LDAP_AUTH_RNOTREG = 4;
+
+ /**
+ * getErrMessage:
+ * returns String Message for LDAP_AUTH_Rxxx code.
+ * @date 20.04.17/FB
+ * @param code
+ * @return Message in string form.
+ */
+ static String getErrMessage(int code)
+
+ {
+ switch(code)
+ {
+ case LDAP_AUTH_ROK:
+ return "LDAP Authentication successfull.";
+ case LDAP_AUTH_RINTERR:
+ return "LDAP Authentication failed due to an internal error!";
+ case LDAP_AUTH_RUNKNOWN:
+ return "LDAP Authentication failed due to unknown user or password!";
+ case LDAP_AUTH_RLOCKED:
+ return "LDAP Authentication: known user is locked!";
+ case LDAP_AUTH_RNOTREG:
+ return "LDAP Authentication: known user has not registered yet for COSMAS II/KorAP!";
+ default:
+ return "LDAP Authentication failed with unknown error code!";
+ }
+ } // getErrMessage
+
+ /**
+ * ldapCode2StatusCode:
+ * - converts a LDAP_AUTH_xxx Error Code to an Error Code of StatusCode.java.
+ * @param base : Base value inside of StatusCode.java reserved for LDAP_AUTH Error Codes.
+ * @param ldapErrCode : the LDAP_AUTH Error code
+ * @return the StatusCode in the range reserved for LDAP_AUTH Errors.
+ * @date 21.04.17/FB
+ */
+ public int ldapCode2StatusCode(int base, int ldapErrCode)
+
+ {
+ return base + ldapErrCode;
+ } // ldapCode2StatusCode
+
+ /*
+ * load properties for LDAP Handling.
+ * 17.02.17/FB
+ */
+
+ static String loadProp() throws IOException
+
+ {
+ String sPwd = null;
+ String sConfFile = System.getProperty("user.home") + "/.config/ldap.conf";
+ FileInputStream in;
+ Properties prop;
+
+ try {
+ in = new FileInputStream(sConfFile);
+ }
+ catch( IOException ex )
+ {
+ System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
+ ex.printStackTrace();
+ return null;
+ }
+
+ if( in == null )
+ {
+ System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
+ return null;
+ }
+ else
+ {
+ if( DEBUGLOG ) System.out.println("Debug: loaded: " + sConfFile);
+ }
+
+ prop = new Properties();
+ Enumeration<?> e;
+
+ try {
+ prop.load(in);
+ e = prop.propertyNames();
+
+ while( e.hasMoreElements() )
+ {
+ String key = (String)e.nextElement();
+ String val = prop.getProperty(key);
+ if( key.compareTo("pwd") == 0 )
+ return val;
+
+ //System.out.println("Property '" + key + "' = '" + val + "'.");
+ }
+ }
+ catch( IOException ex )
+ {
+ ex.printStackTrace();
+ }
+
+ return sPwd;
+
+ } // loadProp
+
+ /**
+ * ldapLogin
+ * Arguments:
+ * sUserDN : either COSMAS II specific Account Name or IDS wide (IDM) account name;
+ * sUserPwd : either COSMAS II specific Password or IDS wide (IDM) password;
+ * return : 0 = OK, User Account + Pwd are OK, no restrictions;
+ * 1 = internal error: cannot verify User+Pwd;
+ * 2 = User Account or Pwd unknown;
+ * 3 = User Account locked;
+ * 4 = User known, but has not registered to KorAP/C2 Service yet;
+ * LDAP Attributes that are checked (definition by Eric Seubert, 02.02.17):
+ * idsC2 = TRUE -> Zugang zu C2 (registriert und zugelassen)
+ * idsC2 = FALSE (bzw Attribut nicht vorhanden)
+ * -> kein Zugang zu C2 (nicht zugelassen, egal ob registriert oder nicht)
+ *
+ * idsStatus = 0 -> Nutzerkennung OK;
+ * idsStatus = 1 -> Nutzer ist kein aktiver IDS-Mitarbeiter
+ * idsStatus = 3 -> Nutzer ist LDAP-weit gesperrt
+ */
+
+ public static int login(String sUserDN, String sUserPwd) throws LDAPException
+
+ {
+
+ String sUserC2DN = sUserDN;
+ String sUserC2Pwd = sUserPwd;
+
+ String ldapFilter = String.format("(|(&(uid=%s)(userPassword=%s))(&(idsC2Profile=%s)(idsC2Password=%s)))",
+ sUserDN, sUserPwd, sUserC2DN, sUserC2Pwd);
+ SearchResult srchRes = null;
+
+ try{
+ sPwd = loadProp();
+ }
+ catch( IOException e )
+ {
+ System.out.println("Error: LDAPAuth.login: cannot load Property file!");
+ return LDAP_AUTH_RINTERR;
+ }
+
+ if( DEBUGLOG )
+ {
+ //System.out.printf("LDAP Version = %d.\n", LDAPConnection.LDAP_V3);
+ System.out.printf("LDAP Host & Port = '%s':%d.\n", ldapHost, ldapPort);
+ System.out.printf("Login User & Pwd = '%s' + '%s'\n", sUserDN, sUserPwd);
+ }
+
+ // LDAP Connection:
+ if( DEBUGLOG ) System.out.println("");
+
+ LDAPConnection lc = new LDAPConnection();
+ try {
+ // connect to LDAP Server:
+ lc.connect(ldapHost, ldapPort);
+ if( DEBUGLOG ) System.out.println("LDAP Connection = OK\n");
+ }
+ catch( LDAPException e)
+ {
+ System.out.printf("Connecting to LDAP Server: failed: '%s'!\n", e.toString());
+ return LDAP_AUTH_RINTERR;
+ }
+
+ if( DEBUGLOG )
+ System.out.printf("Debug: isConnected=%d\n", lc.isConnected() ? 1 : 0);
+
+ try {
+ // bind to server:
+ if( DEBUGLOG ) System.out.printf("Binding with '%s' + '%s'...\n", sLoginDN, sPwd);
+ lc.bind(sLoginDN, sPwd);
+ if( DEBUGLOG ) System.out.printf("Binding: OK.\n");
+ }
+ catch( LDAPException e )
+ {
+ System.out.printf("Binding failed: '%s'!\n", e.toString());
+ return ldapTerminate(lc, LDAP_AUTH_RINTERR);
+ }
+
+ if( DEBUGLOG )
+ System.out.printf("Debug: isConnected=%d\n", lc.isConnected() ? 1 : 0);
+
+ if( DEBUGLOG ) System.out.printf("Finding user '%s'...\n", sUserDN);
+ try{
+ // SCOPE_SUB = Scope Subtree.
+ if( DEBUGLOG ) System.out.printf("Finding Filter: '%s'.\n", ldapFilter);
+
+ // hier werden alle Attribute abgefragt:
+ //srchRes = lc.search(ldapBase, SearchScope.SUB, ldapFilter, null);
+ // wir fragen nur diese Attribute ab:
+ srchRes = lc.search(ldapBase, SearchScope.SUB, ldapFilter, attStatus, attC2);
+
+ if( DEBUGLOG ) System.out.printf("Finding '%s': %d entries.\n", sUserDN, srchRes.getEntryCount());
+ }
+ catch( LDAPSearchException e )
+ {
+ System.out.printf("Search for User failed: '%s'!\n", e.toString());
+ return ldapTerminate(lc, LDAP_AUTH_RUNKNOWN);
+ }
+
+ if( srchRes.getEntryCount() == 0 )
+ {
+ if( DEBUGLOG ) System.out.printf("Finding '%s': no entry found!\n", sUserDN);
+ return ldapTerminate(lc, LDAP_AUTH_RUNKNOWN);
+ }
+
+ if( DEBUGLOG ) System.out.println("Display results:");
+
+ Boolean
+ bStatus = false,
+ bC2 = false;
+
+ // Attribute pr�fen:
+ for (SearchResultEntry e : srchRes.getSearchEntries())
+ {
+ for( Attribute attr : e.getAttributes() )
+ {
+ Integer val;
+
+ if( DEBUGLOG )
+ System.out.printf(" att: '%s'='%s'.\n", attr.getName(), attr.getValue());
+
+ // checking pertinent attribut/value pairs:
+ // "idsStatus": values 0=OK, 1-3 = locked account.
+ if( attr.getName().equals(attStatus) )
+ {
+ if( (val = attr.getValueAsInteger()) == null || val != 0 )
+ {
+ if( DEBUGLOG ) System.out.printf("idsStatus = '%s' -> User locked!\n", attr.getValue());
+ return ldapTerminate(lc, LDAP_AUTH_RLOCKED);
+ }
+ if( DEBUGLOG ) System.out.printf(" att: '%s'='%s': OK.\n", attr.getName(), attr.getValue());
+ bStatus = true;
+ }
+
+ // "c2IDS" must be set to "TRUE" = User known, but has not yet registered to C2 Service -> KorAP Service.
+ if( attr.getName().equals(attC2) )
+ {
+ if( attr.getValue().equals("FALSE") )
+ {
+ if( DEBUGLOG )
+ System.out.printf("idsC2 = '%s'-> User known, but has not registered C2/KorAP Service yet!\n",
+ attr.getValue());
+ return ldapTerminate(lc, LDAP_AUTH_RNOTREG);
+ }
+ if( DEBUGLOG )
+ System.out.printf(" att: idsC2 = '%s'-> registered User: OK.\n", attr.getValue());
+ bC2 = true;
+ }
+ }
+
+ if( DEBUGLOG ) System.out.println();
+ }
+
+ if( bStatus == true && bC2 == true )
+ return ldapTerminate(lc, LDAP_AUTH_ROK); // OK.
+ else
+ return ldapTerminate(lc, LDAP_AUTH_RNOTREG); // Attribute konnten nicht gepr�ft werden.
+
+ } // ldapLogin
+
+/**
+ * ldapTerminate
+ */
+
+public static int ldapTerminate(LDAPConnection lc, int ret)
+
+ {
+ if( DEBUGLOG ) System.out.println("Terminating...");
+ /*
+ try{
+ lc.finalize();
+ if( DEBUGLOG ) System.out.println("Debug: finalize: OK.");
+ }
+ catch( LDAPException e )
+ {
+ System.out.printf("finalize failed: '%s'!\n", e.toString());
+ }
+ */
+
+ lc.close(null);
+ if( DEBUGLOG ) System.out.println("closing connection: done.\n");
+ return ret;
+ } // ldapTerminate
+
+}
+
diff --git a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
index 8fbd509..13b6d23 100644
--- a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
+++ b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
@@ -105,7 +105,7 @@
contextHandler.addServlet(new ServletHolder(
new ServletContainer(rc)), "/api/*");
- server.setHandler(contextHandler);
+ server.setHandler(contextHandler);
// if (kargs.sslContext != null) {
// SslSocketConnector sslConnector = new SslSocketConnector(
diff --git a/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java b/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
index ab37c80..7441edd 100644
--- a/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
+++ b/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
@@ -38,6 +38,8 @@
*/
// todo: use korap.config to get index location
public SearchKrill (String path) {
+
+ System.out.println("Debug: SearchKrill: path='" + path + "'.");
try {
if (path.equals(":temp:")) {
this.index = new KrillIndex();
@@ -46,7 +48,7 @@
File f = new File(path);
jlog.info("Loading index from " + path);
if (!f.exists()) {
- jlog.error("Index not found!");
+ jlog.error("Index not found: " + path + "!");
System.exit(-1);
}
this.index = new KrillIndex(new MMapDirectory(Paths.get(path)));
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/AuthService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/AuthService.java
index 8a7515a..ee63565 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/AuthService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/AuthService.java
@@ -2,6 +2,7 @@
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ResourceFilters;
+
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.config.BeansFactory;
import de.ids_mannheim.korap.exceptions.KustvaktException;
@@ -15,14 +16,21 @@
import de.ids_mannheim.korap.web.KustvaktServer;
import de.ids_mannheim.korap.web.filter.*;
import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
+
import org.slf4j.Logger;
+import javax.servlet.http.HttpServletRequest; // FB
import javax.ws.rs.*;
import javax.ws.rs.core.*;
+import javax.xml.ws.WebServiceContext; // FB
+import javax.xml.ws.handler.MessageContext; // FB
+import javax.annotation.Resource; // FB
+
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Iterator; // 07.02.17/FB
//import com.sun.xml.internal.messaging.saaj.util.Base64;
@@ -35,13 +43,14 @@
@Produces(MediaType.TEXT_HTML + ";charset=utf-8")
public class AuthService {
+ private static Boolean DEBUG_LOG = false;
+
//todo: bootstrap function to transmit certain default configuration settings and examples (example user queries,
// default usersettings, etc.)
private static Logger jlog = KustvaktLogger.getLogger(AuthService.class);
private AuthenticationManagerIface controller;
-
// private SendMail mail;
public AuthService () {
@@ -51,7 +60,7 @@
// this.mail = new SendMail(ExtConfiguration.getMailProperties());
}
-
+
/**
* represents json string with data. All GUI clients can access
* this method to get certain default values
@@ -90,17 +99,56 @@
@GET
@Path("apiToken")
//@ResourceFilters({HeaderFilter.class})
- public Response requestAPIToken (@Context HttpHeaders headers,
+ public Response requestAPIToken (
+ @Context HttpHeaders headers,
@Context Locale locale,
@HeaderParam(ContainerRequest.USER_AGENT) String agent,
@HeaderParam(ContainerRequest.HOST) String host,
@HeaderParam("referer-url") String referer,
- @QueryParam("scope") String scopes) {
+ @QueryParam("scope") String scopes,
+ // @Context WebServiceContext wsContext, // FB
+ @Context SecurityContext secCtx) {
+
List<String> auth = headers
.getRequestHeader(ContainerRequest.AUTHORIZATION);
String[] values = BasicHttpAuth.decode(auth.get(0));
+ if( DEBUG_LOG == true )
+ {
+ System.out.printf("Debug: AuthService.requestAPIToken...:\n");
+ System.out.printf("Debug: auth.size=%d\n", auth.size());
+ System.out.printf("auth.get(0)='%s'\n", auth.get(0));
+ System.out.printf("Debug: values.length=%d\n", values.length);
+ if( auth.size() > 0 )
+ {
+ Iterator it = auth.iterator();
+ while( it.hasNext() )
+ System.out.printf(" header '%s'\n", it.next());
+ }
+ if( values.length > 0 )
+ {
+ for(int i=0; i< values.length; i++)
+ {
+ System.out.printf(" values[%d]='%s'\n", i, values[i]);
+ }
+ }
+
+ MultivaluedMap<String,String> headerMap = headers.getRequestHeaders();
+ if( headerMap != null && headerMap.size() > 0 )
+ {
+ Iterator<String> it = headerMap.keySet().iterator();
+ while( it.hasNext() )
+ {
+ String key = (String)it.next();
+ List<String> vals= headerMap.get(key);
+ System.out.printf("Debug: requestAPIToken: '%s' = '%s'\n", key, vals);
+ }
+
+ }
+ System.out.printf("Debug: requestAPIToken: isSecure = %s.\n", secCtx.isSecure() ? "yes" : "no");
+ } // DEBUG_LOG
+
// "Invalid syntax for username and password"
if (values == null)
throw KustvaktResponseHandler
@@ -118,13 +166,12 @@
attr.put(Attributes.USER_AGENT, agent);
TokenContext context;
try {
- User user = controller.authenticate(0, values[0], values[1], attr);
- Userdata data = this.controller
- .getUserData(user, UserDetails.class);
+ // User user = controller.authenticate(0, values[0], values[1], attr); Implementation by Hanl
+ User user = controller.authenticate(2, values[0], values[1], attr); // Implementation with IdM/LDAP
+ // Userdata data = this.controller.getUserData(user, UserDetails.class); // Implem. by Hanl
// todo: is this necessary?
// attr.putAll(data.fields());
- context = controller.createTokenContext(user, attr,
- Attributes.API_AUTHENTICATION);
+ context = controller.createTokenContext(user, attr, Attributes.API_AUTHENTICATION);
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
@@ -175,8 +222,11 @@
throw KustvaktResponseHandler
.throwit(StatusCodes.BAD_CREDENTIALS);
+ // Implementation Hanl mit '|'. 16.02.17/FB
+ //if (values[0].equalsIgnoreCase("null")
+ // | values[1].equalsIgnoreCase("null"))
if (values[0].equalsIgnoreCase("null")
- | values[1].equalsIgnoreCase("null"))
+ || values[1].equalsIgnoreCase("null"))
throw KustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
Map<String, Object> attr = new HashMap<>();
diff --git a/src/main/resources/validation.properties b/src/main/resources/validation.properties
index 22f27c5..a38ae80 100644
--- a/src/main/resources/validation.properties
+++ b/src/main/resources/validation.properties
@@ -32,5 +32,6 @@
# as used by apache commons validator for strings
# Validator.string=^[\\.;:,\\=&\\*\\/\\/_()\\[\\]@\\|\\-0-9\\p{L}\\p{Space}]{0,1024}$
-Validator.username=^[A-Za-z_.\\d]{6,15}$
+#Validator.username=^[A-Za-z_.\\d]{6,15}$ by Hanl
+Validator.username=^[A-Za-z_.\\d]{3,20}$ # 21.04.17/FB
Validator.password=^((?=.*\\d)(?=.*[A-Za-z])(?!.*[\\(\\)-]).{8,20})$
\ No newline at end of file
diff --git a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
index 73324ea..50b1e6e 100644
--- a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
+++ b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
@@ -75,8 +75,8 @@
private static Logger jlog = LoggerFactory.getLogger(TestHelper.class);
private static final Map<String, Object> data = new HashMap<>();
static {
- data.put(Attributes.ID, 2);
- data.put(Attributes.USERNAME, "testUser1");
+ data.put(Attributes.ID, 3); // 2);
+ data.put(Attributes.USERNAME, "testUser1"); // bodmer funktioniert noch nicht
data.put(Attributes.PASSWORD, "testPass2015");
data.put(Attributes.FIRSTNAME, "test");
data.put(Attributes.LASTNAME, "user");
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
index c282708..87457bd 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
@@ -40,7 +40,7 @@
protected static Client client;
private static String[] classPackages = null;
- private static int PORT = 9000;
+ private static int PORT = 8089; // FB, was: 9000;
private static int PORT_IT = 1;
protected static String containerURI = "http://localhost/";
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktCoreRestTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktCoreRestTest.java
index 72a4a01..c36e48f 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktCoreRestTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktCoreRestTest.java
@@ -21,7 +21,9 @@
@BeforeClass
public static void configure () {
- FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.light",
+
+ // FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.light", version hanl
+ FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full", // volle Version FB
"de.ids_mannheim.korap.web.filter",
"de.ids_mannheim.korap.web.utils");
}