<commit_before>/**
 * OWASP Enterprise Security API (ESAPI)
 * 
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * http://www.owasp.org/esapi.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 * 
 * The ESAPI is published by OWASP under the LGPL. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 * 
 * @author <NAME> <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.owasp.esapi.errors.AuthenticationAccountsException;
import org.owasp.esapi.errors.AuthenticationCredentialsException;
import org.owasp.esapi.errors.AuthenticationException;
import org.owasp.esapi.errors.AuthenticationHostException;
import org.owasp.esapi.errors.AuthenticationLoginException;
import org.owasp.esapi.errors.EncryptionException;
import org.owasp.esapi.errors.IntrusionException;
import org.owasp.esapi.interfaces.ILogger;
import org.owasp.esapi.interfaces.IUser;

/**
 * Reference implementation of the IUser interface. This implementation is serialized into a flat file in a simple format.
 * 
 * @author <NAME> (jeff.williams .at. aspectsecurity.com) <a
 *         href="http://www.aspectsecurity.com">Aspect Security</a>
 * @since June 1, 2007
 * @see org.owasp.esapi.interfaces.IUser
 */
public class User implements IUser, Serializable {


	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The logger. */
	private static final Logger logger = Logger.getLogger("ESAPI", "User");
    
	/** The account name. */
	private String accountName = "";

	/** The screen name. */
	private String screenName = "";

	/** The hashed password. */
	private String hashedPassword = "";

	/** The old password hashes. */
	private List oldPasswordHashes = new ArrayList();

	/** The remember token. */
	private String rememberToken = "";

	/** The csrf token. */
	private String csrfToken = "";

	/** The roles. */
	private Set roles = new HashSet();

	/** The locked. */
	private boolean locked = false;

	/** The logged in. */
	private boolean loggedIn = true;

    /** The enabled. */
	private boolean enabled = false;

    /** The last host address used. */
    private String lastHostAddress;

	/** The last password change time. */
	private Date lastPasswordChangeTime = new Date();

	/** The last login time. */
	private Date lastLoginTime = new Date();

	/** The last failed login time. */
	private Date lastFailedLoginTime = new Date();
	
	/** The expiration time. */
	private Date expirationTime = new Date(Long.MAX_VALUE);

	/** A flag to indicate that the password must be changed before the account can be used. */
	// FIXME: ENHANCE enable this required password change feature?
	// private boolean requiresPasswordChange = true;
	
	/** The failed login count. */
	private int failedLoginCount = 0;
    
	/** Intrusion detection events */
	private Map events = new HashMap();

    
    // FIXME: ENHANCE consider adding these for access control support
    //
    //private String authenticationMethod = null;
    //
    //private String connectionChannel = null;
    
	/**
	 * Instantiates a new user.
	 */
	protected User() {
		// hidden
	}

	/**
	 * Instantiates a new user.
	 * 
	 * @param line
	 *            the line
	 */
	protected User(String line) {
		String[] parts = line.split("\\|");
		this.accountName = parts[0].trim().toLowerCase();
		// FIXME: AAA validate account name
		this.hashedPassword = parts[1].trim();
        
		this.roles.addAll(Arrays.asList(parts[2].trim().toLowerCase().split(" *, *")));
		this.locked = !"unlocked".equalsIgnoreCase(parts[3].trim());
		this.enabled = "enabled".equalsIgnoreCase(parts[4].trim());
		this.rememberToken = parts[5].trim();

		// generate a new csrf token
        this.resetCSRFToken();
        
		this.oldPasswordHashes.addAll( Arrays.asList(parts[6].trim().split(" *, *")));
        this.lastHostAddress = parts[7].trim();
        this.lastPasswordChangeTime = new Date( Long.parseLong(parts[8].trim()));
		this.lastLoginTime = new Date( Long.parseLong(parts[9].trim()));
		this.lastFailedLoginTime = new Date( Long.parseLong(parts[10].trim()));
		this.expirationTime = new Date( Long.parseLong(parts[11].trim()));
		this.failedLoginCount = Integer.parseInt(parts[12].trim());
	}

	/**
	 * Only for use in creating the Anonymous user.
	 * 
	 * @param accountName
	 *            the account name
	 * @param password
	 *            the password
	 */
	protected User( String accountName, String password ) {
		this.accountName = accountName.toLowerCase();
	}

	/**
	 * Instantiates a new user.
	 * 
	 * @param accountName
	 *            the account name
	 * @param password1
	 *            the password1
	 * @param password2
	 *            the password2
	 * 
	 * @throws AuthenticationException
	 *             the authentication exception
	 */
	User(String accountName, String password1, String password2) throws AuthenticationException {
		
		ESAPI.authenticator().verifyAccountNameStrength("Create User", accountName);

		if ( password1 == null ) {
			throw new AuthenticationCredentialsException( "Invalid account name", "Attempt to create account " + accountName + " with a null password" );
		}
		ESAPI.authenticator().verifyPasswordStrength(password1, null );
		
		if (!password1.equals(password2)) throw new AuthenticationCredentialsException("Passwords do not match", "Passwords for " + accountName + " do not match");
		
		this.accountName = accountName.toLowerCase();
		try {
		    setHashedPassword( ESAPI.encryptor().hash(password1, this.accountName) );
		} catch (EncryptionException ee) {
		    throw new AuthenticationException("Internal error", "Error hashing password for " + this.accountName, ee);
		}
		expirationTime = new Date( System.currentTimeMillis() + (long)1000 * 60 * 60 * 24 * 90 );  // 90 days
		logger.logCritical(Logger.SECURITY, "Account created successfully: " + accountName );
	}

	/* (non-Javadoc)
	 * @see org.owasp.esapi.interfaces.IUser#addRole(java.lang.String)
	 */
	public void addRole(String role) throws AuthenticationException {
		String roleName = role.toLowerCase();
		if ( ESAPI.validator().isValidDataFromBrowser("addRole", "RoleName", roleName) ) {
			roles.add(roleName);
			logger.logCritical(Logger.SECURITY, "Role " + roleName + " added to " + getAccountName() );
		} else {
			throw new AuthenticationAccountsException( "Add role failed", "Attempt to add invalid role " + roleName + " to " + getAccountName() );
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.owasp.esapi.interfaces.IUser#addRoles(java.util.Set)
	 */
	public void addRoles(Set newRoles) throws AuthenticationException {
		Iterator i = newRoles.iterator();
		while(i.hasNext()) {
			addRole((String)i.next());
		}
	}

	 /**
	 * Adds a security event to the user.
	 * 
	 * @param event the event
	 */
	public void addSecurityEvent(String eventName) throws IntrusionException {
		Event event = (Event)events.get( eventName );
		if ( event == null ) {
			event = new Event( eventName );
			events.put( eventName, event );
		}
<commit_msg>major revision to Validation scheme. IValidator and Validator were modified the greatest<commit_after>/**
 * OWASP Enterprise Security API (ESAPI)
 * 
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * http://www.owasp.org/esapi.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 * 
 * The ESAPI is published by OWASP under the LGPL. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 * 
 * @author <NAME> <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.owasp.esapi.errors.AuthenticationAccountsException;
import org.owasp.esapi.errors.AuthenticationCredentialsException;
import org.owasp.esapi.errors.AuthenticationException;
import org.owasp.esapi.errors.AuthenticationHostException;
import org.owasp.esapi.errors.AuthenticationLoginException;
import org.owasp.esapi.errors.EncryptionException;
import org.owasp.esapi.errors.IntrusionException;
import org.owasp.esapi.interfaces.ILogger;
import org.owasp.esapi.interfaces.IUser;

/**
 * Reference implementation of the IUser interface. This implementation is serialized into a flat file in a simple format.
 * 
 * @author <NAME> (jeff.williams .at. aspectsecurity.com) <a
 *         href="http://www.aspectsecurity.com">Aspect Security</a>
 * @since June 1, 2007
 * @see org.owasp.esapi.interfaces.IUser
 */
public class User implements IUser, Serializable {


	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The logger. */
	private static final Logger logger = Logger.getLogger("ESAPI", "User");
    
	/** The account name. */
	private String accountName = "";

	/** The screen name. */
	private String screenName = "";

	/** The hashed password. */
	private String hashedPassword = "";

	/** The old password hashes. */
	private List oldPasswordHashes = new ArrayList();

	/** The remember token. */
	private String rememberToken = "";

	/** The csrf token. */
	private String csrfToken = "";

	/** The roles. */
	private Set roles = new HashSet();

	/** The locked. */
	private boolean locked = false;

	/** The logged in. */
	private boolean loggedIn = true;

    /** The enabled. */
	private boolean enabled = false;

    /** The last host address used. */
    private String lastHostAddress;

	/** The last password change time. */
	private Date lastPasswordChangeTime = new Date();

	/** The last login time. */
	private Date lastLoginTime = new Date();

	/** The last failed login time. */
	private Date lastFailedLoginTime = new Date();
	
	/** The expiration time. */
	private Date expirationTime = new Date(Long.MAX_VALUE);

	/** A flag to indicate that the password must be changed before the account can be used. */
	// FIXME: ENHANCE enable this required password change feature?
	// private boolean requiresPasswordChange = true;
	
	/** The failed login count. */
	private int failedLoginCount = 0;
    
	/** Intrusion detection events */
	private Map events = new HashMap();

    
    // FIXME: ENHANCE consider adding these for access control support
    //
    //private String authenticationMethod = null;
    //
    //private String connectionChannel = null;
	
    /**
     * TODO: Push to configuration? 
     * Maximum legal role size 
     **/
    private final int MAX_ROLE_LENGTH = 250;
    
	/**
	 * Instantiates a new user.
	 */
	protected User() {
		// hidden
	}

	/**
	 * Instantiates a new user.
	 * 
	 * @param line
	 *            the line
	 */
	protected User(String line) {
		String[] parts = line.split("\\|");
		this.accountName = parts[0].trim().toLowerCase();
		// FIXME: AAA validate account name
		this.hashedPassword = parts[1].trim();
        
		this.roles.addAll(Arrays.asList(parts[2].trim().toLowerCase().split(" *, *")));
		this.locked = !"unlocked".equalsIgnoreCase(parts[3].trim());
		this.enabled = "enabled".equalsIgnoreCase(parts[4].trim());
		this.rememberToken = parts[5].trim();

		// generate a new csrf token
        this.resetCSRFToken();
        
		this.oldPasswordHashes.addAll( Arrays.asList(parts[6].trim().split(" *, *")));
        this.lastHostAddress = parts[7].trim();
        this.lastPasswordChangeTime = new Date( Long.parseLong(parts[8].trim()));
		this.lastLoginTime = new Date( Long.parseLong(parts[9].trim()));
		this.lastFailedLoginTime = new Date( Long.parseLong(parts[10].trim()));
		this.expirationTime = new Date( Long.parseLong(parts[11].trim()));
		this.failedLoginCount = Integer.parseInt(parts[12].trim());
	}

	/**
	 * Only for use in creating the Anonymous user.
	 * 
	 * @param accountName
	 *            the account name
	 * @param password
	 *            the password
	 */
	protected User( String accountName, String password ) {
		this.accountName = accountName.toLowerCase();
	}

	/**
	 * Instantiates a new user.
	 * 
	 * @param accountName
	 *            the account name
	 * @param password1
	 *            the password1
	 * @param password2
	 *            the password2
	 * 
	 * @throws AuthenticationException
	 *             the authentication exception
	 */
	User(String accountName, String password1, String password2) throws AuthenticationException {
		
		ESAPI.authenticator().verifyAccountNameStrength("Create User", accountName);

		if ( password1 == null ) {
			throw new AuthenticationCredentialsException( "Invalid account name", "Attempt to create account " + accountName + " with a null password" );
		}
		ESAPI.authenticator().verifyPasswordStrength(password1, null );
		
		if (!password1.equals(password2)) throw new AuthenticationCredentialsException("Passwords do not match", "Passwords for " + accountName + " do not match");
		
		this.accountName = accountName.toLowerCase();
		try {
		    setHashedPassword( ESAPI.encryptor().hash(password1, this.accountName) );
		} catch (EncryptionException ee) {
		    throw new AuthenticationException("Internal error", "Error hashing password for " + this.accountName, ee);
		}
		expirationTime = new Date( System.currentTimeMillis() + (long)1000 * 60 * 60 * 24 * 90 );  // 90 days
		logger.logCritical(Logger.SECURITY, "Account created successfully: " + accountName );
	}

	/* (non-Javadoc)
	 * @see org.owasp.esapi.interfaces.IUser#addRole(java.lang.String)
	 */
	public void addRole(String role) throws AuthenticationException {
		String roleName = role.toLowerCase();
		if ( ESAPI.validator().isValidInput("addRole", "RoleName", roleName, MAX_ROLE_LENGTH, false) ) {
			roles.add(roleName);
			logger.logCritical(Logger.SECURITY, "Role " + roleName + " added to " + getAccountName() );
		} else {
			throw new AuthenticationAccountsException( "Add role failed", "Attempt to add invalid role " + roleName + " to " + getAccountName() );
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.owasp.esapi.interfaces.IUser#addRoles(java.util.Set)
	 */
	public void addRoles(Set newRoles) throws AuthenticationException {
		Iterator i = newRoles.iterator();
		while(i.hasNext()) {
			addRole((String)i.next());
		}
	}

	 /**
	 * Adds a security event to the user.
	 * 
	 * @param event the event
	 */
	public void addSecurityEvent(String eventName) throws IntrusionException {
		Event event = (Event)events.get( eventName );
		if ( event == null ) {
			event = new Event( eventName );
			events.put( eventName, event );
		}

{'fraction_non_alphanumeric': 0.12519510926118627, 'fraction_numerical': 0.007479188345473465, 'mean_word_length': 3.5928912783751494, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7124137', 'n_tokens_mistral': 4803, 'n_tokens_neox': 4444, 'n_words': 1260}