/* Auth Function, builds SQL query for connecting user */
	bool CheckCredentials(User* user) {
		std::string thisquery = freeformquery;
		std::string safepass = user->password;

		/* Search and replace the escaped nick and escaped pass into the query */
		SearchAndReplace(safepass, "\"", "");
		std::string* wnick;
		if (user->GetExt("wantsnick", wnick)) {
			SearchAndReplace(thisquery, "$nick", *wnick);
		} else {
			SearchAndReplace(thisquery, "$nick", user->nick);
		}

		SearchAndReplace(thisquery, "$pass", safepass);
		SearchAndReplace(thisquery, "$host", user->host);
		SearchAndReplace(thisquery, "$ip", user->GetIPString());
		
		Module* HashMod = ServerInstance->Modules->Find("m_md5.so");

		if (HashMod) {
			HashResetRequest(this, HashMod).Send();
			SearchAndReplace(thisquery, "$md5pass", HashSumRequest(this, HashMod, user->password).Send());
		}

		HashMod = ServerInstance->Modules->Find("m_sha256.so");

		if (HashMod) {
			HashResetRequest(this, HashMod).Send();
			SearchAndReplace(thisquery, "$sha256pass", HashSumRequest(this, HashMod, user->password).Send());
		}

		/* Build the query */
		SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(thisquery));

		if(req.Send()) {
			/* When we get the query response from the service provider we will be given an ID to play with,
			 * just an ID number which is unique to this query. We need a way of associating that ID with a User
			 * so we insert it into a map mapping the IDs to users.
			 * Thankfully m_sqlutils provides this, it will associate a ID with a user or channel, and if the user quits it removes the
			 * association. This means that if the user quits during a query we will just get a failed lookup from m_sqlutils - telling
			 * us to discard the query.
		 	 */
			AssociateUser(this, SQLutils, req.id, user).Send();

			return true;
		} else {
			if (verbose) {
				ServerInstance->SNO->WriteToSnoMask('A', "Forbidden connection from %s!%s@%s (SQL query failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), req.error.Str());
			}
			return false;
		}
	}
Beispiel #2
0
std::string TreeSocket::MakePass(const std::string &password, const std::string &challenge)
{
	/* This is a simple (maybe a bit hacky?) HMAC algorithm, thanks to jilles for
	 * suggesting the use of HMAC to secure the password against various attacks.
	 *
	 * Note: If m_sha256.so is not loaded, we MUST fall back to plaintext with no
	 *       HMAC challenge/response.
	 */
	Module* sha256 = ServerInstance->Modules->Find("m_sha256.so");
	if (Utils->ChallengeResponse && sha256 && !challenge.empty())
	{
		/* XXX: This is how HMAC is supposed to be done:
		 *
		 * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) )
		 *
		 * Note that we are encoding the hex hash, not the binary
		 * output of the hash which is slightly different to standard.
		 *
		 * Don't ask me why its always 0x5c and 0x36... it just is.
		 */
		std::string hmac1, hmac2;

		for (size_t n = 0; n < password.length(); n++)
		{
			hmac1 += static_cast<char>(password[n] ^ 0x5C);
			hmac2 += static_cast<char>(password[n] ^ 0x36);
		}

		hmac2 += challenge;
		HashResetRequest(Utils->Creator, sha256).Send();
		hmac2 = HashSumRequest(Utils->Creator, sha256, hmac2).Send();

		HashResetRequest(Utils->Creator, sha256).Send();
		std::string hmac = hmac1 + hmac2;
		hmac = HashSumRequest(Utils->Creator, sha256, hmac).Send();

		return "HMAC-SHA256:"+ hmac;
	}
	else if (!challenge.empty() && !sha256)
		ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");

	return password;
}
Beispiel #3
0
	void MakeHash(userrec* user, const char* algo, const char* stuff)
	{
		/* Lets see if they gave us an algorithm which has been implemented */
		hashymodules::iterator x = hashers.find(algo);
		if (x != hashers.end())
		{
			/* Yup, reset it first (Always ALWAYS do this) */
			HashResetRequest(Sender, x->second).Send();
			/* Now attempt to generate a hash */
			user->WriteServ("NOTICE %s :%s hashed password for %s is %s",user->nick, algo, stuff, HashSumRequest(Sender, x->second, stuff).Send() );
		}
		else
		{
			/* I dont do flying, bob. */
			user->WriteServ("NOTICE %s :Unknown hash type, valid hash types are: %s", user->nick, irc::stringjoiner(", ", names, 0, names.size() - 1).GetJoined().c_str() );
		}
	}
Beispiel #4
0
	virtual int OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
	{
		/* First, lets see what hash theyre using on this oper */
		hashymodules::iterator x = hashers.find(hashtype.c_str());

		/* Is this a valid hash name? (case insensitive) */
		if (x != hashers.end())
		{
			/* Reset the hashing module */
			HashResetRequest(this, x->second).Send();
			/* Compare the hash in the config to the generated hash */
			if (!strcasecmp(data.c_str(), HashSumRequest(this, x->second, input.c_str()).Send()))
				return 1;
			/* No match, and must be hashed, forbid */
			else return -1;
		}

		/* Not a hash, fall through to strcmp in core */
		return 0;
	}