<commit_before><?php
	// class_login_ssh.php - Khan Academy Workflow, 2/27/13
	// PHP class which provides SSH key login for strategy pattern authentication
	//
	// changelog:
	//
	// 3/3/13 MDL:
	//	- ignore PHP warnings on unsuccessful login
	// 2/27/13 MDL:
	//	- initial code
	//	- IT WORKS!!

	error_reporting(E_ALL);

	require_once __DIR__ . "/../class_config.php";
	config::load(array("database", "login"));

	class login_ssh extends login_strategy
	{
		// CONSTANTS - - - - - - - - - - - - - - - - - - - - - -

		// Allowed SSH hosts with necessary data
		protected static $HOSTS = array(
			"localhost" => array(
				"port" => 22,
				"fingerprint" => "fingerprint",
				"pubkey" => "/home/%s/.ssh/authorized_keys"
			),
		);

		// PUBLIC METHODS - - - - - - - - - - - - - - - - - - - -

		// Authenticate to a server using SSH public key authentication
		public function authenticate($input)
		{
			// Check for required parameters
			if (isset($input['host'], $input['username'], $input['keyfile']))
			{
				// Sanitize input for safety
				$host = database::sanitize($input['host']);
				$username = database::sanitize($input['username']);
				$keyfile = database::sanitize($input['keyfile']);

				// Check for passphrase, sanitize if found
				if (isset($input['passphrase']))
				{
					$passphrase = database::sanitize($input['passphrase']);
				}

				// Validate host against hosts array
				if (!in_array($host, array_keys(self::$HOSTS)))
				{
					trigger_error("login_ssh->authenticate() attempted to connect to non-whitelisted host '" . $host . "'", E_USER_WARNING);
					return false;
				}

				// Attempt to create SSH connection for authentication
				$ssh = ssh2_connect($host, self::$HOSTS[$host]["port"]);
				if (!$ssh)
				{
					// Trigger error on failure
					trigger_error("login_ssh->authenticate() failed to connect to host '" . $host . "'", E_USER_WARNING);
					return false;
				}

				// Check SSH fingerprint to ensure it is valid
				$fingerprint = ssh2_fingerprint($ssh);
				if ($fingerprint !== self::$HOSTS[$host]["fingerprint"])
				{
					// Trigger error on failure
					trigger_error("login_ssh->authenticate() CRITICAL: failed to verify host fingerprint for host '" . $host . "'!!", E_USER_ERROR);
					return false;
				}

				// Insert username into pubkey path
				$pubkey = sprintf(self::$HOSTS[$host]["pubkey"], $username);

				// Attempt pubkey authentication via SSH, with passphrase if provided
				if (isset($passphrase))
				{
					$success = @ssh2_auth_pubkey_file($ssh, $username, $pubkey, $keyfile, $passphrase);
				}
				else
				{
					$success = @ssh2_auth_pubkey_file($ssh, $username, $pubkey, $keyfile);
				}

				return $success;<commit_msg>Added password authentication over SSH, added toggles to enable/disable methods per host<commit_after><?php
	// class_login_ssh.php - Khan Academy Workflow, 2/27/13
	// PHP class which provides SSH key login for strategy pattern authentication
	//
	// changelog:
	//
	// 3/3/13 MDL:
	//	- ignore PHP warnings on unsuccessful login
	//	- added password login, can be enabled on a per-host basis
	// 2/27/13 MDL:
	//	- initial code
	//	- IT WORKS!!

	error_reporting(E_ALL);

	require_once __DIR__ . "/../class_config.php";
	config::load(array("database", "login"));

	class login_ssh extends login_strategy
	{
		// CONSTANTS - - - - - - - - - - - - - - - - - - - - - -

		// Authentication methods
		const AUTH_PASSWORD = "password";
		const AUTH_KEY = "key";

		// Allowed SSH hosts with necessary data
		protected static $HOSTS = array(
			"localhost" => array(
				"port" => 22,
				"fingerprint" => "fingerprint",
				"pubkey" => "/home/%s/.ssh/authorized_keys",
				"method" => array(
					self::AUTH_PASSWORD => false,
					self::AUTH_KEY => true,
				),
			),
		);

		// PUBLIC METHODS - - - - - - - - - - - - - - - - - - - -

		// Authenticate to a server using SSH public key authentication
		public function authenticate($input)
		{
			// Check for required parameters
			if (isset($input['host'], $input['username']))
			{
				// Sanitize input for safety
				$host = database::sanitize($input['host']);
				$username = database::sanitize($input['username']);

				// Check if a method was set, but default to "key" if not
				if (isset($input['method']))
				{
					$method = database::sanitize($input['method']);
				}
				else
				{
					$method = self::AUTH_KEY;
				}

				// Validate host against hosts array
				if (!in_array($host, array_keys(self::$HOSTS)))
				{
					trigger_error("login_ssh->authenticate() attempted to connect to non-whitelisted host '" . $host . "'", E_USER_WARNING);
					return false;
				}

				// Validate authentication method is valid and allowed
				if (!in_array($method, array_keys(self::$HOSTS[$host]["method"])) || !self::$HOSTS[$host]["method"][$method])
				{
					trigger_error("login_ssh->authenticate() attempted to authenticate using disallowed method '" . $method . "'", E_USER_WARNING);
					return false;
				}

				// Attempt to create SSH connection for authentication
				$ssh = ssh2_connect($host, self::$HOSTS[$host]["port"]);
				if (!$ssh)
				{
					trigger_error("login_ssh->authenticate() failed to connect to host '" . $host . "'", E_USER_WARNING);
					return false;
				}

				// Check SSH fingerprint to ensure it is valid
				$fingerprint = ssh2_fingerprint($ssh);
				if ($fingerprint !== self::$HOSTS[$host]["fingerprint"])
				{
					trigger_error("login_ssh->authenticate() CRITICAL: failed to verify host fingerprint for host '" . $host . "'!!", E_USER_ERROR);
					return false;
				}

				// Determine login method
				// Key file authentication
				if ($method === self::AUTH_KEY)
				{
					// Check to ensure keyfile parameter passed
					if (!isset($input['keyfile']))
					{
						trigger_error("login_ssh->authenticate() missing keyfile parameter for key-based authentication", E_USER_WARNING);
						return false;
					}
					$keyfile = database::sanitize($input['keyfile']);

					// Check for passphrase, sanitize if found
					if (isset($input['passphrase']))
					{
						$passphrase = database::sanitize($input['passphrase']);
					}

					// Insert username into pubkey path
					$pubkey = sprintf(self::$HOSTS[$host]["pubkey"], $username);

					// Attempt pubkey authentication via SSH, with passphrase if provided
					if (isset($passphrase))
					{
						$success = @ssh2_auth_pubkey_file($ssh, $username, $pubkey, $keyfile, $passphrase);
					}
					else
					{
						$success = @ssh2_auth_pubkey_file($ssh, $username, $pubkey, $keyfile);
					}

					return $success;
				}
				// Password authentication
				else if ($method === self::AUTH_PASSWORD)
				{
					// Check to ensure password parameter passsed
					if (!isset($input['password']))
					{
						trigger_error("login_ssh->authenticate() missing password parameter for password-based authentication", E_USER_WARNING);
						return false;
					}
					$password = database::sanitize($input['password']);

					// Attempt password authentication via SSH
					return @ssh2_auth_password($ssh, $username, $password);
				}
				// Invalid login scheme (should never happen)
				else
				{
					trigger_error("login_ssh->authenticate() invalid SSH login method specified: '" . $method . "'", E_USER_WARNING);
					return false;
				}
{'fraction_non_alphanumeric': 0.15234054202025732, 'fraction_numerical': 0.005611825896523406, 'mean_word_length': 2.9095773140716963, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5369431', 'n_tokens_mistral': 2862, 'n_tokens_neox': 2218, 'n_words': 567}