Package hudson.plugins.mysql

Source Code of hudson.plugins.mysql.MySQLSecurityRealm$DescriptorImpl

/**
* The person or persons who have associated work with this document (the
* "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
* his knowledge, the work of authorship identified is in the public domain of
* the country from which the work is published, or (b) hereby dedicates
* whatever copyright the dedicators holds in the work of authorship identified
* below (the "Work") to the public domain. A certifier, moreover, dedicates any
* copyright interest he may have in the associated work, and for these
* purposes, is described as a "dedicator" below.
*
* A certifier has taken reasonable steps to verify the copyright status of this
* work. Certifier recognizes that his good faith efforts may not shield him
* from liability if in fact the work certified is not in the public domain.
*
* Dedicator makes this dedication for the benefit of the public at large and to
* the detriment of the Dedicator's heirs and successors. Dedicator intends this
* dedication to be an overt act of relinquishment in perpetuity of all present
* and future rights under copyright law, whether vested or contingent, in the
* Work. Dedicator understands that such relinquishment of all rights includes
* the relinquishment of all rights to enforce (by lawsuit or otherwise) those
* copyrights in the Work.
*
* Dedicator recognizes that, once placed in the public domain, the Work may be
* freely reproduced, distributed, transmitted, used, modified, built upon, or
* otherwise exploited by anyone for any purpose, commercial or non-commercial,
* and in any way, including by methods that have not yet been invented or
* conceived.
*/
package hudson.plugins.mysql;

import hudson.Extension;
import hudson.Util;
import hudson.model.Descriptor;
import hudson.plugins.mysql.crypt.Cipher;
import hudson.security.AbstractPasswordBasedSecurityRealm;
import hudson.security.GroupDetails;
import hudson.security.SecurityRealm;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.springframework.dao.DataAccessException;

/**
* Implementation of the AbstractPasswordBasedSecurityRealm that uses a MySQL
* database as the source of authentication information.
*
* @author Alex Ackerman
*/
public class MySQLSecurityRealm extends AbstractPasswordBasedSecurityRealm
{

    @DataBoundConstructor
    public MySQLSecurityRealm(String myServer, String myUsername, String myPassword,
            String myPort, String myDatabase, String myDataTable, String myUserField,
            String myPassField, String myCondition, String encryption)
    {
        this.myServer = Util.fixEmptyAndTrim(myServer);
        this.myUsername = Util.fixEmptyAndTrim(myUsername);
        this.myPassword = Util.fixEmptyAndTrim(myPassword);
        this.myPort = Util.fixEmptyAndTrim(myPort);
        if ((myPort == null) || (myPort.equals("")))
            myPort = "3306";
        this.myPort = myPort;
        this.myDatabase = Util.fixEmptyAndTrim(myDatabase);
        this.myCondition = Util.fixEmptyAndTrim(myCondition);
        this.myDataTable = Util.fixEmptyAndTrim(myDataTable);
        this.myUserField = Util.fixEmptyAndTrim(myUserField);
        this.myPassField = Util.fixEmptyAndTrim(myPassField);
        this.encryption = encryption;
    }

    public static final class DescriptorImpl extends Descriptor<SecurityRealm>
    {
        @Override
        public String getHelpFile() {
            return "/plugin/mysql-auth/help/overview.html";
        }
       
        @Override
        public String getDisplayName() {
            return Messages.DisplayName();
        }
    }

    @Extension
    public static DescriptorImpl install()
    {
        return new DescriptorImpl();
    }

    /**
     * Authenticates the specified user using the password against the stored
     * database configuration.
     *
     * @param username      The username to lookup
     * @param password      The password to use for authentication
     * @return              A UserDetails object containing information about
     *                      the user.
     * @throws AuthenticationException  Thrown when the username/password do
     *                                  not match stored values.
     */
    @Override
    protected UserDetails authenticate(String username, String password)
            throws AuthenticationException
    {
        UserDetails userDetails = null;

        String connectionString;

        connectionString = "jdbc:mysql://" + myServer + "/" +
                myDatabase;
        LOGGER.fine("MySQLSecurity: Connection String - " + connectionString);
        Connection conn = null;
        try
        {
            // Connect to the database
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(connectionString,
                    myUsername, myPassword);
            LOGGER.info("MySQLSecurity: Connection established.");

            // Prepare the statement and query the user table
            // TODO: Review userQuery to see if there's a better way to do this
            String userQuery = "SELECT * FROM " + myDataTable + " WHERE " +
                    myUserField + " = ?";
            PreparedStatement statement = conn.prepareStatement(userQuery);
            statement.setString(1, myDataTable);
            LOGGER.fine("MySQLSecurity: Query Info - ");
            LOGGER.fine("- Table: " + myDataTable);
            LOGGER.fine("- User Field: " + myUserField);
            LOGGER.fine("- Username: " + myUsername);
            //statement.setString(2, myUserField);
            statement.setString(1, username);
            ResultSet results = statement.executeQuery();
            LOGGER.fine("MySQLSecurity: Query executed.");

            if (results.first())
            {
                String storedPassword = results.getString(myPassField);
                Cipher cipher;
                if (encryption.equals(Cipher.CRYPT))
                {
                    String salt = storedPassword.substring(0, 2);
                    cipher = new Cipher(encryption, salt);
                }
                else
                {
                    cipher = new Cipher(encryption);
                }
                String encryptedPassword = cipher.encode(password.trim());
                LOGGER.fine("Encrypted Password: " + encryptedPassword);
                LOGGER.fine("Stored Password: " + storedPassword);
                if (!storedPassword.equals(encryptedPassword))
                {
                    LOGGER.warning("MySQLSecurity: Invalid Username or Password");
                    throw new MySQLAuthenticationException("Invalid Username or Password");
                }
                else
                {
                    // Password is valid.  Build UserDetail
                    Set<GrantedAuthority> groups = new HashSet<GrantedAuthority>();
                    groups.add(SecurityRealm.AUTHENTICATED_AUTHORITY);
                    userDetails = new MySQLUserDetail(username, encryptedPassword,
                            true, true, true, true,
                            groups.toArray(new GrantedAuthority[groups.size()]));
                }
            }
            else
            {
                LOGGER.warning("MySQLSecurity: Invalid Username or Password");
                throw new MySQLAuthenticationException("Invalid Username or Password");
            }

        }
        catch (Exception e)
        {
            LOGGER.warning("MySQLSecurity Realm Error: " + e.getLocalizedMessage());
        }
        finally
        {
            if (conn != null)
            {
                try
                {
                    conn.close();
                    LOGGER.info("MySQLSecurity: Connection closed.");
                }
                catch (Exception ex)
                {
                    /** Ignore any errors **/
                }
            }
        }

        return userDetails;
    }

    /**
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     * @throws DataAccessException
     */
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException
    {
        UserDetails user = null;
        String connectionString;

        connectionString = "jdbc:mysql://" + myServer + "/" +
                myDatabase;
        LOGGER.info("MySQLSecurity: Connection String - " + connectionString);
        Connection conn = null;
        try
        {
            // Connect to the database
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(connectionString,
                    myUsername, myPassword);
            LOGGER.info("MySQLSecurity: Connection established.");

            // Prepare the statement and query the user table
            // TODO: Review userQuery to see if there's a better way to do this
            String userQuery = "SELECT * FROM " + myDataTable + " WHERE " +
                    myUserField + " = ?";
            PreparedStatement statement = conn.prepareStatement(userQuery);
            //statement.setString(1, myDataTable);
            //statement.setString(2, myUserField);
            statement.setString(1, username);
            ResultSet results = statement.executeQuery();
            LOGGER.fine("MySQLSecurity: Query executed.");

            // Grab the first result (should be only user returned)
            if (results.first())
            {
                // Build the user detail
                Set<GrantedAuthority> groups = new HashSet<GrantedAuthority>();
                groups.add(SecurityRealm.AUTHENTICATED_AUTHORITY);
                user = new MySQLUserDetail(username, results.getString(myPassField),
                            true, true, true, true,
                            groups.toArray(new GrantedAuthority[groups.size()]));
            }
            else
            {
                LOGGER.warning("MySQLSecurity: Invalid Username or Password");
                throw new UsernameNotFoundException("MySQL: User not found");
            }

        }
        catch (Exception e)
        {
            LOGGER.warning("MySQLSecurity Realm Error: " + e.getLocalizedMessage());
        }
        finally
        {
            if (conn != null)
            {
                try
                {
                    conn.close();
                    LOGGER.info("MySQLSecurity: Connection closed.");
                }
                catch (Exception ex)
                {
                    /** Ignore any errors **/
                }
            }
        }
        return user;
    }

    /**
     *
     * @param groupname
     * @return
     * @throws UsernameNotFoundException
     * @throws DataAccessException
     */
    @Override
    public GroupDetails loadGroupByGroupname(String groupname)
            throws UsernameNotFoundException, DataAccessException
    {
        LOGGER.warning("ERROR: Group lookup is not supported.");
        throw new UsernameNotFoundException("MySQLSecurityRealm: Non-supported function");
    }

    class Authenticator extends AbstractUserDetailsAuthenticationProvider
    {

        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails,
                UsernamePasswordAuthenticationToken authentication)
                throws AuthenticationException {
            // Assumed to be done in the retrieveUser method
        }

        @Override
        protected UserDetails retrieveUser(String username,
                UsernamePasswordAuthenticationToken authentication)
                throws AuthenticationException {
            return MySQLSecurityRealm.this.authenticate(username,
                    authentication.getCredentials().toString());
        }

    }

    public String getMyServer()
    {
        return myServer;
    }

    public String getMyUsername()
    {
        return myUsername;
    }

    public String getMyPassword()
    {
        return myPassword;
    }

    public String getMyDatabase()
    {
        return myDatabase;
    }

    public String getMyDataTable()
    {
        return myDataTable;
    }

    public String getMyUserField()
    {
        return myUserField;
    }

    public String getMyPassField()
    {
        return myPassField;
    }

    public String getMyPort()
    {
        return myPort;
    }
   
    public String getMyCondition()
    {
        return myCondition;
    }

    public String getEncryption()
    {
        return encryption;
    }

    /**
     * Logger for debugging purposes.
     */
    private static final Logger LOGGER =
            Logger.getLogger(MySQLSecurityRealm.class.getName());

    /**
     * The MySQL server to use.
     */
    private String myServer;
    /**
     * The MySQL username to use to connect to the database server.
     */
    private String myUsername;
    /**
     * The MySQL password to use to connect to the database server.
     */
    private String myPassword;
    /**
     * The database containing the user's authentication information.
     */
    private String myDatabase;
    /**
     * The table containing a user's authentication information.
     */
    private String myDataTable;
    /**
     * Username field in the database.
     */
    private String myUserField;
    /**
     * Password field in the database.
     */
    private String myPassField;
    /**
     * Port used by the MySQL server.  If not specified, defaults to 3306.
     */
    private String myPort;
    /**
     * Condition string which may prevent user from being enabled.  This is a
     * field used by Bugzilla.
     */
    private String myCondition;

    /**
     * Encryption type used for the password
     */
    private String encryption;

}
TOP

Related Classes of hudson.plugins.mysql.MySQLSecurityRealm$DescriptorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.