This source file includes following definitions.
- local_login_status_
- state
- rejection_reason
- ProcessMessage
- OnMessageProcessed
- GetNextMessage
- CreateChannelAuthenticator
- MaybeCheckLocalLogin
- IsLocalLoginAllowed
- PamConversation
- CreateAuthenticator
#include "remoting/host/pam_authorization_factory_posix.h"
#include <security/pam_appl.h>
#include "base/bind.h"
#include "base/callback.h"
#include "base/environment.h"
#include "remoting/base/logging.h"
#include "remoting/host/username.h"
#include "remoting/protocol/channel_authenticator.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
namespace remoting {
namespace {
class PamAuthorizer : public protocol::Authenticator {
public:
PamAuthorizer(scoped_ptr<protocol::Authenticator> underlying);
virtual ~PamAuthorizer();
virtual State state() const OVERRIDE;
virtual RejectionReason rejection_reason() const OVERRIDE;
virtual void ProcessMessage(const buzz::XmlElement* message,
const base::Closure& resume_callback) OVERRIDE;
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
virtual scoped_ptr<protocol::ChannelAuthenticator>
CreateChannelAuthenticator() const OVERRIDE;
private:
void MaybeCheckLocalLogin();
bool IsLocalLoginAllowed();
void OnMessageProcessed(const base::Closure& resume_callback);
static int PamConversation(int num_messages,
const struct pam_message** messages,
struct pam_response** responses,
void* context);
scoped_ptr<protocol::Authenticator> underlying_;
enum { NOT_CHECKED, ALLOWED, DISALLOWED } local_login_status_;
};
}
PamAuthorizer::PamAuthorizer(scoped_ptr<protocol::Authenticator> underlying)
: underlying_(underlying.Pass()),
local_login_status_(NOT_CHECKED) {
}
PamAuthorizer::~PamAuthorizer() {
}
protocol::Authenticator::State PamAuthorizer::state() const {
if (local_login_status_ == DISALLOWED) {
return REJECTED;
} else {
return underlying_->state();
}
}
protocol::Authenticator::RejectionReason
PamAuthorizer::rejection_reason() const {
if (local_login_status_ == DISALLOWED) {
return INVALID_CREDENTIALS;
} else {
return underlying_->rejection_reason();
}
}
void PamAuthorizer::ProcessMessage(const buzz::XmlElement* message,
const base::Closure& resume_callback) {
underlying_->ProcessMessage(message, base::Bind(
&PamAuthorizer::OnMessageProcessed,
base::Unretained(this), resume_callback));
}
void PamAuthorizer::OnMessageProcessed(const base::Closure& resume_callback) {
MaybeCheckLocalLogin();
resume_callback.Run();
}
scoped_ptr<buzz::XmlElement> PamAuthorizer::GetNextMessage() {
scoped_ptr<buzz::XmlElement> result(underlying_->GetNextMessage());
MaybeCheckLocalLogin();
return result.Pass();
}
scoped_ptr<protocol::ChannelAuthenticator>
PamAuthorizer::CreateChannelAuthenticator() const {
return underlying_->CreateChannelAuthenticator();
}
void PamAuthorizer::MaybeCheckLocalLogin() {
if (local_login_status_ == NOT_CHECKED && state() == ACCEPTED) {
local_login_status_ = IsLocalLoginAllowed() ? ALLOWED : DISALLOWED;
}
}
bool PamAuthorizer::IsLocalLoginAllowed() {
std::string username = GetUsername();
if (username.empty()) {
return false;
}
struct pam_conv conv = { PamConversation, NULL };
pam_handle_t* handle = NULL;
int result = pam_start("chrome-remote-desktop", username.c_str(),
&conv, &handle);
if (result == PAM_SUCCESS) {
result = pam_acct_mgmt(handle, 0);
}
pam_end(handle, result);
HOST_LOG << "Local login check for " << username
<< (result == PAM_SUCCESS ? " succeeded." : " failed.");
return result == PAM_SUCCESS;
}
int PamAuthorizer::PamConversation(int num_messages,
const struct pam_message** messages,
struct pam_response** responses,
void* context) {
*responses = static_cast<struct pam_response*>(
calloc(num_messages, sizeof(struct pam_response)));
for (int i = 0; i < num_messages; ++i) {
const struct pam_message* message = messages[i];
switch (message->msg_style) {
case PAM_ERROR_MSG:
LOG(ERROR) << "PAM conversation error message: " << message->msg;
break;
case PAM_TEXT_INFO:
HOST_LOG << "PAM conversation message: " << message->msg;
break;
default:
LOG(FATAL) << "Unexpected PAM conversation response required: "
<< message->msg << "; msg_style = " << message->msg_style;
}
}
return PAM_SUCCESS;
}
PamAuthorizationFactory::PamAuthorizationFactory(
scoped_ptr<protocol::AuthenticatorFactory> underlying)
: underlying_(underlying.Pass()) {
}
PamAuthorizationFactory::~PamAuthorizationFactory() {
}
scoped_ptr<protocol::Authenticator>
PamAuthorizationFactory::CreateAuthenticator(
const std::string& local_jid,
const std::string& remote_jid,
const buzz::XmlElement* first_message) {
scoped_ptr<protocol::Authenticator> authenticator(
underlying_->CreateAuthenticator(local_jid, remote_jid, first_message));
return scoped_ptr<protocol::Authenticator>(
new PamAuthorizer(authenticator.Pass()));
}
}