OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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. | |
4 | |
5 #include "remoting/host/user_auth_pam.h" | |
6 | |
7 #include <security/pam_appl.h> | |
8 #include <stdlib.h> | |
9 #include <string> | |
10 | |
11 namespace remoting { | |
12 | |
13 // Private Implementation pattern to avoid leaking PAM types, and the | |
14 // conversation function, into the header file. | |
15 class UserAuthPamPimpl { | |
16 public: | |
17 explicit UserAuthPamPimpl(UserAuthPam* user_auth_pam); | |
18 ~UserAuthPamPimpl(); | |
19 bool Authenticate(const std::string& username, | |
20 const std::string& password); | |
21 | |
22 private: | |
23 // Conversation function passed to PAM as a callback. | |
24 static int convFn(int num_msg, const struct pam_message** msg, | |
Sergey Ulanov
2011/02/10 20:14:28
ConvFunction?
| |
25 struct pam_response** resp, void* appdata_ptr); | |
26 | |
27 UserAuthPam* user_auth_pam_; | |
28 pam_handle_t* pam_handle_; | |
29 | |
30 // Store these for the PAM conversation function. | |
31 std::string username_; | |
32 std::string password_; | |
33 }; | |
34 | |
35 UserAuthPamPimpl::UserAuthPamPimpl(UserAuthPam* user_auth_pam) | |
36 : user_auth_pam_(user_auth_pam) { | |
37 } | |
38 | |
39 UserAuthPamPimpl::~UserAuthPamPimpl() { | |
40 } | |
41 | |
42 bool UserAuthPamPimpl::Authenticate(const std::string& username, | |
43 const std::string& password) { | |
Sergey Ulanov
2011/02/10 20:14:28
nit: wrapped arguments should be aligned with the
| |
44 username_ = username; | |
45 password_ = password; | |
46 struct pam_conv c; | |
47 c.conv = convFn; | |
48 c.appdata_ptr = static_cast<void*>(this); | |
49 // TODO(lambroslambrou): allow PAM service name to be configurable | |
Sergey Ulanov
2011/02/10 20:14:28
nit: comments should be full sentences: start with
| |
50 if (pam_start("chromoting", username_.c_str(), &c, &pam_handle_) != | |
51 PAM_SUCCESS) { | |
52 return false; | |
53 } | |
54 | |
55 // TODO(lambroslambrou): move to separate thread | |
Sergey Ulanov
2011/02/10 20:14:28
nit: same here
| |
56 int pam_status = pam_authenticate(pam_handle_, 0); | |
57 pam_end(pam_handle_, pam_status); | |
58 return pam_status == PAM_SUCCESS; | |
59 } | |
60 | |
61 // static | |
62 int UserAuthPamPimpl::convFn(int num_msg, const struct pam_message** msg, | |
63 struct pam_response** resp, void* appdata_ptr) { | |
Sergey Ulanov
2011/02/10 20:14:28
nit: indent properly
| |
64 if (num_msg <= 0) | |
65 return PAM_CONV_ERR; | |
66 UserAuthPamPimpl* user_auth = | |
67 reinterpret_cast<UserAuthPamPimpl*>(appdata_ptr); | |
68 // Must allocate with malloc(), as the calling PAM module will | |
69 // release the memory with free(). | |
70 struct pam_response* resp_tmp = reinterpret_cast<struct pam_response*>( | |
71 malloc(num_msg * sizeof(struct pam_response))); | |
72 if (resp_tmp == NULL) | |
73 return PAM_CONV_ERR; | |
74 bool raise_error = false; | |
75 int count; | |
Sergey Ulanov
2011/02/10 20:14:28
This can be inside of for()
| |
76 for (count = 0; count < num_msg; count++) { | |
77 // Alias for readability | |
Sergey Ulanov
2011/02/10 20:14:28
nit: period at the end of the sentence.
| |
78 struct pam_response &r = resp_tmp[count]; | |
79 r.resp_retcode = 0; | |
80 r.resp = NULL; | |
81 switch (msg[count]->msg_style) { | |
82 case PAM_PROMPT_ECHO_ON: | |
83 r.resp = strdup(user_auth->username_.c_str()); | |
84 if (r.resp == NULL) | |
85 raise_error = true; | |
86 break; | |
87 case PAM_PROMPT_ECHO_OFF: | |
88 r.resp = strdup(user_auth->password_.c_str()); | |
89 if (r.resp == NULL) | |
90 raise_error = true; | |
91 break; | |
92 case PAM_TEXT_INFO: | |
93 // No response needed, continue with next prompt. | |
94 break; | |
95 default: | |
96 // Unexpected style code, so abort. | |
97 raise_error = true; | |
98 } | |
99 if (raise_error) | |
100 break; | |
101 } | |
102 | |
103 if (raise_error) { | |
104 // Not passing the response back, so free up any memory used. | |
105 for (int n = 0; n < count; n++) { | |
106 if (resp_tmp[n].resp) { | |
107 free(resp_tmp[n].resp); | |
108 } | |
109 } | |
110 free(resp_tmp); | |
111 return PAM_CONV_ERR; | |
112 } else { | |
113 *resp = resp_tmp; | |
114 return PAM_SUCCESS; | |
115 } | |
116 } | |
117 | |
118 UserAuthPam::UserAuthPam() | |
119 : pimpl_(new UserAuthPamPimpl(this)) { | |
120 } | |
121 | |
122 UserAuthPam::~UserAuthPam() { | |
123 } | |
124 | |
125 bool UserAuthPam::Authenticate(const std::string& username, | |
126 const std::string& password) { | |
127 return pimpl_->Authenticate(username, password); | |
128 } | |
129 | |
130 } // namespace remoting | |
OLD | NEW |