Skip to content

Commit

Permalink
Fine tune log messages, add bcrypt_debug() native
Browse files Browse the repository at this point in the history
  • Loading branch information
lassir committed Jan 31, 2015
1 parent f9e80ce commit fc28a13
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 34 deletions.
34 changes: 25 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Bcrypt for SA-MP

An implementation of bcrypt password hashing library for Pawn written in C++.
An implementation of bcrypt password hashing library for Pawn, written in C/C++.

## Benefits of bcrypt

Expand All @@ -14,19 +14,35 @@ An implementation of bcrypt password hashing library for Pawn written in C++.
* `bcrypt_check(key[], hash[], callback_name[], callback_format[] = "", {Float, _}:...);`
* `bool:bcrypt_is_equal();`
* `bool:bcrypt_needs_rehash(hash[], cost);`
* `bcrypt_find_cost(time_target = 250);`
* `bcrypt_debug(BCRYPT_DEBUG_LEVEL:level = BCRYPT_LOG_ERROR)`
* `bcrypt_set_thread_limit(value);`

## Usage
See the [Wiki](wiki) for detailed usage.

## Installation

* Copy the plugin file and the include file to their appropriate directories
### Linux

* Include the .inc file in your gamemode or filterscript (#include <bcrypt>)
1. Copy `bcrypt-samp.so` to the `plugins` folder
2. Add `plugins bcrypt-samp.so` to server.cfg
3. Copy `bcrypt.inc` to the compiler's include directory (`pawno/include` by default)
4. Add `#include <bcrypt>` to your gamemode or filterscript

* Call function `bcrypt_hash` when you would like to hash user input (e.g. on registration, or when updating the work factor). Once the hash is calculated, the callback set in the parameters will be called, and the hash can be acquired using `bcrypt_get_hash` function
### Windows

* Call function `bcrypt_check` when you would like to verify whether or not user input matches a given hash (e.g. on login). Once the verification is done, the callback set in the parameters will be called, and the result can be acquired using `bcrypt_is_equal` function
1. Copy `bcrypt-samp.dll` to the `plugins` folder
2. Add `plugins bcrypt-samp` to server.cfg
3. Copy `bcrypt.inc` to the compiler's include directory (`pawno/include` by default)
4. Add `#include <bcrypt>` to your gamemode or filterscript

## Usage

* If you ever change the cost, you can use `bcrypt_needs_rehash` to check whether or not a hash needs to be updated
* Call function `bcrypt_hash` when you would like to hash user input (e.g. on registration, or when updating the work factor). Once the hash is calculated, the callback defined in the parameters will be called, and the hash can be acquired using `bcrypt_get_hash` function

* Call function `bcrypt_check` when you would like to verify whether or not user input matches a given hash (e.g. on login). Once the verification is done, the callback defined in the parameters will be called, and the result can be acquired using `bcrypt_is_equal` function

* You can use `bcrypt_needs_rehash` to check whether or not the hash needs to be updated

* If you would like to override the default number of threads used, you may use function `bcrypt_set_thread_limit`. In most cases, however, the default value is adequate

Expand All @@ -52,7 +68,7 @@ public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
case DIALOG_LOGIN:
{
// Variable hash is expected to contain the hash loaded from the database
bcrypt_check(playerid, BCRYPT_LOGIN, inputtext, hash);
bcrypt_check(inputtext, hash, "OnPasswordChecked", "d", playerid);
}
}
Expand All @@ -75,4 +91,4 @@ public OnPasswordChecked(playerid)
printf("Password checked for %d: %s", (match) ? ("Match") : ("No match"));
return 1;
}
```
```
12 changes: 11 additions & 1 deletion bcrypt.inc → pawn/bcrypt.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,16 @@
#endif

#define BCRYPT_HASH_LENGTH 61
#define BCRYPT_PLUGIN_VERSION "2.2.2"
#define BCRYPT_PLUGIN_VERSION "2.2.3"

enum BCRYPT_DEBUG_LEVEL {
BCRYPT_LOG_FATAL,
BCRYPT_LOG_ERROR,
BCRYPT_LOG_WARNING,
BCRYPT_LOG_INFO,
BCRYPT_LOG_DEBUG,
BCRYPT_LOG_TRACE
}

native bcrypt_hash(key[], cost = 12, callback_name[], callback_format[] = "", {Float, _}:...);
native bcrypt_check(password[], hash[], callback_name[], callback_format[] = "", {Float, _}:...);
Expand All @@ -39,6 +48,7 @@ native bool:bcrypt_is_equal();
native bool:bcrypt_needs_rehash(hash[], cost);
native bcrypt_find_cost(time_target = 250);
native bcrypt_set_thread_limit(value);
native bcrypt_debug(BCRYPT_DEBUG_LEVEL:level = BCRYPT_LOG_ERROR);

// Version check
forward OnBcryptVersionCheck(index, response_code, data[]);
Expand Down
8 changes: 4 additions & 4 deletions src/callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Callback* Callback::addParameter(std::string parameter)

Callback* Callback::exec()
{
BOOST_LOG_TRIVIAL(trace) << "Executing callback " << this->getName();
BOOST_LOG_TRIVIAL(trace) << "Executing callback " << this->getName() << "...";

using namespace samp_sdk;

Expand All @@ -78,12 +78,12 @@ Callback* Callback::exec()

for (std::set<AMX *>::iterator amx = amx_list.begin(); amx != amx_list.end(); ++amx)
{
BOOST_LOG_TRIVIAL(trace) << "Callback::exec: AMX: " << *amx;
BOOST_LOG_TRIVIAL(trace) << " Callback::exec: " << *amx;
int amx_idx = 0;

if (amx_FindPublic(*amx, this->name.c_str(), &amx_idx) == AMX_ERR_NONE)
{
BOOST_LOG_TRIVIAL(trace) << *amx << ": Public found";
BOOST_LOG_TRIVIAL(trace) << " => Public found.";

cell amx_addr = -1;

Expand Down Expand Up @@ -111,7 +111,7 @@ Callback* Callback::exec()
}
else
{
BOOST_LOG_TRIVIAL(trace) << *amx << ": Public not found";
BOOST_LOG_TRIVIAL(trace) << " => Public not found.";
}
}
return this;
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ AMX_NATIVE_INFO PluginNatives [] =
DEFINE_NATIVE(bcrypt_needs_rehash)
DEFINE_NATIVE(bcrypt_find_cost)
DEFINE_NATIVE(bcrypt_set_thread_limit)
DEFINE_NATIVE(bcrypt_debug)
{ 0, 0 }
};

Expand Down
81 changes: 74 additions & 7 deletions src/natives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
#include <cstring>

#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>

#include "bcrypt.h"
#include "plugin.h"
#include "natives.h"

using namespace samp_sdk;

namespace logging = boost::log;

// native bcrypt_hash(key[], cost, callback_name[], callback_format[], {Float, _}:...);
DECLARE_NATIVE(native::bcrypt_hash)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_hash called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_hash() called.";

if (params[0] < 3 * sizeof(cell))
{
Expand Down Expand Up @@ -51,7 +54,7 @@ DECLARE_NATIVE(native::bcrypt_hash)
// native bcrypt_check(thread_idx, thread_id, const password[], const hash[]);
DECLARE_NATIVE(native::bcrypt_check)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_check called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_check() called.";

if (params[0] < 3 * sizeof(cell))
{
Expand Down Expand Up @@ -83,7 +86,7 @@ DECLARE_NATIVE(native::bcrypt_check)
// native bcrypt_get_hash(destination[]);
DECLARE_NATIVE(native::bcrypt_get_hash)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_get_hash called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_get_hash() called.";

if (params[0] != sizeof(cell))
{
Expand All @@ -100,15 +103,15 @@ DECLARE_NATIVE(native::bcrypt_get_hash)
// native bool:bcrypt_is_equal(destination[]);
DECLARE_NATIVE(native::bcrypt_is_equal)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_is_equal called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_is_equal() called.";

return Plugin::get()->getActiveMatch();
}

// native bool:bcrypt_needs_rehash(hash[], cost);
DECLARE_NATIVE(native::bcrypt_needs_rehash)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_needs_rehash called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_needs_rehash() called.";

if (params[0] != sizeof(cell) * 2)
{
Expand All @@ -135,7 +138,7 @@ DECLARE_NATIVE(native::bcrypt_needs_rehash)
// native bcrypt_find_cost(time_target = 250);
DECLARE_NATIVE(native::bcrypt_find_cost)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_find_cost called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_find_cost() called.";

if (params[0] != 1 * sizeof(cell))
{
Expand Down Expand Up @@ -194,7 +197,7 @@ DECLARE_NATIVE(native::bcrypt_find_cost)
// native bcrypt_set_thread_limit(value);
DECLARE_NATIVE(native::bcrypt_set_thread_limit)
{
BOOST_LOG_TRIVIAL(trace) << "bcrypt_set_thread_limit called";
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_set_thread_limit() called.";

if (params[0] != 1 * sizeof(cell))
{
Expand All @@ -219,3 +222,67 @@ DECLARE_NATIVE(native::bcrypt_set_thread_limit)

return 1;
}


// native bcrypt_debug(level)
DECLARE_NATIVE(native::bcrypt_debug)
{
BOOST_LOG_TRIVIAL(trace) << "Native bcrypt_debug() called.";

if (params[0] != 1 * sizeof(cell))
{
BOOST_LOG_TRIVIAL(error) << "bcrypt_debug: Invalid number of parameters (" << params[0] * sizeof(cell) << " given, 1 expected)";
return 0;
}

enum DebugLevel {
LOG_FATAL,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG,
LOG_TRACE
};

unsigned debug_level = static_cast<unsigned>(params[1]);

switch (debug_level)
{
case DebugLevel::LOG_FATAL:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::fatal);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log fatal errors.";
break;

case DebugLevel::LOG_ERROR:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::error);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log errors.";
break;

case DebugLevel::LOG_WARNING:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::warning);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log warnings.";
break;

case DebugLevel::LOG_INFO:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log info messages.";
break;

case DebugLevel::LOG_DEBUG:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::debug);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log debugging messages.";
break;

case DebugLevel::LOG_TRACE:
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::trace);
BOOST_LOG_TRIVIAL(info) << "Debugging level changed: Log trace messages.";
break;

default:
BOOST_LOG_TRIVIAL(error) << "bcrypt_debug: Invalid debugging level (" << debug_level << ")";
break;

}

return 1;
}
1 change: 1 addition & 0 deletions src/natives.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace native
DECLARE_NATIVE(bcrypt_needs_rehash);
DECLARE_NATIVE(bcrypt_find_cost);
DECLARE_NATIVE(bcrypt_set_thread_limit);
DECLARE_NATIVE(bcrypt_debug);
}

#endif
23 changes: 10 additions & 13 deletions src/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "plugin.h"
#include "bcrypt.h"

namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

Expand Down Expand Up @@ -47,13 +48,13 @@ void Plugin::initialise(void **data)
keywords::file_name = "bcrypt_log.txt",
keywords::auto_flush = true,
keywords::format = expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
<< " <" << boost::log::trivial::severity << "> "
<< expr::message
);

boost::log::core::get()->set_filter(
boost::log::trivial::severity >= boost::log::trivial::trace
boost::log::trivial::severity >= boost::log::trivial::error
);

boost::log::add_common_attributes();
Expand Down Expand Up @@ -112,22 +113,22 @@ int Plugin::getThreadLimit()

void Plugin::queueTask(unsigned short type, std::string key, unsigned short cost, Callback *cb)
{
BOOST_LOG_TRIVIAL(debug) << "Task queued: '" << cb->getName() << "'";
BOOST_LOG_TRIVIAL(debug) << "Task " << cb->getName() << " queued.";
this->task_queue.push({ type, key, cost, "", cb });
}

void Plugin::queueTask(unsigned short type, std::string key, std::string hash, Callback *cb)
{
BOOST_LOG_TRIVIAL(debug) << "Task queued: '" << cb->getName() << "'";
BOOST_LOG_TRIVIAL(debug) << "Task " << cb->getName() << " queued.";
this->task_queue.push({ type, key, 0, hash, cb });
}

void Plugin::queueResult(unsigned short type, std::string hash, bool match, Callback *cb)
{
BOOST_LOG_TRIVIAL(trace) << "Queue result: '" << cb->getName() << "'. Waiting for mutex.";
BOOST_LOG_TRIVIAL(trace) << "Result for " << cb->getName() << ": Waiting for a mutex...";
std::lock_guard<std::mutex> lock(Plugin::result_queue_mutex);

BOOST_LOG_TRIVIAL(debug) << "Queue result: '" << cb->getName() << "'. Mutex obtained, adding to queue.";
BOOST_LOG_TRIVIAL(debug) << "Result for " << cb->getName() << ": Mutex obtained, adding to the queue.";
this->result_queue.push({ type, hash, match, cb });
this->active_threads--;
}
Expand All @@ -144,8 +145,6 @@ std::string Plugin::getActiveHash()

void Plugin::generateBcryptThread(Callback *cb, std::string buffer, short cost)
{
BOOST_LOG_TRIVIAL(debug) << "Thread created: generateBcryptThread (" << cb->getName() << ")";

Bcrypt *crypter = new Bcrypt();

crypter
Expand All @@ -162,8 +161,6 @@ void Plugin::generateBcryptThread(Callback *cb, std::string buffer, short cost)

void Plugin::checkBcryptThread(Callback *cb, std::string password, std::string hash)
{
BOOST_LOG_TRIVIAL(debug) << "Thread created: checkBcryptThread (" << cb->getName() << ")";

Bcrypt *crypter = new Bcrypt();

crypter
Expand All @@ -187,7 +184,7 @@ void Plugin::processTaskQueue()
case QueueType::HASH:
{
// Start a new thread
BOOST_LOG_TRIVIAL(trace) << "Preparing to create a thread for '" << this->task_queue.front().cb->getName() << "'";
BOOST_LOG_TRIVIAL(trace) << "Crating a thread for " << this->task_queue.front().cb->getName() << "...";
this->active_threads++;

std::thread t(&Plugin::generateBcryptThread, this, this->task_queue.front().cb, this->task_queue.front().key, this->task_queue.front().cost);
Expand All @@ -197,7 +194,7 @@ void Plugin::processTaskQueue()
case QueueType::CHECK:
{
// Start a new thread
BOOST_LOG_TRIVIAL(trace) << "Preparing to create a thread for '" << this->task_queue.front().cb->getName() << "'";
BOOST_LOG_TRIVIAL(trace) << "Creating a thread for " << this->task_queue.front().cb->getName() << "...";
this->active_threads++;

std::thread t(&Plugin::checkBcryptThread, this, this->task_queue.front().cb, this->task_queue.front().key, this->task_queue.front().hash);
Expand All @@ -223,7 +220,7 @@ void Plugin::processResultQueue()

while (!this->result_queue.empty())
{
BOOST_LOG_TRIVIAL(debug) << "Calling callback '" << this->result_queue.front().cb->getName() << "'";
BOOST_LOG_TRIVIAL(debug) << "Calling callback " << this->result_queue.front().cb->getName() << "...";

this->active_result.hash = this->result_queue.front().hash;
this->active_result.match = this->result_queue.front().match;
Expand Down

0 comments on commit fc28a13

Please sign in to comment.