Skip to content

Commit

Permalink
pam: made it more error tolerant and readable
Browse files Browse the repository at this point in the history
  • Loading branch information
franku committed Oct 31, 2018
1 parent d4773d0 commit 8a0122f
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 74 deletions.
17 changes: 11 additions & 6 deletions core/src/console/auth_pam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ bool ConsolePamAuthenticate(FILE *std_in, BareosSocket *UA_sock)
if(tid) {
StopBsockTimer(tid);
}
tid = StartBsockTimer(UA_sock, 10);
tid = StartBsockTimer(UA_sock, 30);
if (!tid) {
error = true;
}
Expand All @@ -74,8 +74,13 @@ bool ConsolePamAuthenticate(FILE *std_in, BareosSocket *UA_sock)
state = PamAuthState::RECEIVE_MSG;
break;
case PAM_SUCCESS:
state = PamAuthState::AUTH_OK;
quit = true;
if (UA_sock->recv() == 1) {
state = PamAuthState::AUTH_OK;
quit = true;
} else {
Dmsg0(100, "Error, did not receive 2nd part of a message\n");
error = true;
}
break;
default:
Dmsg1(100, "Error, unknown pam type %d\n", type);
Expand Down Expand Up @@ -115,14 +120,14 @@ bool ConsolePamAuthenticate(FILE *std_in, BareosSocket *UA_sock)
if(userinput) {
Actuallyfree(userinput);
}
if(tid) {
StopBsockTimer(tid);
}
error = true;
break;
}
}; /* while (!quit) */

if(tid) {
StopBsockTimer(tid);
}
SetEcho (std_in, true);
ConsoleOutput("\n");

Expand Down
72 changes: 45 additions & 27 deletions core/src/console/console.cc
Original file line number Diff line number Diff line change
Expand Up @@ -859,27 +859,38 @@ static bool SelectDirector(const char *director, DirectorResource **ret_dir, Con
return 1;
}

static BStringList ReadPamCredentialsFile(const std::string &pam_credentials_filename)
{
std::ifstream s(pam_credentials_filename);
std::string user, pw;
if (!s.is_open()) {
Emsg0(M_ERROR_TERM, 0, _("Could not open PAM credentials file.\n"));
return BStringList();
} else {
std::getline(s, user);
std::getline(s, pw);
if (user.empty() || pw.empty()) {
Emsg0(M_ERROR_TERM, 0, _("Could not read user or password.\n"));
return BStringList();
}
}
BStringList args;
args << user << pw;
return args;
}

static bool ExaminePamAuthentication(bool use_pam_credentials_file, const std::string &pam_credentials_filename)
{
if (use_pam_credentials_file) {
std::ifstream s(pam_credentials_filename);
if (!s.is_open()) {
Emsg0(M_ERROR_TERM, 0, _("Could not open PAM credentials file.\n"));
return false;
} else {
std::string user, pw;
std::getline(s, user);
std::getline(s, pw);
if (user.empty() || pw.empty()) {
Emsg0(M_ERROR_TERM, 0, _("Could not read user or password.\n"));
return false;
}
BStringList args;
args << user << pw;
UA_sock->FormatAndSendResponseMessage(kMessageIdPamUserCredentials, args);
BStringList args(ReadPamCredentialsFile(pam_credentials_filename));
if(args.empty()) {
return false;
}
UA_sock->StartTimer(30);
UA_sock->FormatAndSendResponseMessage(kMessageIdPamUserCredentials, args);
UA_sock->StopTimer();
} else {
UA_sock->FormatAndSendResponseMessage(kMessageIdPamInteractive, "OK");
UA_sock->FormatAndSendResponseMessage(kMessageIdPamInteractive, std::string());
if (!ConsolePamAuthenticate(stdin, UA_sock)) {
TerminateConsole(0);
return false;
Expand All @@ -889,7 +900,10 @@ static bool ExaminePamAuthentication(bool use_pam_credentials_file, const std::s
}

namespace console {
BareosSocket *ConnectToDirector(JobControlRecord &jcr, utime_t heart_beat, char *errmsg, int errmsg_len, uint32_t &response_id)
static BareosSocket *ConnectToDirector(JobControlRecord &jcr,
utime_t heart_beat,
BStringList &response_args,
uint32_t &response_id)
{
BareosSocketTCP *UA_sock = New(BareosSocketTCP);
if (!UA_sock->connect(NULL, 5, 15, heart_beat, "Director daemon", director_resource->address, NULL,
Expand Down Expand Up @@ -929,14 +943,12 @@ BareosSocket *ConnectToDirector(JobControlRecord &jcr, utime_t heart_beat, char

if (!UA_sock->DoTlsHandshake(tls_policy, local_tls_resource, false,
qualified_resource_name.c_str(), password->value, &jcr)) {
ConsoleOutput(errmsg);
TerminateConsole(0);
return nullptr;
}

if (!UA_sock->ConsoleAuthenticateWithDirector(&jcr, name, *password, errmsg,
errmsg_len, director_resource, response_id)) {
ConsoleOutput(errmsg);
if (!UA_sock->ConsoleAuthenticateWithDirector(&jcr, name, *password, director_resource,
response_args, response_id)) {
TerminateConsole(0);
return nullptr;
}
Expand All @@ -950,9 +962,7 @@ BareosSocket *ConnectToDirector(JobControlRecord &jcr, utime_t heart_beat, char
int main(int argc, char *argv[])
{
int ch;
int errmsg_len;
char *director = NULL;
char errmsg[1024];
bool list_directors = false;
bool no_signals = false;
bool test_config = false;
Expand All @@ -969,7 +979,6 @@ int main(int argc, char *argv[])
static const std::string program_arguments {"D:lc:d:nstu:x:?"};
#endif

errmsg_len = sizeof(errmsg);
setlocale(LC_ALL, "");
bindtextdomain("bareos", LOCALEDIR);
textdomain("bareos");
Expand Down Expand Up @@ -1141,20 +1150,29 @@ int main(int argc, char *argv[])
}

uint32_t response_id;
UA_sock = ConnectToDirector(jcr, heart_beat, errmsg, errmsg_len, response_id);
BStringList response_args;
UA_sock = ConnectToDirector(jcr, heart_beat, response_args, response_id);
if (!UA_sock) { return 1; }

UA_sock->OutputCipherMessageString(ConsoleOutput);

ConsoleOutput(errmsg);

if (response_id == kMessageIdPamRequired) {
if (!ExaminePamAuthentication(use_pam_credentials_file, pam_credentials_filename)) {
TerminateConsole(0);
return 1;
} else {
response_args.clear();
if (!UA_sock->ReceiveAndEvaluateResponseMessage(response_id, response_args)) {
TerminateConsole(0);
return 1;
}
}
}

if (response_id == kMessageIdOk) {
ConsoleOutput(response_args.JoinReadable().c_str());
}

Dmsg0(40, "Opened connection with Director daemon\n");

ConsoleOutput(_("\nEnter a period to cancel a command.\n"));
Expand Down
8 changes: 4 additions & 4 deletions core/src/dird/auth_pam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ static int PamConversationCallback(int num_msg, const struct pam_message **msgm,
switch (msgm[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
if (!PamConvSendMessage(pam_data->UA_sock_,
msgm[i]->msg, msgm[i]->msg_style)) {
if (!PamConvSendMessage(pam_data->UA_sock_,
msgm[i]->msg, msgm[i]->msg_style)) {
error = true;
break;
}
Expand All @@ -107,8 +107,8 @@ static int PamConversationCallback(int num_msg, const struct pam_message **msgm,
if (!PamConvSendMessage(pam_data->UA_sock_,
msgm[i]->msg, PAM_PROMPT_ECHO_ON)) {
error = true;
break;
}
}
break;
default:
Dmsg3(debuglevel, "message[%d]: pam error type: %d error: \"%s\"\n",
1, msgm[i]->msg_style, msgm[i]->msg);
Expand Down
30 changes: 14 additions & 16 deletions core/src/dird/authenticate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,23 +245,20 @@ static bool GetConsoleName(BareosSocket *ua_sock, std::string &name)
return true;
}

static void SendErrorMessage(std::string console_name, UaContext *ua)
static void LogErrorMessage(std::string console_name, UaContext *ua)
{
ua->UA_sock->fsend("%s", _(dir_not_authorized_message));
Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"), console_name.c_str(),
ua->UA_sock->who(), ua->UA_sock->host(), ua->UA_sock->port());
sleep(5);
}

static void SendOkMessage(UaContext *ua)
static void SendOkMessage(UaContext *ua, bool final_state)
{
char buffer[100];
::snprintf(buffer, 100, "OK: %s Version: %s (%s)", my_name, VERSION, BDATE);

if (ua->cons && ua->cons->use_pam_authentication_) {
ua->UA_sock->FormatAndSendResponseMessage(kMessageIdPamRequired, std::string(buffer));
} else {
if (final_state) {
char buffer[128];
::snprintf(buffer, 100, "OK: %s Version: %s (%s)", my_name, VERSION, BDATE);
ua->UA_sock->FormatAndSendResponseMessage(kMessageIdOk, std::string(buffer));
} else if (ua->cons && ua->cons->use_pam_authentication_) {
ua->UA_sock->FormatAndSendResponseMessage(kMessageIdPamRequired, std::string());
}
}

Expand Down Expand Up @@ -372,7 +369,6 @@ bool AuthenticateUserAgent(UaContext *ua)
}

if (NumberOfConsoleConnectionsExceeded()) {
ua->UA_sock->fsend("%s", _(dir_not_authorized_message));
Emsg0(M_ERROR, 0, _("Number of console connections exceeded MaximumConsoleConnections\n"));
return false;
}
Expand All @@ -381,23 +377,25 @@ bool AuthenticateUserAgent(UaContext *ua)

if (OptionalAuthenticateRootConsole(console_name, ua, auth_success)) {
if (!auth_success) {
SendErrorMessage(console_name, ua);
LogErrorMessage(console_name, ua);
return false;
} else {
SendOkMessage(ua);
SendOkMessage(ua, true);
}
} else {
AuthenticateNamedConsole(console_name, ua, auth_success);
if (!auth_success) {
SendErrorMessage(console_name, ua);
LogErrorMessage(console_name, ua);
return false;
} else {
SendOkMessage(ua);
SendOkMessage(ua, false);
}
if (OptionalAuthenticatePamUser(console_name, ua, auth_success)) {
if (!auth_success) {
SendErrorMessage(console_name, ua);
LogErrorMessage(console_name, ua);
return false;
} else {
SendOkMessage(ua, true);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions core/src/lib/bnet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ bool EvaluateResponseMessageId(const std::string &message, uint32_t &id_out, BSt

bool BareosSocket::ReceiveAndEvaluateResponseMessage(uint32_t &id_out, BStringList &args_out)
{
StartTimer(30); //30 seconds
int ret = recv();
StopTimer();

Expand All @@ -653,10 +654,13 @@ bool BareosSocket::FormatAndSendResponseMessage(uint32_t id, const BStringList &
m += AsciiControlCharacters::RecordSeparator();
m += list_of_agruments.Join(AsciiControlCharacters::RecordSeparator());

StartTimer(30); //30 seconds
if (send(m.c_str(), m.size()) <=0 ) {
Dmsg1(100, "Could not send response message: %d\n", m.c_str());
StopTimer();
return false;
}
StopTimer();
return true;
}

Expand Down
7 changes: 2 additions & 5 deletions core/src/lib/bsock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,16 +325,13 @@ static char hello[] = "Hello %s calling\n";
bool BareosSocket::ConsoleAuthenticateWithDirector(JobControlRecord *jcr,
const char *identity,
s_password &password,
char *response_text,
int response_len,
TlsResource *tls_resource,
BStringList &response_args,
uint32_t &response_id)
{
char bashed_name[MAX_NAME_LENGTH];
BareosSocket *dir = this; /* for readability */

response_text[0] = 0;

bstrncpy(bashed_name, identity, sizeof(bashed_name));
BashSpaces(bashed_name);

Expand All @@ -353,7 +350,7 @@ bool BareosSocket::ConsoleAuthenticateWithDirector(JobControlRecord *jcr,
BStringList args;
if (dir->ReceiveAndEvaluateResponseMessage(message_id, args)) {
response_id = message_id;
Bsnprintf(response_text, response_len, "%s\n", args.JoinReadable().c_str());
response_args = args;
return true;
}
Dmsg0(100, "Wrong Message Protocol ID\n");
Expand Down
3 changes: 1 addition & 2 deletions core/src/lib/bsock.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ class BareosSocket : public SmartAlloc {
bool ConsoleAuthenticateWithDirector(JobControlRecord *jcr,
const char *name,
s_password &password,
char *response,
int response_len,
TlsResource *tls_resource,
BStringList &response_args,
uint32_t &response_id);
bool ParameterizeAndInitTlsConnection(TlsResource *tls_resource,
const char *identity,
Expand Down
12 changes: 6 additions & 6 deletions core/src/lib/btimers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,15 @@ static btimer_t *btimer_start_common(uint32_t wait)
return wid;
}

/*
* Stop btimer
*/
static void StopBtimer(btimer_t *wid)
{
if (wid == NULL) {
Emsg0(M_ABORT, 0, _("StopBtimer called with NULL btimer_id\n"));
Emsg0(M_INFO, 0, _("StopBtimer called with NULL btimer_id\n"));
return;
}
if (wid->wd) {
UnregisterWatchdog(wid->wd);
free(wid->wd);
}
UnregisterWatchdog(wid->wd);
free(wid->wd);
free(wid);
}
4 changes: 2 additions & 2 deletions core/src/lib/signal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ extern "C" void SignalHandler(int sig)
pid_t pid;
int exelen = strlen(exepath);

fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
fprintf(stderr, _("%s, %s got signal %d - %s. Attempting traceback.\n"),
exename, my_name, sig, get_signal_name(sig));
fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
fprintf(stderr, _("exepath=%s\n"), exepath);

if (exelen + 12 > (int)sizeof(btpath)) {
bstrncpy(btpath, "btraceback", sizeof(btpath));
Expand Down
6 changes: 3 additions & 3 deletions core/src/qt-tray-monitor/authenticate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "lib/tls_conf.h"
#include "lib/bnet.h"
#include "lib/qualified_resource_name_type_converter.h"
#include "lib/bstringlist.h"

const int debuglevel = 50;

Expand Down Expand Up @@ -89,11 +90,10 @@ static AuthenticationResult AuthenticateWithDirector(JobControlRecord *jcr, Dire
return AuthenticationResult::kTlsHandshakeFailed;
}

char errmsg[1024];
int32_t errmsg_len = sizeof(errmsg);
uint32_t response_id;
BStringList response_args;
if (!dir->ConsoleAuthenticateWithDirector(jcr, monitor->name(), monitor->password,
errmsg, errmsg_len, dir_res, response_id)) {
dir_res, response_args, response_id)) {
Jmsg(jcr, M_FATAL, 0, _("Director authorization problem.\n"
"Most likely the passwords do not agree.\n"
"Please see %s for help.\n"), MANUAL_AUTH_URL);
Expand Down
Loading

0 comments on commit 8a0122f

Please sign in to comment.