summaryrefslogtreecommitdiff
path: root/src/token_authorization_middleware.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/token_authorization_middleware.cpp')
-rw-r--r--src/token_authorization_middleware.cpp192
1 files changed, 0 insertions, 192 deletions
diff --git a/src/token_authorization_middleware.cpp b/src/token_authorization_middleware.cpp
deleted file mode 100644
index 508bfd982c..0000000000
--- a/src/token_authorization_middleware.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-#include <random>
-#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>
-
-namespace crow {
-
-using random_bytes_engine =
- std::independent_bits_engine<std::default_random_engine, CHAR_BIT,
- unsigned char>;
-
-// 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) {
- auto return_unauthorized = [&req, &res]() {
- res.code = 401;
- res.end();
- };
-
- auto return_bad_request = [&req, &res]() {
- res.code = 400;
- res.end();
- };
-
- auto return_internal_error = [&req, &res]() {
- res.code = 500;
- res.end();
- };
-
- if (req.url == "/" || boost::starts_with(req.url, "/static/")) {
- // 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 for based page
- // that didn't
- // load the full angular UI until after login
- return;
- }
-
- if (req.url == "/login") {
- if (req.method != HTTPMethod::POST) {
- return_unauthorized();
- return;
- } else {
- auto login_credentials = crow::json::load(req.body);
- if (!login_credentials) {
- return_bad_request();
- return;
- }
- if (!login_credentials.has("username") ||
- !login_credentials.has("password")) {
- return_bad_request();
- return;
- }
- auto username = login_credentials["username"].s();
- auto password = login_credentials["password"].s();
-
- // TODO(ed) pull real passwords from PAM
- if (authenticate_user_pam(username, password)) {
- crow::json::wvalue x;
-
- // TODO(ed) the RNG should be initialized at start, not every time we
- // want a token
- std::random_device rand;
- 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
- 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.insert(encoded_token);
-
- x["token"] = encoded_token;
-
- res.write(json::dump(x));
- res.add_header("Content-Type", "application/json");
- res.end();
- } else {
- return_unauthorized();
- return;
- }
- }
-
- } else { // Normal, non login, non static file request
- // Check to make sure we're logged in
- if (this->auth_token2.empty()) {
- return_unauthorized();
- return;
- }
- // Check for an authorization header, reject if not present
- if (req.headers.count("Authorization") != 1) {
- return_unauthorized();
- return;
- }
-
- std::string auth_header = req.get_header_value("Authorization");
- // If the user is attempting any kind of auth other than token, reject
- if (!boost::starts_with(auth_header, "Token ")) {
- return_unauthorized();
- return;
- }
- std::string auth_key = auth_header.substr(6);
- // TODO(ed), use span here instead of constructing a new string
- 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) {
- // Do nothing
-}
-}