Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(620)

Unified Diff: remoting/host/user_auth_pam.cc

Issue 6484002: Authenticate user/password with PAM in BeginSessionRequest() (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Add UserAuthenticator interface Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/user_auth_pam.h ('k') | remoting/host/user_authenticator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/user_auth_pam.cc
diff --git a/remoting/host/user_auth_pam.cc b/remoting/host/user_auth_pam.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4d7b754c1d956ecbf9d888b6ac833906aeeb0733
--- /dev/null
+++ b/remoting/host/user_auth_pam.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/user_auth_pam.h"
+
+#include <security/pam_appl.h>
+#include <stdlib.h>
+#include <string>
+
+namespace remoting {
+
+// Private Implementation pattern to avoid leaking PAM types, and the
+// conversation function, into the header file.
+class UserAuthPamPimpl {
+ public:
+ explicit UserAuthPamPimpl(UserAuthPam* user_auth_pam);
+ ~UserAuthPamPimpl();
+ bool Authenticate(const std::string& username,
+ const std::string& password);
+
+ private:
+ // Conversation function passed to PAM as a callback.
+ static int ConvFunction(int num_msg,
+ const struct pam_message** msg,
+ struct pam_response** resp,
+ void* appdata_ptr);
+
+ UserAuthPam* user_auth_pam_;
+ pam_handle_t* pam_handle_;
+
+ // Store these for the PAM conversation function.
+ std::string username_;
+ std::string password_;
+};
+
+UserAuthPamPimpl::UserAuthPamPimpl(UserAuthPam* user_auth_pam)
+ : user_auth_pam_(user_auth_pam) {
+}
+
+UserAuthPamPimpl::~UserAuthPamPimpl() {
+}
+
+bool UserAuthPamPimpl::Authenticate(const std::string& username,
+ const std::string& password) {
+ username_ = username;
+ password_ = password;
+ struct pam_conv c;
+ c.conv = ConvFunction;
+ c.appdata_ptr = static_cast<void*>(this);
+ // TODO(lambroslambrou): Allow PAM service name to be configurable.
+ if (pam_start("chromoting", username_.c_str(), &c, &pam_handle_) !=
+ PAM_SUCCESS) {
+ return false;
+ }
+
+ // TODO(lambroslambrou): Move to separate thread.
+ int pam_status = pam_authenticate(pam_handle_, 0);
+ pam_end(pam_handle_, pam_status);
+ return pam_status == PAM_SUCCESS;
+}
+
+// static
+int UserAuthPamPimpl::ConvFunction(int num_msg,
+ const struct pam_message** msg,
+ struct pam_response** resp,
+ void* appdata_ptr) {
+ if (num_msg <= 0)
+ return PAM_CONV_ERR;
+ UserAuthPamPimpl* user_auth =
+ reinterpret_cast<UserAuthPamPimpl*>(appdata_ptr);
+ // Must allocate with malloc(), as the calling PAM module will
+ // release the memory with free().
+ struct pam_response* resp_tmp = reinterpret_cast<struct pam_response*>(
+ malloc(num_msg * sizeof(struct pam_response)));
+ if (resp_tmp == NULL)
+ return PAM_CONV_ERR;
+ bool raise_error = false;
+ // On exit from the loop, 'count' will hold the number of initialised items
+ // that the cleanup code needs to look at, in case of error.
+ int count;
+ for (count = 0; count < num_msg; count++) {
Sergey Ulanov 2011/02/14 18:58:25 nit: "for (int count = 0; count < num_msg; count++
Lambros 2011/02/14 19:12:14 The "count" is used outside the loop (on line 111)
+ // Alias for readability.
+ struct pam_response& r = resp_tmp[count];
+ r.resp_retcode = 0;
+ r.resp = NULL;
+ switch (msg[count]->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ r.resp = strdup(user_auth->username_.c_str());
+ if (r.resp == NULL)
+ raise_error = true;
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ r.resp = strdup(user_auth->password_.c_str());
+ if (r.resp == NULL)
+ raise_error = true;
+ break;
+ case PAM_TEXT_INFO:
+ // No response needed, continue with next prompt.
+ break;
+ default:
+ // Unexpected style code, so abort.
+ raise_error = true;
+ }
+ if (raise_error)
+ break;
+ }
+
+ if (raise_error) {
+ // Not passing the response back, so free up any memory used.
+ for (int n = 0; n < count; n++) {
+ if (resp_tmp[n].resp) {
+ free(resp_tmp[n].resp);
+ }
+ }
+ free(resp_tmp);
+ return PAM_CONV_ERR;
+ } else {
+ *resp = resp_tmp;
+ return PAM_SUCCESS;
+ }
+}
+
+UserAuthPam::UserAuthPam()
+ : pimpl_(new UserAuthPamPimpl(this)) {
Sergey Ulanov 2011/02/14 18:58:25 nit: This can fit on the previous line.
+}
+
+UserAuthPam::~UserAuthPam() {
+}
+
+bool UserAuthPam::Authenticate(const std::string& username,
+ const std::string& password) {
+ return pimpl_->Authenticate(username, password);
+}
+
+} // namespace remoting
« no previous file with comments | « remoting/host/user_auth_pam.h ('k') | remoting/host/user_authenticator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698