From 6f1841e610be580b8094b02766ed43c4ede92a7b Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sat, 4 Feb 2023 15:48:17 +0100 Subject: [PATCH] use stdin to provide authentication token to authenticator rather than command line option --- doc/authentication.md | 7 +-- example/authenticator/pam/src/main.cpp | 55 ++++++++----------- example/authenticator/simple/authenticator.sh | 2 +- example/provider/python/webfuse_provider.py | 2 +- src/webfuse/util/authenticator.cpp | 21 +++++-- 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/doc/authentication.md b/doc/authentication.md index 3e4cd19..a0c6036 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -19,12 +19,7 @@ operation, the credentials are queried via `getcreds`request. ## Authenticator An authenticator is an executable or script used for token-based -authentication. During HTTP handshake, webfuse will scan for the -configured HTTP header and invoke the authenticator. - - authenticator TOKEN - -The provided `token` contains the contents of the HTTP header. +authentication. Credentials are passed to the authenticator via `stdin`. ## Header restrictions diff --git a/example/authenticator/pam/src/main.cpp b/example/authenticator/pam/src/main.cpp index aa9cb60..3a6c2aa 100644 --- a/example/authenticator/pam/src/main.cpp +++ b/example/authenticator/pam/src/main.cpp @@ -133,54 +133,47 @@ bool authenticate(std::string const & username, std::string const & password) int main(int argc, char* argv[]) { int exit_code = EXIT_FAILURE; - bool print_usage = true; - if (argc == 2) + if (argc == 1) { - std::string const token = argv[1]; - if (("-h" != token) && ("--help" != token)) - { - print_usage = false; + std::string token; + std::getline(std::cin, token); - openlog("webfuse_pam_auth", 0, LOG_AUTH); + openlog("webfuse_pam_auth", 0, LOG_AUTH); - std::string username; - std::string password; - auto const decode_valid = decode(token, username, password); - if (decode_valid) + std::string username; + std::string password; + auto const decode_valid = decode(token, username, password); + if (decode_valid) + { + auto const is_authenticated = authenticate(username, password); + if (is_authenticated) { - auto const is_authenticated = authenticate(username, password); - if (is_authenticated) - { - syslog(LOG_AUTH, "authenticate user \"%s\"", username.c_str()); - exit_code = EXIT_SUCCESS; - } - else - { - syslog(LOG_AUTH, "failed to authenticate user \"%s\"", username.c_str()); - } + syslog(LOG_AUTH, "authenticate user \"%s\"", username.c_str()); + exit_code = EXIT_SUCCESS; } else { - syslog(LOG_AUTH, "failed to decode authentication token"); + syslog(LOG_AUTH, "failed to authenticate user \"%s\"", username.c_str()); } - - closelog(); } - } - - if (print_usage) + closelog(); + } + else { std::cout << R"(webfuse_pam_authenticator, (c) 2023 Falk Werner webfuse PAM authenticator Usage: - webfuse_pam_authenticator + webfuse_pam_authenticator [-h] + +Options: + --help, -h print this message and exit -Arguments: - token used for authentication - token := base64( ":" ) +Credentials: + Credentials are passed as based64-encoded token via stdin: + token := base64( ":" ) )"; } diff --git a/example/authenticator/simple/authenticator.sh b/example/authenticator/simple/authenticator.sh index 23ee163..5330483 100755 --- a/example/authenticator/simple/authenticator.sh +++ b/example/authenticator/simple/authenticator.sh @@ -1,6 +1,6 @@ #!/usr/bin/bash -AUTH_TOKEN="$1" +read AUTH_TOKEN if [[ "$AUTH_TOKEN" == "simple_token" ]] then diff --git a/example/provider/python/webfuse_provider.py b/example/provider/python/webfuse_provider.py index 6a075c2..d508a29 100755 --- a/example/provider/python/webfuse_provider.py +++ b/example/provider/python/webfuse_provider.py @@ -577,7 +577,7 @@ class FilesystemProvider: writer.write_u64(buffer.f_namemax) def getcreds(self, _, writer): - credentials = self.token if self.token != "" else getpass.getpass(prompt="credentials: ") + credentials = self.token if self.token != None and self.token != "" else getpass.getpass(prompt="credentials: ") writer.write_str(credentials) def main(): diff --git a/src/webfuse/util/authenticator.cpp b/src/webfuse/util/authenticator.cpp index dd6fb38..579aaab 100644 --- a/src/webfuse/util/authenticator.cpp +++ b/src/webfuse/util/authenticator.cpp @@ -17,23 +17,35 @@ bool authenticator::authenticate(std::string const & token) { bool result = false; + int fds[2]; + int const rc = pipe(fds); + if (0 != rc) + { + return false; + } + pid_t const pid = fork(); if (pid == 0) { // child + close(STDIN_FILENO); + dup2(fds[0], STDIN_FILENO); + // prepare file descriptors - closefrom(0); - open("/dev/null", O_RDONLY); + closefrom(1); open("/dev/null", O_WRONLY); dup2(STDOUT_FILENO, STDERR_FILENO); - execl(app_.c_str(), app_.c_str(), token.c_str(), nullptr); + execl(app_.c_str(), app_.c_str(), nullptr); exit(EXIT_FAILURE); } else if (pid > 0) { + write(fds[1], reinterpret_cast(token.c_str()), token.size()); + close(fds[1]); + // parent int exit_status = EXIT_FAILURE; @@ -44,7 +56,8 @@ bool authenticator::authenticate(std::string const & token) exit_status = WEXITSTATUS(status); } - result = (exit_status == EXIT_SUCCESS); + close(fds[0]); + result = (exit_status == EXIT_SUCCESS); } return result;