summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/db/LdapUser.java
blob: 0a1856515520fa49b1f43cc6a5625d04da309d74 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package org.openslx.imagemaster.db;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
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.message.SearchScope;
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.log4j.Logger;
import org.openslx.imagemaster.Globals;
import org.openslx.imagemaster.Globals.PropBool;
import org.openslx.imagemaster.Globals.PropString;
import org.openslx.imagemaster.session.User;
import org.openslx.imagemaster.thrift.iface.AuthenticationError;
import org.openslx.imagemaster.thrift.iface.AuthenticationException;
import org.openslx.imagemaster.util.Sha512Crypt;

/**
 * This TrustManager is used to accept custom certificates.
 * TODO: Once we are talking to the real server(s), we should
 * actually verify the cert, or we could just stop using ssl
 * altogether.
 */
class MyTrustManager implements X509TrustManager {

	@Override
	public void checkClientTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {}

	@Override
	public void checkServerTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return new X509Certificate[0];
	}
	
}

/**
 * Represents a user instance that was queries (primarily) from LDAP.
 * Additional information that is not provided by the LDAP server might
 * be fetched from other sources, like the local database.
 */
public class LdapUser extends User
{
	private static final Logger log = Logger.getLogger( LdapUser.class );
	
	protected LdapUser(int userId, String username, String password, String organization,
			String firstName, String lastName, String eMail,
			String satelliteAddress) {
		super(userId, username, password, organization, firstName, lastName, eMail,
				satelliteAddress);
	}
	
	/**
	 * Query LDAP for user with given login
	 * @param login  Login of user in the form "user@organization.com"
	 * @return instance of LDAPUser for matching entry from LDAP, or null if not found
	 */
	public static LdapUser forLogin( final String login, final String password ) throws AuthenticationException {
		String username, organization, firstName, lastName, eMail, satelliteAddress;
		
		String[] temp = login.split("@");
		if (temp.length != 2) throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Login must be in form user@organization.com");
		username = temp[0];
		
		LdapConnectionConfig ldapConfig = new LdapConnectionConfig();
		ldapConfig.setTrustManagers(new MyTrustManager());
		ldapConfig.setLdapPort(Globals.getPropertyInt( Globals.PropInt.LDAPPORT ));
		ldapConfig.setLdapHost(Globals.getPropertyString( Globals.PropString.LDAPHOST ));
		ldapConfig.setUseSsl(Globals.getPropertyBool( PropBool.LDAPSSL ));
		
		LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig );
		
		// bind connection
		try {
			if ( connection.connect() ) {
				String name = Globals.getPropertyString( PropString.LDAPBINDQUERY ).replace("%", username);
				connection.bind(name, password);
			}
		} catch (LdapException e1) {
			log.warn( "Connection to LDAP failed: " + e1.getMessage() );
		}
		
		if ( !connection.isConnected() ) {
			try {
				connection.unBind();
				connection.close();
			} catch (LdapException | IOException e) {
				// Not doing anything here, as ldap already failed...
			}
			throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Could not connect to LDAP server." );
		}
		
		// test authorization
		if ( !connection.isAuthenticated() ) {
			try {
				connection.unBind();
				connection.close();
			} catch (LdapException | IOException e) {
				// Failing disconnect... Can't do much about it, just go on
			}
			throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Could not authenticate to LDAP server. Invalid credentials?" );
		}
		
		// make search query
		try {
			EntryCursor cursor = connection.search(Globals.getPropertyString( Globals.PropString.LDAPSEARCHBASEDN ),
					Globals.getPropertyString( Globals.PropString.LDAPSEARCHFILTER ).replace("%", username), SearchScope.SUBTREE);
			// only use the first result
			cursor.next();
			Entry entry = cursor.get();
			username = entry.get("uid").getString();
			organization = "Test Organization"; // will be filled with bwIDM LDAP server
			firstName = entry.get("givenName").getString();
			lastName = entry.get("sn").getString();
			eMail = entry.get("rufPreferredMail").getString();
			// get the satellite address from db
			DbSatellite dbSatellite = DbSatellite.fromOrganization(organization);
			if (dbSatellite != null) {
				satelliteAddress = dbSatellite.getAddress();
			} else {
				// TODO: Organization is not known.. Handle this
				satelliteAddress = "addressNotKown";
			}
		} catch (LdapException | CursorException e1) {
			return null;
		} finally {
			// close connection
			try {
				connection.unBind();
			} catch (LdapException e) {
				return null;
			}
			try {
				connection.close();
			} catch (IOException e) {
				return null;
			}
		}
		return new LdapUser(0, username, Sha512Crypt.Sha512_crypt(password, null, 0), organization, firstName, lastName, eMail, satelliteAddress);
	}
}