BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / remoting / host / pam_authorization_factory_posix.cc
blob7de2141fe2d50ab1cee1db275c3ad7b844e75e6e
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/pam_authorization_factory_posix.h"
7 #include <security/pam_appl.h>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/environment.h"
12 #include "remoting/base/logging.h"
13 #include "remoting/host/username.h"
14 #include "remoting/protocol/channel_authenticator.h"
15 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
17 namespace remoting {
19 namespace {
20 class PamAuthorizer : public protocol::Authenticator {
21 public:
22 PamAuthorizer(scoped_ptr<protocol::Authenticator> underlying);
23 ~PamAuthorizer() override;
25 // protocol::Authenticator interface.
26 State state() const override;
27 bool started() const override;
28 RejectionReason rejection_reason() const override;
29 void ProcessMessage(const buzz::XmlElement* message,
30 const base::Closure& resume_callback) override;
31 scoped_ptr<buzz::XmlElement> GetNextMessage() override;
32 const std::string& GetAuthKey() const override;
33 scoped_ptr<protocol::ChannelAuthenticator> CreateChannelAuthenticator()
34 const override;
36 private:
37 void MaybeCheckLocalLogin();
38 bool IsLocalLoginAllowed();
39 void OnMessageProcessed(const base::Closure& resume_callback);
41 static int PamConversation(int num_messages,
42 const struct pam_message** messages,
43 struct pam_response** responses,
44 void* context);
46 scoped_ptr<protocol::Authenticator> underlying_;
47 enum { NOT_CHECKED, ALLOWED, DISALLOWED } local_login_status_;
49 } // namespace
51 PamAuthorizer::PamAuthorizer(scoped_ptr<protocol::Authenticator> underlying)
52 : underlying_(underlying.Pass()),
53 local_login_status_(NOT_CHECKED) {
56 PamAuthorizer::~PamAuthorizer() {
59 protocol::Authenticator::State PamAuthorizer::state() const {
60 if (local_login_status_ == DISALLOWED) {
61 return REJECTED;
62 } else {
63 return underlying_->state();
67 bool PamAuthorizer::started() const {
68 return underlying_->started();
71 protocol::Authenticator::RejectionReason
72 PamAuthorizer::rejection_reason() const {
73 if (local_login_status_ == DISALLOWED) {
74 return INVALID_CREDENTIALS;
75 } else {
76 return underlying_->rejection_reason();
80 void PamAuthorizer::ProcessMessage(const buzz::XmlElement* message,
81 const base::Closure& resume_callback) {
82 // |underlying_| is owned, so Unretained() is safe here.
83 underlying_->ProcessMessage(message, base::Bind(
84 &PamAuthorizer::OnMessageProcessed,
85 base::Unretained(this), resume_callback));
88 void PamAuthorizer::OnMessageProcessed(const base::Closure& resume_callback) {
89 MaybeCheckLocalLogin();
90 resume_callback.Run();
93 scoped_ptr<buzz::XmlElement> PamAuthorizer::GetNextMessage() {
94 scoped_ptr<buzz::XmlElement> result(underlying_->GetNextMessage());
95 MaybeCheckLocalLogin();
96 return result.Pass();
99 const std::string& PamAuthorizer::GetAuthKey() const {
100 return underlying_->GetAuthKey();
103 scoped_ptr<protocol::ChannelAuthenticator>
104 PamAuthorizer::CreateChannelAuthenticator() const {
105 return underlying_->CreateChannelAuthenticator();
108 void PamAuthorizer::MaybeCheckLocalLogin() {
109 if (local_login_status_ == NOT_CHECKED && state() == ACCEPTED) {
110 local_login_status_ = IsLocalLoginAllowed() ? ALLOWED : DISALLOWED;
114 bool PamAuthorizer::IsLocalLoginAllowed() {
115 std::string username = GetUsername();
116 if (username.empty()) {
117 return false;
119 struct pam_conv conv = { PamConversation, nullptr };
120 pam_handle_t* handle = nullptr;
121 int result = pam_start("chrome-remote-desktop", username.c_str(),
122 &conv, &handle);
123 if (result == PAM_SUCCESS) {
124 result = pam_acct_mgmt(handle, 0);
126 pam_end(handle, result);
128 HOST_LOG << "Local login check for " << username
129 << (result == PAM_SUCCESS ? " succeeded." : " failed.");
131 return result == PAM_SUCCESS;
134 int PamAuthorizer::PamConversation(int num_messages,
135 const struct pam_message** messages,
136 struct pam_response** responses,
137 void* context) {
138 // Assume we're only being asked to log messages, in which case our response
139 // need to be free()-able zero-initialized memory.
140 *responses = static_cast<struct pam_response*>(
141 calloc(num_messages, sizeof(struct pam_response)));
143 // We don't expect this function to be called. Since we have no easy way
144 // of returning a response, we consider it to be an error if we're asked
145 // for one and abort. Informational and error messages are logged.
146 for (int i = 0; i < num_messages; ++i) {
147 const struct pam_message* message = messages[i];
148 switch (message->msg_style) {
149 case PAM_ERROR_MSG:
150 LOG(ERROR) << "PAM conversation error message: " << message->msg;
151 break;
152 case PAM_TEXT_INFO:
153 HOST_LOG << "PAM conversation message: " << message->msg;
154 break;
155 default:
156 LOG(FATAL) << "Unexpected PAM conversation response required: "
157 << message->msg << "; msg_style = " << message->msg_style;
160 return PAM_SUCCESS;
164 PamAuthorizationFactory::PamAuthorizationFactory(
165 scoped_ptr<protocol::AuthenticatorFactory> underlying)
166 : underlying_(underlying.Pass()) {
169 PamAuthorizationFactory::~PamAuthorizationFactory() {
172 scoped_ptr<protocol::Authenticator>
173 PamAuthorizationFactory::CreateAuthenticator(
174 const std::string& local_jid,
175 const std::string& remote_jid,
176 const buzz::XmlElement* first_message) {
177 scoped_ptr<protocol::Authenticator> authenticator(
178 underlying_->CreateAuthenticator(local_jid, remote_jid, first_message));
179 return make_scoped_ptr(new PamAuthorizer(authenticator.Pass()));
183 } // namespace remoting