summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-26 19:52:44 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-26 19:52:44 +0200
commita595932283a3f3bf002eff5bf044762b78cab5f0 (patch)
tree790ba05f95b3fd3d6790f8132f9f6f95f908f18a
parentc73f913844f6aed9e740780f8a6732477fa3d680 (diff)
crypt(3) http auth pws
-rw-r--r--Makefile5
-rw-r--r--TODO3
-rw-r--r--auth.cpp54
-rw-r--r--auth.h13
-rw-r--r--config.cpp3
-rw-r--r--debian/changelog1
-rw-r--r--response.cpp5
-rw-r--r--webserver.conf4
-rw-r--r--webserver.cpp30
9 files changed, 100 insertions, 18 deletions
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 <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;
+}
+
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 <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);
+
+}
+
diff --git a/config.cpp b/config.cpp
index 3750bcf..793fa67 100644
--- a/config.cpp
+++ b/config.cpp
@@ -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);