incremental
diff --git a/src/token_authorization_middleware.cpp b/src/token_authorization_middleware.cpp
index 4bac9b4..508bfd9 100644
--- a/src/token_authorization_middleware.cpp
+++ b/src/token_authorization_middleware.cpp
@@ -2,6 +2,7 @@
#include <unordered_map>
#include <boost/algorithm/string/predicate.hpp>
+#include <security/pam_appl.h>
#include <base64.hpp>
#include <token_authorization_middleware.hpp>
#include <crow/logging.h>
@@ -12,10 +13,67 @@
std::independent_bits_engine<std::default_random_engine, CHAR_BIT,
unsigned char>;
-TokenAuthorizationMiddleware::TokenAuthorizationMiddleware()
- : auth_token2(""){
+// function used to get user input
+int pam_function_conversation(int num_msg, const struct pam_message** msg,
+ struct pam_response** resp, void* appdata_ptr) {
+ char* pass = (char*)malloc(strlen((char*)appdata_ptr) + 1);
+ strcpy(pass, (char*)appdata_ptr);
- };
+ int i;
+
+ *resp = (pam_response*)calloc(num_msg, sizeof(struct pam_response));
+
+ for (i = 0; i < num_msg; ++i) {
+ /* Ignore all PAM messages except prompting for hidden input */
+ if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) continue;
+
+ /* Assume PAM is only prompting for the password as hidden input */
+ resp[i]->resp = pass;
+ }
+
+ return PAM_SUCCESS;
+}
+
+bool authenticate_user_pam(const std::string& username,
+ const std::string& password) {
+ const struct pam_conv local_conversation = {pam_function_conversation,
+ (char*)password.c_str()};
+ pam_handle_t* local_auth_handle = NULL; // this gets set by pam_start
+
+ int retval;
+ retval = pam_start("su", username.c_str(), &local_conversation,
+ &local_auth_handle);
+
+ if (retval != PAM_SUCCESS) {
+ printf("pam_start returned: %d\n ", retval);
+ return false;
+ }
+
+ retval = pam_authenticate(local_auth_handle,
+ PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
+
+ if (retval != PAM_SUCCESS) {
+ if (retval == PAM_AUTH_ERR) {
+ printf("Authentication failure.\n");
+ } else {
+ printf("pam_authenticate returned %d\n", retval);
+ }
+ return false;
+ }
+
+ printf("Authenticated.\n");
+ retval = pam_end(local_auth_handle, retval);
+
+ if (retval != PAM_SUCCESS) {
+ printf("pam_end returned\n");
+ return false;
+ }
+
+ return true;
+}
+
+TokenAuthorizationMiddleware::TokenAuthorizationMiddleware(){
+};
void TokenAuthorizationMiddleware::before_handle(crow::request& req,
response& res, context& ctx) {
@@ -38,9 +96,10 @@
// TODO this is total hackery to allow the login page to work before the
// user is authenticated. Also, it will be quite slow for all pages instead
// of a one time hit for the whitelist entries. Ideally, this should be
- // done
- // in the url router handler, with tagged routes for the whitelist entries.
- // Another option would be to whitelist a minimal
+ // done in the url router handler, with tagged routes for the whitelist
+ // entries. Another option would be to whitelist a minimal for based page
+ // that didn't
+ // load the full angular UI until after login
return;
}
@@ -63,7 +122,7 @@
auto password = login_credentials["password"].s();
// TODO(ed) pull real passwords from PAM
- if (username == "dude" && password == "dude") {
+ if (authenticate_user_pam(username, password)) {
crow::json::wvalue x;
// TODO(ed) the RNG should be initialized at start, not every time we
@@ -72,16 +131,14 @@
random_bytes_engine rbe;
std::string token('a', 20);
// TODO(ed) for some reason clang-tidy finds a divide by zero error in
- // cstdlibc here
- // commented out for now. Needs investigation
+ // cstdlibc here commented out for now. Needs investigation
std::generate(begin(token), end(token), std::ref(rbe)); // NOLINT
std::string encoded_token;
base64::base64_encode(token, encoded_token);
- ctx.auth_token = encoded_token;
- this->auth_token2 = encoded_token;
+ // ctx.auth_token = encoded_token;
+ this->auth_token2.insert(encoded_token);
- auto auth_token = ctx.auth_token;
- x["token"] = auth_token;
+ x["token"] = encoded_token;
res.write(json::dump(x));
res.add_header("Content-Type", "application/json");
@@ -92,10 +149,6 @@
}
}
- } else if (req.url == "/logout") {
- this->auth_token2 = "";
- res.code = 200;
- res.end();
} else { // Normal, non login, non static file request
// Check to make sure we're logged in
if (this->auth_token2.empty()) {
@@ -114,16 +167,26 @@
return_unauthorized();
return;
}
-
+ std::string auth_key = auth_header.substr(6);
// TODO(ed), use span here instead of constructing a new string
- if (auth_header.substr(6) != this->auth_token2) {
+ if (this->auth_token2.find(auth_key) == this->auth_token2.end()) {
return_unauthorized();
return;
}
+
+ if (req.url == "/logout") {
+ this->auth_token2.erase(auth_key);
+ res.code = 200;
+ res.end();
+ return;
+ }
+
// else let the request continue unharmed
}
}
void TokenAuthorizationMiddleware::after_handle(request& req, response& res,
- context& ctx) {}
+ context& ctx) {
+ // Do nothing
+}
}
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index f47eb79..404e15c 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -228,11 +228,15 @@
g3::initializeLogging(worker.get());
auto sink_handle = worker->addSink(std::make_unique<crow::ColorCoutSink>(),
&crow::ColorCoutSink::ReceiveLogMessage);
-
+ bool enable_ssl = true;
std::string ssl_pem_file("server.pem");
- ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file);
- crow::App<crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware>
+ if (enable_ssl) {
+ ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file);
+ }
+
+ crow::App<
+ crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware>
app;
crow::webassets::request_routes(app);
@@ -309,13 +313,33 @@
return j;
});
+
+ CROW_ROUTE(app, "/intel/firmwareupload")
+ .methods("POST"_method)([](const crow::request& req) {
+ // TODO(ed) handle errors here (file exists already and is locked, ect)
+ std::ofstream out(
+ "/tmp/fw_update_image",
+ std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
+ out << req.body;
+ out.close();
+
+ crow::json::wvalue j;
+ j["status"] = "Upload Successfull";
+
+ return j;
+ });
+
LOG(DEBUG) << "Building SSL context";
- auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file);
+
int port = 18080;
LOG(DEBUG) << "Starting webserver on port " << port;
- app.port(port)
- .ssl(std::move(ssl_context))
- //.concurrency(4)
- .run();
+ app.port(port);
+ if (enable_ssl) {
+ LOG(DEBUG) << "SSL Enabled";
+ auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file);
+ app.ssl(std::move(ssl_context));
+ }
+ app.concurrency(4);
+ app.run();
}