Subversion Repositories oidplus

Rev

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