From a595932283a3f3bf002eff5bf044762b78cab5f0 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 26 Apr 2020 19:52:44 +0200 Subject: crypt(3) http auth pws --- Makefile | 5 ++++- TODO | 3 +-- auth.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ auth.h | 13 +++++++++++++ config.cpp | 3 +++ debian/changelog | 1 + response.cpp | 5 ++++- webserver.conf | 4 ++-- webserver.cpp | 30 ++++++++++++++++++------------ 9 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 auth.cpp create mode 100644 auth.h diff --git a/Makefile b/Makefile index c692bf0..17ae99c 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,10 @@ CXXTESTFLAGS=-Igoogletest/include -Igooglemock/include/ -Igoogletest -Igooglemoc LIBS=\ -lboost_context \ --lboost_system \ -lboost_filesystem \ +-lboost_timer \ +-lboost_system \ +-lcrypt \ -lpthread \ -lssl -lcrypto \ -ldl @@ -63,6 +65,7 @@ LIBS+= \ endif PROGSRC=\ + auth.cpp \ base64.cpp \ config.cpp \ file.cpp \ diff --git a/TODO b/TODO index b8f0b41..44740ff 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ -crypt pws licence bsd -Speed up config.GetPath +Speed up config.GetPath weblog: blättern weblog: link consistency check (cron?) weblog: style: zitate diff --git a/auth.cpp b/auth.cpp new file mode 100644 index 0000000..c9c9765 --- /dev/null +++ b/auth.cpp @@ -0,0 +1,54 @@ +#include "auth.h" + +#include +#include + +#include +#include + +// crypt specified password +std::string Auth::generate(const std::string& pw) +{ + struct crypt_data data; + memset((void *)&data, '\0', sizeof(data)); + + if (crypt_gensalt_rn("$6$", 2000, nullptr, 0, data.setting, sizeof(data.setting)) == nullptr) + throw std::runtime_error("Error on crypt_gensalt_r()"); + + strncpy(data.input, pw.data(), sizeof(data.input)); + + if (crypt_r(data.input, data.setting, &data) == nullptr) + throw std::runtime_error("Error on crypt_r()"); + + return data.output; +} + +// validate specified password against crypted hash +bool Auth::validate(const std::string& crypted, const std::string& pw) +{ + struct crypt_data data; + memset((void *)&data, '\0', sizeof(data)); + + size_t pos = crypted.find_last_of('$'); + if (pos == crypted.npos) { + std::cerr << "Warning: Bad password hash configured (format)" << std::endl; + return false; + } + + if (sizeof(data.setting) <= pos) { + std::cerr << "Warning: Bad password hash configured (salt size)" << std::endl; + return false; + } + + memcpy(&data.setting, crypted.data(), pos); + + strncpy(data.input, pw.data(), sizeof(data.input)); + + if (crypt_r(data.input, data.setting, &data) == nullptr) { + std::cerr << "Warning: Error on crypt_r()" << std::endl; + return false; + } + + return crypted == data.output; +} + diff --git a/auth.h b/auth.h new file mode 100644 index 0000000..1a25e79 --- /dev/null +++ b/auth.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +// Password encryption via crypt(3) + +namespace Auth { + + std::string generate(const std::string& pw); + bool validate(const std::string& crypted, const std::string& pw); + +} + diff --git a/config.cpp b/config.cpp index 3750bcf..793fa67 100644 --- a/config.cpp +++ b/config.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -208,6 +209,8 @@ void Config::dump() const // throws std::out_of_range if not found const Path& Config::GetPath(const Socket& socket, const std::string& requested_host, const std::string& requested_path) const { + //boost::timer::auto_cpu_timer t; + // TODO: speed this up std::string host{requested_host}; const Path* result{nullptr}; diff --git a/debian/changelog b/debian/changelog index eacca64..4d6642b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ webserver (1.3) unstable; urgency=medium * Added statistics * Removed upload limit (now 1GB) * Support Ubuntu 1910 + * Crypt(3) HTTP AUTH passwords -- Roland Reichwein Sat, 25 Apr 2020 12:35:44 +0200 diff --git a/response.cpp b/response.cpp index 696b859..9eda5ff 100644 --- a/response.cpp +++ b/response.cpp @@ -1,5 +1,6 @@ #include "response.h" +#include "auth.h" #include "base64.h" #include "file.h" @@ -292,7 +293,9 @@ response_type generate_response(request_type& req, Server& server) std::string password{authorization.substr(pos + 1)}; auto it {auth.find(login)}; - if (it == auth.end() || it->second != password) + // it.second contains crypted/hash + // password is plain text to validate against the hash + if (it == auth.end() || !Auth::validate(it->second, password)) return HttpStatusAndStats("401", "Bad Authorization", req_ctx, res); } diff --git a/webserver.conf b/webserver.conf index 5adc9ba..55a1870 100644 --- a/webserver.conf +++ b/webserver.conf @@ -29,7 +29,7 @@ /home/ernie/testbox Testbox1 0 - + weblog @@ -45,7 +45,7 @@ cgi /home/ernie/code/webserver/cgi-bin - + /home/ernie/code/webserver/fullchain.pem /home/ernie/code/webserver/privkey.pem diff --git a/webserver.cpp b/webserver.cpp index c49751e..98fedc3 100644 --- a/webserver.cpp +++ b/webserver.cpp @@ -1,3 +1,4 @@ +#include "auth.h" #include "config.h" #include "server.h" #include "plugin.h" @@ -21,25 +22,30 @@ void initlocale() { int main(int argc, char* argv[]) { - //initlocale(); // TODO: breaks plugins - - std::string config_filename; + try { + //initlocale(); // TODO: breaks plugins - if (!(argc == 1 || argc == 3)) { - usage(); - return 1; - } + std::string config_filename; - if (argc == 3) { - if (argv[1] != "-c"s) { + if (!(argc == 1 || argc == 3)) { usage(); return 1; } - config_filename = argv[2]; - } + if (argc == 3) { + + // normal run with configuration file specified + if (argv[1] == "-c"s) { + config_filename = argv[2]; + } else if (argv[1] == "-p"s) { // generate crypted password + std::cout << Auth::generate(argv[2]) << std::endl; + return 0; + } else { + usage(); + return 1; + } + } - try { Config config{config_filename}; PluginLoader plugin_loader(config); -- cgit v1.2.3