001    package org.esupportail.cas.server.handlers.database;
002    
003    import java.sql.Connection;
004    import java.sql.ResultSet;
005    import java.sql.SQLException;
006    import java.sql.Statement;
007    
008    import org.dom4j.Element;
009    import org.esupportail.cas.server.util.RedundantHandler;
010    import org.esupportail.cas.server.util.crypt.Crypt;
011    import org.esupportail.cas.server.util.log.Log;
012    
013    /**
014     * This class also implements a database server class, which can
015     * authenticate users by searching into a database. It is used by 
016     * SearchDatabaseHandler.
017     *
018     * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
019     * @author Jean-Baptiste Daniel <danielj at users.sourceforge.net>
020     * @author Arunas Stockus <arunas.stockus at univ-lr.fr>
021     */
022    public final class QueryDatabaseServer extends DatabaseServer {
023            
024            /**
025             * Constructor.
026             *
027             * @param handlerDebug debugging mode of the handler
028             * @param handler      the handler the server will be used by
029             * @param serverElement the XML element that declares the server 
030             * @throws Exception Exception
031             */
032            public QueryDatabaseServer(
033                            final Boolean handlerDebug,
034                            final RedundantHandler handler,
035                            final Element serverElement) throws Exception {
036                    super(handlerDebug, handler, serverElement);
037                    traceBegin();
038                    traceEnd();
039            }
040            
041            /**
042             * Try to authenticate a user (by searching into the handler's database).
043             *
044             * @param username the user's name
045             * @param password the user's password
046             *
047             * @return Server.AUTHENTICATE_SUCCESS, Server.AUTHENTICATE_NOAUTH
048             * or Server.AUTHENTICATE_FAILURE.
049             */     
050            public int authenticate(
051                            final String username,
052                            final String password) {
053                    Connection connection = null;
054                    traceBegin();
055                    
056                    if (username.indexOf('\'') != -1) {
057                            Log.info("Username \"" + username + "\" contains a single quote, this could be an attack.");
058                            trace("Usernames containing single quotes are rejected.");
059                            traceEnd("AUTHENTICATE_NOAUTH");
060                            return AUTHENTICATE_NOAUTH;
061                    }
062                    
063                    QueryDatabaseHandler handler = (QueryDatabaseHandler) getHandler();
064                    
065                    try {
066                            
067                            connection = connect(handler.getBindUsername(), handler.getBindPassword());
068                            switch (getConnectError()) {
069                                    case CONNECT_NOAUTH:
070                                    case CONNECT_FAILURE:
071                                            trace("Connection failed.");
072                                            traceEnd("AUTHENTICATE_FAILURE");
073                                            return AUTHENTICATE_FAILURE;
074                                    default: //CONNECT_SUCCESS
075                                            break;
076                            }
077                            
078                            trace("Create an SQL statement...");
079                            Statement statement = connection.createStatement();
080                            
081                            String sqlQuery = handler.getUserSqlQuery(username);
082                            
083                            trace("Execute the query (" + sqlQuery + ")...");
084                            ResultSet statementResult = statement.executeQuery(sqlQuery);
085                            
086                            if (statementResult.next()) { 
087                                    
088                                    String encryption = handler.getEncryption();
089                                    trace("Username found, checking password (" + encryption + ")...");
090                                    // now for each result, encrypt the password (if needed) and compare
091                                    String encryptedPassword = statementResult.getString(1);
092                                    if (Crypt.match(encryption, password, encryptedPassword)) {
093                                            // username/password matches
094                                            trace("Password matches.");
095                                            trace("Closing the connection...");
096                                            connection.close();
097                                            traceEnd("AUTHENTICATE_SUCCESS");
098                                            return AUTHENTICATE_SUCCESS;
099                                    } else {
100                                            trace("Username found but password does not match.");
101                                    }
102                            }
103                            // no match found
104                            trace("Search failed.");
105                            trace("Closing the connection...");
106                            connection.close();
107                            traceEnd("AUTHENTICATE_NOAUTH");
108                            return AUTHENTICATE_NOAUTH;
109                            
110                    } catch (Exception e) {
111                            // something went wrong
112                            trace("Search failure: " + e.toString());
113                            try {
114                                    trace("Closing the connection...");
115                                    connection.close();
116                            } catch (SQLException e1) {
117                                    Log.warn("Connection could not be closed.");
118                            }
119                            traceEnd("AUTHENTICATE_FAILURE"); 
120                            return AUTHENTICATE_FAILURE; 
121                    }
122                    
123            }
124    
125    }