0
0
Fork 0
mirror of https://github.com/boltgolt/howdy.git synced 2024-09-19 09:51:19 +02:00

Add more documentation

This commit is contained in:
MusiKid 2021-04-07 11:15:01 +02:00 committed by musikid
parent 02a831ff8e
commit 3abc3d5cdc
No known key found for this signature in database
GPG key ID: 7567D43648C6E2F4

View file

@ -72,12 +72,14 @@ int on_howdy_auth(int code, function<int(int, const char *)> conv_function) {
break; break;
// Otherwise, we can't discribe what happend but it wasn't successful // Otherwise, we can't discribe what happend but it wasn't successful
default: default:
conv_function(PAM_ERROR_MSG, string("Unknown error:" + to_string(code)).c_str()); conv_function(PAM_ERROR_MSG,
string("Unknown error:" + to_string(code)).c_str());
syslog(LOG_INFO, "Failure, unknown error %d", code); syslog(LOG_INFO, "Failure, unknown error %d", code);
} }
} }
// As this function is only called for error status codes, signal an error to PAM // As this function is only called for error status codes, signal an error to
// PAM
return PAM_AUTH_ERR; return PAM_AUTH_ERR;
} }
@ -88,7 +90,10 @@ int on_howdy_auth(int code, function<int(int, const char *)> conv_function) {
* @param message String to show the user * @param message String to show the user
* @return Returns the conversation function return code * @return Returns the conversation function return code
*/ */
int send_message(function<int(int, const struct pam_message **, struct pam_response **, void *)> conv, int type, const char *message) { int send_message(function<int(int, const struct pam_message **,
struct pam_response **, void *)>
conv,
int type, const char *message) {
// Formet the message as PAM expects it // Formet the message as PAM expects it
// No need to free this, it's allocated on the stack // No need to free this, it's allocated on the stack
const struct pam_message msg = {.msg_style = type, .msg = message}; const struct pam_message msg = {.msg_style = type, .msg = message};
@ -111,7 +116,8 @@ int send_message(function<int(int, const struct pam_message **, struct pam_respo
* @param auth_tok True if we should ask for a password too * @param auth_tok True if we should ask for a password too
* @return Returns a PAM return code * @return Returns a PAM return code
*/ */
int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool auth_tok) { int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
bool auth_tok) {
// Open and read the config file // Open and read the config file
INIReader reader("/lib/security/howdy/config.ini"); INIReader reader("/lib/security/howdy/config.ini");
// Open the system log so we can write to it // Open the system log so we can write to it
@ -123,13 +129,15 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
int pam_res = PAM_IGNORE; int pam_res = PAM_IGNORE;
// Try to get the conversation function and error out if we can't // Try to get the conversation function and error out if we can't
if ((pam_res = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != PAM_SUCCESS) { if ((pam_res = pam_get_item(pamh, PAM_CONV, (const void **)&conv)) !=
PAM_SUCCESS) {
syslog(LOG_ERR, "Failed to acquire conversation"); syslog(LOG_ERR, "Failed to acquire conversation");
return pam_res; return pam_res;
} }
// Wrap the PAM conversation function in our own, easier function // Wrap the PAM conversation function in our own, easier function
auto conv_function = bind(send_message, conv->conv, placeholders::_1, placeholders::_2); auto conv_function =
bind(send_message, conv->conv, placeholders::_1, placeholders::_2);
// Error out if we could not ready the config file // Error out if we could not ready the config file
if (reader.ParseError() < 0) { if (reader.ParseError() < 0) {
@ -144,14 +152,17 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
// Stop if we're in a remote shell and configured to exit // Stop if we're in a remote shell and configured to exit
if (reader.GetBoolean("core", "ignore_ssh", true)) { if (reader.GetBoolean("core", "ignore_ssh", true)) {
if (getenv("SSH_CONNECTION") != nullptr || getenv("SSH_CLIENT") != nullptr || getenv("SSHD_OPTS") != nullptr) { if (getenv("SSH_CONNECTION") != nullptr ||
getenv("SSH_CLIENT") != nullptr || getenv("SSHD_OPTS") != nullptr) {
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} }
} }
// If enabled, send a notice to the user that facial login is being attempted // If enabled, send a notice to the user that facial login is being attempted
if (reader.GetBoolean("core", "detection_notice", false)) { if (reader.GetBoolean("core", "detection_notice", false)) {
if ((pam_res = conv_function(PAM_TEXT_INFO, "Attempting facial authentication")) != PAM_SUCCESS) { if ((pam_res = conv_function(PAM_TEXT_INFO,
"Attempting facial authentication")) !=
PAM_SUCCESS) {
syslog(LOG_ERR, "Failed to send detection notice"); syslog(LOG_ERR, "Failed to send detection notice");
} }
} }
@ -188,6 +199,7 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
} }
posix_spawn_file_actions_t file_actions; posix_spawn_file_actions_t file_actions;
posix_spawn_file_actions_init(&file_actions); posix_spawn_file_actions_init(&file_actions);
// We close stdout and stderr for the child
posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO); posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO);
posix_spawn_file_actions_addclose(&file_actions, STDERR_FILENO); posix_spawn_file_actions_addclose(&file_actions, STDERR_FILENO);
const char *const args[] = {"/usr/bin/python3", "/lib/security/howdy/compare.py", const char *const args[] = {"/usr/bin/python3", "/lib/security/howdy/compare.py",
@ -218,7 +230,8 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
packaged_task<int()> pass_task([&] { packaged_task<int()> pass_task([&] {
char *auth_tok_ptr = nullptr; char *auth_tok_ptr = nullptr;
int pam_res = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **) &auth_tok_ptr, nullptr); int pam_res = pam_get_authtok(pamh, PAM_AUTHTOK,
(const char **)&auth_tok_ptr, nullptr);
{ {
unique_lock<mutex> lk(m); unique_lock<mutex> lk(m);
t = Type::Pam; t = Type::Pam;
@ -239,6 +252,8 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
if (t == Type::Howdy) { if (t == Type::Howdy) {
if (auth_tok) { if (auth_tok) {
// We cancel the thread using pthread, pam_get_authtok seems to be a
// cancellation point
auto native_hd = pass_thread.native_handle(); auto native_hd = pass_thread.native_handle();
pthread_cancel(native_hd); pthread_cancel(native_hd);
pass_thread.join(); pass_thread.join();
@ -258,7 +273,7 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
} }
} else { } else {
kill(child_pid, SIGTERM); kill(child_pid, SIGTERM);
child_thread.join(); python_thread.join();
pass_thread.join(); pass_thread.join();
auto pam_res = pass_future.get(); auto pam_res = pass_future.get();
@ -269,26 +284,33 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, bool au
} }
} }
// Called by PAM when a user needs to be authenticated, for example by running the sudo command // Called by PAM when a user needs to be authenticated, for example by running
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { // the sudo command
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return identify(pamh, flags, argc, argv, true); return identify(pamh, flags, argc, argv, true);
} }
// Called by PAM when a session is started, such as by the su command // Called by PAM when a session is started, such as by the su command
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return identify(pamh, flags, argc, argv, false); return identify(pamh, flags, argc, argv, false);
} }
// The functions below are required by PAM, but not needed in this module // The functions below are required by PAM, but not needed in this module
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return PAM_IGNORE; return PAM_IGNORE;
} }
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return PAM_IGNORE; return PAM_IGNORE;
} }
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return PAM_IGNORE; return PAM_IGNORE;
} }
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
return PAM_IGNORE; return PAM_IGNORE;
} }