diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-26 19:52:44 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-26 19:52:44 +0200 |
commit | a595932283a3f3bf002eff5bf044762b78cab5f0 (patch) | |
tree | 790ba05f95b3fd3d6790f8132f9f6f95f908f18a | |
parent | c73f913844f6aed9e740780f8a6732477fa3d680 (diff) |
crypt(3) http auth pws
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | auth.cpp | 54 | ||||
-rw-r--r-- | auth.h | 13 | ||||
-rw-r--r-- | config.cpp | 3 | ||||
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | response.cpp | 5 | ||||
-rw-r--r-- | webserver.conf | 4 | ||||
-rw-r--r-- | webserver.cpp | 30 |
9 files changed, 100 insertions, 18 deletions
@@ -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 \ @@ -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 <crypt.h> +#include <string.h> + +#include <stdexcept> +#include <iostream> + +// 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; +} + @@ -0,0 +1,13 @@ +#pragma once + +#include <string> + +// Password encryption via crypt(3) + +namespace Auth { + + std::string generate(const std::string& pw); + bool validate(const std::string& crypted, const std::string& pw); + +} + @@ -3,6 +3,7 @@ #include <boost/algorithm/string/predicate.hpp> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> +#include <boost/timer/timer.hpp> #include <algorithm> #include <exception> @@ -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 <rr@antcom.de> 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 @@ <target>/home/ernie/testbox</target> <WEBBOX_NAME>Testbox1</WEBBOX_NAME> <WEBBOX_READONLY>0</WEBBOX_READONLY> - <auth login="abc" password="def"/> + <auth login="abc" password="$6$rounds=2000$HGwnefVabvSkS4Kg$5xYJDIVL7rkMGVVBOHf8/pHTJFKeEDytzS9em6En9qydgUFqbtbOTnTp/HyYk9At4eDL64jGKmbSKNFsXlquI1"/> </path> <path requested="/blog"> <plugin>weblog</plugin> @@ -45,7 +45,7 @@ <path requested="/cgi-bin"> <plugin>cgi</plugin> <target>/home/ernie/code/webserver/cgi-bin</target> - <auth login="abc" password="def"/> + <auth login="abc" password="$6$rounds=2000$HGwnefVabvSkS4Kg$5xYJDIVL7rkMGVVBOHf8/pHTJFKeEDytzS9em6En9qydgUFqbtbOTnTp/HyYk9At4eDL64jGKmbSKNFsXlquI1"/> </path> <certpath>/home/ernie/code/webserver/fullchain.pem</certpath> <keypath>/home/ernie/code/webserver/privkey.pem</keypath> 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); |