From 363844c39af5b8d4899a3f4b6a3e5d7382676b4f Mon Sep 17 00:00:00 2001 From: Frank Ueberschar Date: Mon, 15 Oct 2018 13:18:23 +0200 Subject: [PATCH] pam: implemented a local pam callback that uses a preset pam-password --- core/src/console/console.cc | 3 ++- core/src/dird/auth_pam.cc | 34 +++++++++++++++++++++------ core/src/dird/authenticate.cc | 44 +++++++++++++++++++++++------------ 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/core/src/console/console.cc b/core/src/console/console.cc index a41b6680491..185b04b7e37 100644 --- a/core/src/console/console.cc +++ b/core/src/console/console.cc @@ -1095,7 +1095,8 @@ int main(int argc, char *argv[]) #if defined(HAVE_PAM) if (console_resource && console_resource->use_pam_authentication_) { -// UA_sock->fsend("@@username:franku"); +// UA_sock->fsend("@@username:bareos-pam"); +// UA_sock->fsend("@@password:linuxlinux"); Bmicrosleep(1,0); if (!ConsolePamAuthenticate(stdin, UA_sock)) { TerminateConsole(0); diff --git a/core/src/dird/auth_pam.cc b/core/src/dird/auth_pam.cc index 72252a3ad1b..8ebed41d5aa 100644 --- a/core/src/dird/auth_pam.cc +++ b/core/src/dird/auth_pam.cc @@ -33,10 +33,11 @@ static const std::string service_name("bareos"); struct PamData { BareosSocket *UA_sock_; + const std::string &passwd_; - PamData(BareosSocket *UA_sock) { - UA_sock_ = UA_sock; - } + PamData(BareosSocket *UA_sock, const std::string& passwd) + : UA_sock_(UA_sock) + , passwd_(passwd) { } }; /* @@ -98,6 +99,7 @@ static int PamConversionCallback(int num_msg, const struct pam_message **msgm, } if (pam_data->UA_sock_->recv()) { resp[i].resp = actuallystrdup(pam_data->UA_sock_->msg); + resp[i].resp_retcode = 0; } if (pam_data->UA_sock_->IsStop() || pam_data->UA_sock_->IsError()) { error = true; @@ -119,7 +121,6 @@ static int PamConversionCallback(int num_msg, const struct pam_message **msgm, } /* switch (msgm[i]->msg_style) { */ } /* for( ; i < num_msg ..) */ - if (error) { for (int i = 0; i < num_msg; ++i) { if (resp[i].resp) { @@ -137,16 +138,35 @@ static int PamConversionCallback(int num_msg, const struct pam_message **msgm, return PAM_SUCCESS; } +static int PamLocalCallback(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) +{ + struct pam_response *resp = + reinterpret_cast (actuallycalloc( + num_msg, sizeof(struct pam_response))); + + PamData *pam_data = reinterpret_cast(appdata_ptr); + + if (num_msg == 1) { + resp[0].resp = actuallystrdup(pam_data->passwd_.c_str()); + resp[0].resp_retcode = 0; + } + + *response = resp; + return PAM_SUCCESS; +} + bool PamAuthenticateUser(BareosSocket *UA_sock, const std::string &username_in, const std::string &password_in, std::string& authenticated_username) { - std::unique_ptr pam_callback_data(new PamData(UA_sock)); + std::unique_ptr pam_callback_data(new PamData(UA_sock, password_in)); std::unique_ptr pam_conversation_container(new struct pam_conv); struct pam_handle *pamh; /* pam session handle */ - pam_conversation_container->conv = PamConversionCallback; + bool not_interactive = !username_in.empty() && !password_in.empty(); + pam_conversation_container->conv = not_interactive ? PamLocalCallback : PamConversionCallback; pam_conversation_container->appdata_ptr = pam_callback_data.get(); const char *username = username_in.empty() ? nullptr : username_in.c_str(); @@ -172,7 +192,7 @@ bool PamAuthenticateUser(BareosSocket *UA_sock, const void* data; err = pam_get_item(pamh, PAM_USER, &data); if (err != PAM_SUCCESS) { - Dmsg1(debuglevel, "PAM set_item failed: %s\n", pam_strerror(pamh, err)); + Dmsg1(debuglevel, "PAM get_item failed: %s\n", pam_strerror(pamh, err)); return false; } else { if (data) { diff --git a/core/src/dird/authenticate.cc b/core/src/dird/authenticate.cc index f5529f1d530..f127384ee4f 100644 --- a/core/src/dird/authenticate.cc +++ b/core/src/dird/authenticate.cc @@ -287,25 +287,35 @@ static void AuthenticateNamedConsole(std::string console_name, UaContext *ua, bo #if defined(HAVE_PAM) static void LookupTokenFromSocketStream(BareosSocket *ua_sock, const std::string& token, std::string& output) { - char buffer[128]; - memset(buffer, 0, sizeof(buffer)); + std::unique_ptr buffer(new char[token.size()]); + memset(buffer.get(), 0, token.size()); + int flags = ua_sock->SetNonblocking(); - int ret = ::recv(ua_sock->fd_, buffer, token.size(), MSG_PEEK); - if (ret == (int)token.size()) { - if (ua_sock->recv() <= 0) { return; } - std::string temp(ua_sock->msg); - output = temp.substr(temp.find(':')+1); - } + + int tries = 3; + bool ready = false; + + do { + Bmicrosleep(1,0); + int ret = ::recv(ua_sock->fd_, buffer.get(), token.size(), MSG_PEEK); + if (ret == (int)token.size()) { + if (ua_sock->recv() <= 0) { return; } + std::string temp(ua_sock->msg); + output = temp.substr(temp.find(':')+1); + ready = true; + } + } while (tries-- && !ready); + ua_sock->RestoreBlocking(flags); } -static void LookupOptionalPamUser(BareosSocket *ua_sock, std::string& pam_username) +static void LookupOptionalUsername(BareosSocket *ua_sock, std::string& pam_username) { const std::string token {"@@username:"}; LookupTokenFromSocketStream(ua_sock, token, pam_username); } -static void LookupOptionalPamPassword(BareosSocket *ua_sock, std::string& pam_password) +static void LookupOptionalPassword(BareosSocket *ua_sock, std::string& pam_password) { const std::string token {"@@password:"}; LookupTokenFromSocketStream(ua_sock, token, pam_password); @@ -329,9 +339,8 @@ static bool OptionalAuthenticatePamUser(std::string console_name, UaContext *ua, std::string pam_username; std::string pam_password; - Bmicrosleep(1,0); - LookupOptionalPamUser(ua->UA_sock, pam_username); - LookupOptionalPamPassword(ua->UA_sock, pam_password); + LookupOptionalUsername(ua->UA_sock, pam_username); + LookupOptionalPassword(ua->UA_sock, pam_password); std::string authenticated_username; if (!PamAuthenticateUser(ua->UA_sock, pam_username, pam_password, authenticated_username)) { @@ -340,8 +349,13 @@ static bool OptionalAuthenticatePamUser(std::string console_name, UaContext *ua, } else { ConsoleResource *user = (ConsoleResource *)my_config->GetResWithName(R_CONSOLE, authenticated_username.c_str()); - ua->cons = user; - auth_success = true; + if (!user) { + ua->cons = nullptr; + auth_success = false; + } else { + ua->cons = user; + auth_success = true; + } } return true; } /* HAVE PAM */