This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Class LDAPLoginForm |
||
4 | * |
||
5 | * This not very interesting in itself. It's pretty much boiler-plate code to access the authenticator. |
||
6 | */ |
||
7 | class LDAPLoginForm extends MemberLoginForm |
||
0 ignored issues
–
show
|
|||
8 | { |
||
9 | /** |
||
10 | * This field is used in the "You are logged in as %s" message |
||
11 | * @var string |
||
12 | */ |
||
13 | public $loggedInAsField = 'FirstName'; |
||
14 | |||
15 | /** |
||
16 | * @var string |
||
17 | */ |
||
18 | protected $authenticator_class = 'LDAPAuthenticator'; |
||
19 | |||
20 | /** |
||
21 | * @var LDAPSecurityController |
||
22 | */ |
||
23 | protected $ldapSecController = null; |
||
24 | |||
25 | /** |
||
26 | * Time in seconds that we use to ensure consistent repsonse times |
||
27 | * |
||
28 | * @var int |
||
29 | */ |
||
30 | const RESPONSE_TIME = 2; |
||
31 | |||
32 | /** |
||
33 | * Enables consistent handling times of password resets |
||
34 | * @config |
||
35 | */ |
||
36 | private static $consistent_password_times = false; |
||
0 ignored issues
–
show
|
|||
37 | |||
38 | |||
39 | /** |
||
40 | * Constructor. |
||
41 | * |
||
42 | * @param Controller $controller |
||
43 | * @param string $name method on the $controller |
||
44 | * @param FieldList $fields |
||
45 | * @param FieldList $actions |
||
46 | * @param bool $checkCurrentUser - show logout button if logged in |
||
47 | */ |
||
48 | public function __construct($controller, $name, $fields = null, $actions = null, $checkCurrentUser = true) |
||
49 | { |
||
50 | parent::__construct($controller, $name, $fields, $actions, $checkCurrentUser); |
||
51 | |||
52 | // will be used to get correct Link() |
||
53 | $this->ldapSecController = Injector::inst()->create('LDAPSecurityController'); |
||
54 | |||
55 | if (Config::inst()->get('LDAPAuthenticator', 'allow_email_login')==='yes') { |
||
56 | $loginField = new TextField('Login', _t('LDAPLoginForm.USERNAMEOREMAIL', 'Username or email'), null, null, $this); |
||
57 | } else { |
||
58 | $loginField = new TextField('Login', _t('LDAPLoginForm.USERNAME', 'Username'), null, null, $this); |
||
59 | } |
||
60 | |||
61 | $this->Fields()->replaceField('Email', $loginField); |
||
62 | $this->setValidator(new RequiredFields('Login', 'Password')); |
||
63 | if (Security::config()->remember_username) { |
||
64 | $loginField->setValue(Session::get('SessionForms.MemberLoginForm.Email')); |
||
65 | } else { |
||
66 | // Some browsers won't respect this attribute unless it's added to the form |
||
67 | $this->setAttribute('autocomplete', 'off'); |
||
68 | $loginField->setAttribute('autocomplete', 'off'); |
||
69 | } |
||
70 | |||
71 | // Users can't change passwords unless appropriate a LDAP user with write permissions is |
||
72 | // configured the LDAP connection binding |
||
73 | $this->Actions()->remove($this->Actions()->fieldByName('forgotPassword')); |
||
74 | $allowPasswordChange = Config::inst()->get('LDAPService', 'allow_password_change'); |
||
75 | if ($allowPasswordChange && $name != 'LostPasswordForm' && !Member::currentUser()) { |
||
76 | $forgotPasswordLink = sprintf('<p id="ForgotPassword"><a href="%s">%s</a></p>', |
||
77 | $this->ldapSecController->Link('lostpassword'), |
||
78 | _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") |
||
79 | ); |
||
80 | $forgotPassword = new LiteralField('forgotPassword', $forgotPasswordLink); |
||
81 | $this->Actions()->add($forgotPassword); |
||
82 | } |
||
83 | |||
84 | // Focus on the Username field when the page is loaded |
||
85 | Requirements::block('MemberLoginFormFieldFocus'); |
||
86 | $js = <<<JS |
||
87 | (function() { |
||
88 | var el = document.getElementById("Login"); |
||
89 | if(el && el.focus && (typeof jQuery == 'undefined' || jQuery(el).is(':visible'))) el.focus(); |
||
90 | })(); |
||
91 | JS; |
||
92 | Requirements::customScript($js, 'LDAPLoginFormFieldFocus'); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Forgot password form handler method. |
||
97 | * |
||
98 | * Called when the user clicks on "I've lost my password". |
||
99 | * |
||
100 | * Extensions can use the 'forgotPassword' method to veto executing |
||
101 | * the logic, by returning FALSE. In this case, the user will be redirected back |
||
102 | * to the form without further action. It is recommended to set a message |
||
103 | * in the form detailing why the action was denied. |
||
104 | * |
||
105 | * Overridden because we need to generate a link to the LDAPSecurityController |
||
106 | * instead of the SecurityController |
||
107 | * |
||
108 | * @param array $data Submitted data |
||
109 | * @return SS_HTTPResponse |
||
110 | */ |
||
111 | public function forgotPassword($data) |
||
112 | { |
||
113 | // Passing true returns a float rather than a string |
||
114 | $startTime = microtime(true); |
||
115 | // No need to protect against injections, LDAPService will ensure that this is safe |
||
116 | $login = trim($data['Login']); |
||
117 | |||
118 | $service = Injector::inst()->get('LDAPService'); |
||
119 | if (Email::validEmailAddress($login)) { |
||
0 ignored issues
–
show
The method
Email::validEmailAddress() has been deprecated with message: 4.0 Use the "is_valid_address" method instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.
Loading history...
|
|||
120 | if (Config::inst()->get('LDAPAuthenticator', 'allow_email_login')!='yes') { |
||
121 | $this->sessionMessage( |
||
122 | _t( |
||
123 | 'LDAPLoginForm.USERNAMEINSTEADOFEMAIL', |
||
124 | 'Please enter your username instead of your email to get a password reset link.' |
||
125 | ), |
||
126 | 'bad' |
||
127 | ); |
||
128 | $this->consistentResponseTime($startTime); |
||
129 | $this->controller->redirect($this->controller->Link('lostpassword')); |
||
130 | return; |
||
131 | } |
||
132 | $userData = $service->getUserByEmail($login); |
||
133 | } else { |
||
134 | $userData = $service->getUserByUsername($login); |
||
135 | } |
||
136 | |||
137 | // Avoid information disclosure by displaying the same status, |
||
138 | // regardless whether the email address actually exists |
||
139 | if (!isset($userData['objectguid'])) { |
||
140 | $this->consistentResponseTime($startTime); |
||
141 | return $this->controller->redirect($this->controller->Link('passwordsent/') |
||
142 | . urlencode($data['Login'])); |
||
143 | } |
||
144 | |||
145 | $member = Member::get()->filter('GUID', $userData['objectguid'])->limit(1)->first(); |
||
146 | // User haven't been imported yet so do that now |
||
147 | View Code Duplication | if (!($member && $member->exists())) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
148 | $member = new Member(); |
||
149 | $member->GUID = $userData['objectguid']; |
||
150 | } |
||
151 | |||
152 | // Update the users from LDAP so we are sure that the email is correct. |
||
153 | // This will also write the Member record. |
||
154 | $service->updateMemberFromLDAP($member); |
||
155 | |||
156 | // Allow vetoing forgot password requests |
||
157 | $results = $this->extend('forgotPassword', $member); |
||
158 | if ($results && is_array($results) && in_array(false, $results, true)) { |
||
0 ignored issues
–
show
The expression
$results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
159 | $this->consistentResponseTime($startTime); |
||
160 | return $this->controller->redirect($this->ldapSecController->Link('lostpassword')); |
||
161 | } |
||
162 | |||
163 | if ($member) { |
||
164 | $token = $member->generateAutologinTokenAndStoreHash(); |
||
165 | $e = Member_ForgotPasswordEmail::create(); |
||
166 | $e->populateTemplate($member); |
||
167 | $e->populateTemplate([ |
||
168 | 'PasswordResetLink' => LDAPSecurityController::getPasswordResetLink($member, $token) |
||
169 | ]); |
||
170 | $e->setTo($member->Email); |
||
171 | $e->send(); |
||
172 | $this->consistentResponseTime($startTime); |
||
173 | $this->controller->redirect($this->controller->Link('passwordsent/') . urlencode($data['Login'])); |
||
174 | } elseif ($data['Login']) { |
||
175 | // Avoid information disclosure by displaying the same status, |
||
176 | // regardless whether the email address actually exists |
||
177 | $this->consistentResponseTime($startTime); |
||
178 | $this->controller->redirect($this->controller->Link('passwordsent/') . urlencode($data['Login'])); |
||
179 | } else { |
||
180 | if (Config::inst()->get('LDAPAuthenticator', 'allow_email_login')==='yes') { |
||
181 | $this->sessionMessage( |
||
182 | _t( |
||
183 | 'LDAPLoginForm.ENTERUSERNAMEOREMAIL', |
||
184 | 'Please enter your username or your email address to get a password reset link.' |
||
185 | ), |
||
186 | 'bad' |
||
187 | ); |
||
188 | } else { |
||
189 | $this->sessionMessage( |
||
190 | _t( |
||
191 | 'LDAPLoginForm.ENTERUSERNAME', |
||
192 | 'Please enter your username to get a password reset link.' |
||
193 | ), |
||
194 | 'bad' |
||
195 | ); |
||
196 | } |
||
197 | $this->consistentResponseTime($startTime); |
||
198 | $this->controller->redirect($this->controller->Link('lostpassword')); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * Ensures response times are the same across all scenarios i.e. email exists or doesn't |
||
204 | * this helps to avoid issues where malicious users could find if an email is legitimate based on response time |
||
205 | * |
||
206 | * @param float $startTime |
||
207 | */ |
||
208 | protected function consistentResponseTime($startTime) |
||
209 | { |
||
210 | if (!Config::inst()->get('LDAPLoginForm', 'consistent_password_times')) { |
||
211 | return; |
||
212 | } |
||
213 | |||
214 | $timeTaken = microtime(true) - $startTime; |
||
215 | if ($timeTaken < self::RESPONSE_TIME) { |
||
216 | $sleepTime = self::RESPONSE_TIME - $timeTaken; |
||
217 | // usleep takes microseconds, so we times our sleep period by 1mil (1mil ms = 1s) |
||
218 | usleep($sleepTime * 1000000); |
||
219 | } |
||
220 | |||
221 | } |
||
222 | } |
||
223 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.