Subversion Repositories oidplus

Rev

Rev 482 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
430 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2020 Daniel Marschall, ViaThinkSoft
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
class OIDplusPagePublicLoginLdap extends OIDplusPagePluginPublic {
21
 
22
        protected function ldapAuthByEMail($email, $password) {
482 daniel-mar 23
                $cfg_ldap_server      = OIDplus::baseConfig()->getValue('LDAP_SERVER');
24
                $cfg_ldap_port        = OIDplus::baseConfig()->getValue('LDAP_PORT', 389);
25
                $cfg_ldap_base_dn     = OIDplus::baseConfig()->getValue('LDAP_BASE_DN');
26
                $cfg_ldap_rdn         = OIDplus::baseConfig()->getValue('LDAP_CONTROLUSER_RDN');
27
                $cfg_ldap_password    = OIDplus::baseConfig()->getValue('LDAP_CONTROLUSER_PASSWORD');
28
                $cfg_ldap_user_filter = OIDplus::baseConfig()->getValue('LDAP_USER_FILTER', '(&(objectClass=user)(cn=*))');
430 daniel-mar 29
 
30
                // Connect to the server
31
                if (!empty($cfg_ldap_port)) {
32
                        if (!($ldapconn = @ldap_connect($cfg_ldap_server, $cfg_ldap_port))) throw new OIDplusException(_L('Cannot connect to LDAP server'));
33
                } else {
34
                        if (!($ldapconn = @ldap_connect($cfg_ldap_server))) throw new OIDplusException(_L('Cannot connect to LDAP server'));
35
                }
36
                ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
37
                ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
38
 
39
                // Login in order to search for the user
40
                if (!empty($cfg_ldap_rdn)) {
41
                        if (!empty($cfg_ldap_password)) {
42
                                if (!($ldapbind = @ldap_bind($ldapconn, $cfg_ldap_rdn, $cfg_ldap_password))) throw new OIDplusException(_L('System cannot login to LDAP in order to search the user'));
43
                        } else {
44
                                if (!($ldapbind = @ldap_bind($ldapconn, $cfg_ldap_rdn))) throw new OIDplusException(_L('System cannot login to LDAP in order to search the user'));
45
                        }
46
                } else {
47
                        if (!($ldapbind = @ldap_bind($ldapconn))) throw new OIDplusException(_L('System cannot login to LDAP in order to search the user'));
48
                }
49
 
50
                // Search the user using the email address
482 daniel-mar 51
                if (!($result = @ldap_search($ldapconn,$cfg_ldap_base_dn, $cfg_ldap_user_filter))) throw new OIDplusException(_L('Error in search query: %1', ldap_error($ldapconn)));
430 daniel-mar 52
                $data = ldap_get_entries($ldapconn, $result);
53
                $found_username = null;
54
                for ($i=0; $i<$data['count']; $i++) {
55
                        if ((isset($data[$i]['mail'][0])) && ($data[$i]['mail'][0] == $email)) {
56
                                $found_username = $data[$i]['userprincipalname'][0];
57
                                $ldap_userinfo = array();
58
                                foreach ($data[$i] as $x => $y) {
59
                                        if (is_int($x)) continue;
60
                                        if (!is_array($y)) continue;
61
                                        $ldap_userinfo[$x] = $y[0];
62
                                }
63
                        }
64
                }
65
                if (is_null($found_username)) return false;
66
 
67
                // Login as the new user in order to check the credentials
68
                //ldap_unbind($ldapconn); // commented out because ldap_unbind() kills the link descriptor
69
                if ($ldapbind = @ldap_bind($ldapconn, $found_username, $password)) {
70
                        //ldap_unbind($ldapconn);
71
                        ldap_close($ldapconn);
72
                        return $ldap_userinfo;
73
                } else {
74
                        return false;
75
                }
76
        }
77
 
78
        private function registerRA($ra, $ldap_userinfo) {
79
                $email = $ra->raEmail();
80
 
81
                $ra->register_ra(null); // create a user account without password
82
 
83
                /*
464 daniel-mar 84
                OIDplus DB Field          ActiveDirectory field
430 daniel-mar 85
                ------------------------------------------------
86
                ra_name                   cn
87
                personal_name             displayname (or: givenname + " " + sn)
88
                organization              company
89
                office                    physicaldeliveryofficename or department
90
                street                    streetaddress
91
                zip_town                  postalcode + " " + l
92
                country                   co (human-readable) or c (ISO country code)
93
                phone                     telephonenumber or homephone
94
                mobile                    mobile
95
                fax                       facsimiletelephonenumber
96
                (none)                    wwwhomepage
97
                */
98
 
99
                if (!isset($ldap_userinfo['cn']))                         $ldap_userinfo['cn'] = '';
100
                if (!isset($ldap_userinfo['displayname']))                $ldap_userinfo['displayname'] = '';
101
                if (!isset($ldap_userinfo['givenname']))                  $ldap_userinfo['givenname'] = '';
102
                if (!isset($ldap_userinfo['sn']))                         $ldap_userinfo['sn'] = '';
103
                if (!isset($ldap_userinfo['company']))                    $ldap_userinfo['company'] = '';
104
                if (!isset($ldap_userinfo['physicaldeliveryofficename'])) $ldap_userinfo['physicaldeliveryofficename'] = '';
105
                if (!isset($ldap_userinfo['department']))                 $ldap_userinfo['department'] = '';
106
                if (!isset($ldap_userinfo['streetaddress']))              $ldap_userinfo['streetaddress'] = '';
107
                if (!isset($ldap_userinfo['postalcode']))                 $ldap_userinfo['postalcode'] = '';
108
                if (!isset($ldap_userinfo['l']))                          $ldap_userinfo['l'] = '';
109
                if (!isset($ldap_userinfo['co']))                         $ldap_userinfo['co'] = '';
110
                if (!isset($ldap_userinfo['c']))                          $ldap_userinfo['c'] = '';
111
                if (!isset($ldap_userinfo['telephonenumber']))            $ldap_userinfo['telephonenumber'] = '';
112
                if (!isset($ldap_userinfo['homephone']))                  $ldap_userinfo['homephone'] = '';
113
                if (!isset($ldap_userinfo['mobile']))                     $ldap_userinfo['mobile'] = '';
114
                if (!isset($ldap_userinfo['facsimiletelephonenumber']))   $ldap_userinfo['facsimiletelephonenumber'] = '';
434 daniel-mar 115
                //if (!isset($ldap_userinfo['wwwhomepage']))                $ldap_userinfo['wwwhomepage'] = '';
430 daniel-mar 116
 
117
                $opuserdata = array();
118
                $opuserdata['ra_name'] = $ldap_userinfo['cn'];
119
                if (!empty($ldap_userinfo['displayname'])) {
120
                        $opuserdata['personal_name'] = $ldap_userinfo['displayname'];
121
                } else {
122
                        $opuserdata['personal_name'] = trim($ldap_userinfo['givenname'].' '.$ldap_userinfo['sn']);
123
                }
124
                $opuserdata['organization'] = $ldap_userinfo['company'];
125
                if (!empty($ldap_userinfo['physicaldeliveryofficename'])) {
126
                        $opuserdata['office'] = $ldap_userinfo['physicaldeliveryofficename'];
127
                } else {
128
                        $opuserdata['office'] = $ldap_userinfo['department'];
129
                }
130
                $opuserdata['street'] = $ldap_userinfo['streetaddress'];
131
                $opuserdata['zip_town'] = trim($ldap_userinfo['postalcode'].' '.$ldap_userinfo['l']);
132
                $opuserdata['country'] = $ldap_userinfo['co']; // ISO country code: $ldap_userinfo['c']
133
                $opuserdata['phone'] = $ldap_userinfo['telephonenumber']; // homephone for private phone number
134
                $opuserdata['mobile'] = $ldap_userinfo['mobile'];
135
                $opuserdata['fax'] = $ldap_userinfo['facsimiletelephonenumber'];
136
 
137
                foreach ($opuserdata as $dbfield => $val) {
138
                        if (!empty($val)) {
139
                                OIDplus::db()->query("update ###ra set ".$dbfield." = ? where email = ?", array($val, $email));
140
                        }
141
                }
142
        }
143
 
144
        public function action($actionID, $params) {
145
                if ($actionID == 'ra_login_ldap') {
146
                        if (!OIDplus::baseConfig()->getValue('LDAP_ENABLED', false)) {
147
                                throw new OIDplusException(_L('LDAP authentication is disabled on this system.'));
148
                        }
149
 
464 daniel-mar 150
                        if (!function_exists('ldap_connect')) throw new OIDplusConfigInitializationException(_L('PHP extension "%1" not installed','LDAP'));
151
 
430 daniel-mar 152
                        if (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false)) {
153
                                $secret=OIDplus::baseConfig()->getValue('RECAPTCHA_PRIVATE', '');
154
                                $response=$params["captcha"];
155
                                $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
156
                                $captcha_success=json_decode($verify);
157
                                if ($captcha_success->success==false) {
158
                                        throw new OIDplusException(_L('CAPTCHA not successfully verified'));
159
                                }
160
                        }
161
 
162
                        $email = $params['email'];
163
                        $password = $params['password'];
164
 
165
                        if (empty($email)) {
166
                                throw new OIDplusException(_L('Please enter a valid email address'));
167
                        }
168
 
169
                        if (!($ldap_userinfo = $this->ldapAuthByEMail($email, $password))) {
170
                                if (OIDplus::config()->getValue('log_failed_ra_logins', false)) {
171
                                        OIDplus::logger()->log("[WARN]A!", "Failed login to RA account '$email' using LDAP");
172
                                }
173
                                throw new OIDplusException(_L('Wrong password or user not registered'));
174
                        }
175
 
176
                        $ra = new OIDplusRA($email);
177
                        if (!$ra->existing()) {
178
                                $this->registerRA($ra, $ldap_userinfo);
179
                                OIDplus::logger()->log("[INFO]RA($email)!", "RA '$email' was created because of successful LDAP login");
180
                        }
181
 
182
                        OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged in via LDAP");
183
                        OIDplus::authUtils()::raLogin($email);
184
 
185
                        OIDplus::db()->query("UPDATE ###ra set last_login = ".OIDplus::db()->sqlDate()." where email = ?", array($email));
186
 
187
                        return array("status" => 0);
188
                } else {
189
                        throw new OIDplusException(_L('Unknown action ID'));
190
                }
191
        }
192
 
193
        public function init($html=true) {
194
                // Nothing
195
        }
196
 
197
        public function gui($id, &$out, &$handled) {
198
                if ($id === 'oidplus:login_ldap') {
199
                        $handled = true;
200
                        $out['title'] = _L('Login using LDAP / ActiveDirectory');
201
                        $out['icon']  = OIDplus::webpath(__DIR__).'icon_big.png';
202
 
203
                        if (!OIDplus::baseConfig()->getValue('LDAP_ENABLED', false)) {
204
                                $out['icon'] = 'img/error_big.png';
205
                                $out['text'] = _L('LDAP authentication is disabled on this system.');
206
                                return;
207
                        }
208
 
464 daniel-mar 209
                        if (!function_exists('ldap_connect')) {
210
                                $out['icon'] = 'img/error_big.png';
211
                                $out['text'] = _L('PHP extension "%1" not installed','LDAP');
212
                                return;
213
                        }
214
 
431 daniel-mar 215
                        $out['text'] = '';
216
 
430 daniel-mar 217
                        $out['text'] .= '<noscript>';
218
                        $out['text'] .= '<p>'._L('You need to enable JavaScript to use the login area.').'</p>';
219
                        $out['text'] .= '</noscript>';
220
 
221
                        $out['text'] .= '<div id="loginLdapArea" style="visibility: hidden">';
222
                        $out['text'] .= (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false) ?
223
                                        '<script> grecaptcha.render(document.getElementById("g-recaptcha"), { "sitekey" : "'.OIDplus::baseConfig()->getValue('RECAPTCHA_PUBLIC', '').'" }); </script>'.
224
                                        '<p>'._L('Before logging in, please solve the following CAPTCHA').'</p>'.
431 daniel-mar 225
                                        '<div id="g-recaptcha" class="g-recaptcha" data-sitekey="'.OIDplus::baseConfig()->getValue('RECAPTCHA_PUBLIC', '').'"></div>' : '');
430 daniel-mar 226
                        $out['text'] .= '<br>';
227
 
431 daniel-mar 228
                        $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:login').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Regular login method').'</a></p>';
229
 
230
                        $out['text'] .= '<h2>'._L('Login as RA').'</h2>';
231
 
430 daniel-mar 232
                        $login_list = OIDplus::authUtils()->loggedInRaList();
233
                        if (count($login_list) > 0) {
234
                                foreach ($login_list as $x) {
235
                                        $out['text'] .= '<p>'._L('You are logged in as %1','<b>'.$x->raEmail().'</b>').' (<a href="#" onclick="return raLogout('.js_escape($x->raEmail()).');">'._L('Logout').'</a>)</p>';
236
                                }
237
                                $out['text'] .= '<p>'._L('If you have more accounts, you can log in with another account here.').'</p>';
238
                        } else {
239
                                $out['text'] .= '<p>'._L('Enter your email address and your password to log in as Registration Authority.').'</p>';
240
                        }
241
                        $out['text'] .= '<form onsubmit="return raLoginLdapOnSubmit(this);">';
242
                        $out['text'] .= '<div><label class="padding_label">'._L('E-Mail').':</label><input type="text" name="email" value="" id="raLoginLdapEMail"></div>';
243
                        $out['text'] .= '<div><label class="padding_label">'._L('Password').':</label><input type="password" name="password" value="" id="raLoginLdapPassword"></div>';
244
                        $out['text'] .= '<br><input type="submit" value="'._L('Login').'"><br><br>';
245
                        $out['text'] .= '</form>';
246
 
247
                        $invitePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.2.92'); // OIDplusPageRaInvite
431 daniel-mar 248
                        $out['text'] .= '<p><abbr title="'._L('You don\'t need to register. Just enter your Windows/Company credentials.').'">'._L('How to register?').'</abbr></p>';
430 daniel-mar 249
 
250
                        $mins = ceil(OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60)/60);
251
                        $out['text'] .= '<p><font size="-1">'._L('<i>Privacy information</i>: By using the login functionality, you are accepting that a "session cookie" is temporarily stored in your browser. The session cookie is a small text file that is sent to this website every time you visit it, to identify you as an already logged in user. It does not track any of your online activities outside OIDplus. The cookie will be destroyed when you log out or after an inactivity of %1 minutes.', $mins);
252
                        $privacy_document_file = 'OIDplus/privacy_documentation.html';
253
                        $resourcePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.1.500'); // OIDplusPagePublicResources
496 daniel-mar 254
                        if (!is_null($resourcePlugin) && file_exists(OIDplus::localpath().'res/'.$privacy_document_file)) {
470 daniel-mar 255
                                $out['text'] .= ' <a '.OIDplus::gui()->link('oidplus:resources$'.$privacy_document_file.'#cookies').'>'._L('More information about the cookies used').'</a>';
430 daniel-mar 256
                        }
257
                        $out['text'] .= '</font></p></div>';
258
 
259
                        $out['text'] .= '<script>document.getElementById("loginLdapArea").style.visibility = "visible";</script>';
260
                }
261
        }
262
 
263
        public function publicSitemap(&$out) {
264
                $out[] = 'oidplus:login_ldap';
265
        }
266
 
267
        public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
268
                return true;
269
        }
270
 
271
        public function tree_search($request) {
272
                return false;
273
        }
274
 
275
        public function implementsFeature($id) {
276
                if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.5') return true; // alternativeLoginMethods
277
                return false;
278
        }
279
 
280
        public function alternativeLoginMethods() {
281
                $logins = array();
282
                if (OIDplus::baseConfig()->getValue('LDAP_ENABLED', false)) {
283
                        $logins[] = array(
284
                                'oidplus:login_ldap',
431 daniel-mar 285
                                _L('Login using LDAP / ActiveDirectory'),
430 daniel-mar 286
                                OIDplus::webpath(__DIR__).'treeicon.png'
287
                        );
288
                }
289
                return $logins;
290
        }
291
}