GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (4873)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

plugins/ldap/include/ldapPlugin.class.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) Enalean, 2012-2015. All Rights Reserved.
4
 * Copyright (c) STMicroelectronics, 2008. All Rights Reserved.
5
 *
6
 * Originally written by Manuel Vacelet, 2008
7
 *
8
 * This file is a part of Tuleap.
9
 *
10
 * Tuleap is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * Tuleap is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with Tuleap; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24
25
require_once 'autoload.php';
26
require_once 'constants.php';
27
28
class LdapPlugin extends Plugin {
29
    /**
30
     * @type LDAP
31
     */
32
    private $ldapInstance;
33
34
    /**
35
     * @var LDAP
36
     */
37
    private $ldap_write_instance;
38
39
    /**
40
     * @type LDAP_UserManager
41
     */
42
    private $_ldapUmInstance;
43
44
    function __construct($id) {
45
        parent::__construct($id);
46
    }
47
48
    public function getHooksAndCallbacks() {
49
        // Layout
50
        $this->_addHook('display_newaccount', 'forbidIfLdapAuth', false);
51
        $this->_addHook('before_register', 'before_register', false);
52
        
53
        // Search
54
        $this->addHook(Event::LAYOUT_SEARCH_ENTRY);
55
        $this->addHook(Event::SEARCH_TYPE);
56
57
        // Authentication
58
        $this->_addHook(Event::SESSION_BEFORE_LOGIN, 'authenticate', false);
59
        $this->_addHook(Event::SESSION_AFTER_LOGIN, 'allowCodendiLogin', false);
60
61
        // Login
62
        $this->addHook('login_presenter');
63
        $this->_addHook('display_lostpw_createaccount', 'forbidIfLdapAuth', false);
64
        $this->_addHook('account_redirect_after_login', 'account_redirect_after_login', false);
65
66
        // User finder
67
        $this->_addHook('user_manager_find_user', 'user_manager_find_user', false);
68
        $this->_addHook('user_manager_get_user_by_identifier', 'user_manager_get_user_by_identifier', false);
69
70
        // User Home
71
        $this->_addHook('user_home_pi_entry', 'personalInformationEntry', false);  
72
        $this->_addHook('user_home_pi_tail', 'personalInformationTail', false);
73
74
        // User account
75
        $this->_addHook('account_pi_entry', 'accountPiEntry', false);
76
        $this->_addHook('before_change_email-complete', 'cancelChangeAndUserLdap', false);
77
        $this->_addHook('before_change_email-confirm', 'cancelChangeAndUserLdap', false);
78
        $this->_addHook('before_change_email', 'cancelChangeAndUserLdap', false);
79
        $this->_addHook('before_change_pw', 'cancelChangeAndUserLdap', false);
80
        $this->_addHook('before_change_realname', 'cancelChangeAndUserLdap', false);
81
        $this->_addHook('before_lostpw-confirm', 'cancelChange', false);
82
        $this->_addHook('before_lostpw', 'cancelChange', false);
83
        $this->_addHook('display_change_password', 'forbidIfLdapAuthAndUserLdap', false);
84
        $this->_addHook('display_change_email', 'forbidIfLdapAuthAndUserLdap', false);
85
        // Comment if want to allow real name change in LDAP mode
86
        $this->_addHook('display_change_realname', 'forbidIfLdapAuthAndUserLdap', false);
87
88
        // Site Admin
89
        $this->_addHook('before_admin_change_pw', 'warnNoPwChange', false);
90
        $this->_addHook('usergroup_update_form', 'addLdapInput', false);
91
        $this->_addHook('usergroup_update', 'updateLdapID', false);
92
93
        // Project admin
94
        $this->_addHook('ugroup_table_row',                 'ugroup_table_row',            false);
95
        $this->_addHook('project_admin_add_user_form',      'project_admin_add_user_form', false);
96
        $this->_addHook(Event::UGROUP_UPDATE_USERS_ALLOWED, 'ugroup_update_users_allowed', false);
97
98
        // Svn intro
99
        $this->addHook(Event::SVN_INTRO);
100
        $this->_addHook('svn_check_access_username', 'svn_check_access_username', false);
101
102
        // Search as you type user
103
        $this->_addHook('ajax_search_user', 'ajax_search_user', false);
104
        
105
        // Project creation
106
        $this->_addHook('register_project_creation', 'register_project_creation', false);
107
        
108
        // Backend SVN
109
        $this->_addHook('backend_factory_get_svn', 'backend_factory_get_svn', false);
110
        $this->_addHook(Event::SVN_APACHE_AUTH,    'svn_apache_auth',         false);
111
112
        // Daily codendi job
113
        $this->_addHook('codendi_daily_start', 'codendi_daily_start', false);
114
        
115
        // SystemEvent
116
        $this->_addHook(Event::SYSTEM_EVENT_GET_TYPES_FOR_DEFAULT_QUEUE);
117
        $this->_addHook(Event::GET_SYSTEM_EVENT_CLASS, 'get_system_event_class', false);
118
119
        // Ask for LDAP Username of a User
120
        $this->_addHook(Event::GET_LDAP_LOGIN_NAME_FOR_USER);
121
122
        // User profile creation/update
123
        $this->addHook(Event::USER_MANAGER_UPDATE_DB);
124
        $this->addHook(Event::USER_MANAGER_CREATE_ACCOUNT);
125
126
        if (defined('GIT_EVENT_PLATFORM_CAN_USE_GERRIT')) {
127
            $this->addHook(GIT_EVENT_PLATFORM_CAN_USE_GERRIT);
128
        }
129
130
        return parent::getHooksAndCallbacks();
131
    }
132
    
133
    /**
134
     * @return LdapPluginInfo
135
     */
136
    function getPluginInfo() {
137
        if (! $this->pluginInfo instanceof LdapPluginInfo) {
138
            $this->pluginInfo = new LdapPluginInfo($this);
139
        }
140
        return $this->pluginInfo;
141
    }
142
143
    /**
144
     * @return LDAP
145
     */
146
    public function getLdap() {
147
        if (!isset($this->ldapInstance)) {
148
            $this->ldapInstance = $this->instanciateLDAP();
149
        }
150
        return $this->ldapInstance;
151
    }
152
153
    private function instanciateLDAP() {
154
        return new LDAP(
155
            $this->getLDAPParams(),
156
            $this->getLogger(),
157
            $this->getQueryEscaper()
158
        );
159
    }
160
161
    /**
162
     * @return TruncateLevelLogger
163
     */
164
    public function getLogger() {
165
        return new TruncateLevelLogger(new BackendLogger(), ForgeConfig::get('sys_logger_level'));
166
    }
167
168
    /**
169
     * @return LDAP
170
     */
171
    public function getLDAPWrite() {
172
        if (! isset($this->ldap_write_instance)) {
173
            $ldap_params = $this->getLDAPParams();
174
            if (isset($ldap_params['server_type']) && $ldap_params['server_type'] == LDAP::SERVER_TYPE_ACTIVE_DIRECTORY ) {
175
                throw new LDAP_Exception_NoWriteException();
176
            } elseif (isset($ldap_params['write_server']) && trim($ldap_params['write_server']) != '') {
177
                $this->ldap_write_instance = $this->instanciateLDAP();
178
            } else {
179
                throw new LDAP_Exception_NoWriteException();
180
            }
181
        }
182
        return $this->ldap_write_instance;
183
    }
184
185
    private function hasLDAPWrite() {
186
        try {
187
            $this->getLDAPWrite();
188
            return true;
189
        } catch (LDAP_Exception_NoWriteException $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
190
191
        }
192
        return false;
193
    }
194
195
    private function getLDAPParams() {
196
        $ldap_params = array();
197
        $keys = $this->getPluginInfo()->propertyDescriptors->getKeys()->iterator();
198
        foreach ($keys as $k) {
199
            $nk = str_replace('sys_ldap_', '', $k);
200
            $ldap_params[$nk] = $this->getPluginInfo()->getPropertyValueForName($k);
201
        }
202
        return $ldap_params;
203
    }
204
205
    /**
206
     * Wrapper
207
     *
208
     * @return LDAP_UserManager
209
     */
210
    public function getLdapUserManager() {
211
        if (!isset($this->_ldapUmInstance)) {
212
            $this->_ldapUmInstance = new LDAP_UserManager($this->getLdap(), LDAP_UserSync::instance());
213
        }
214
        return $this->_ldapUmInstance;
215
    }
216
217
    public function getQueryEscaper() {
218
        return new LdapQueryEscaper();
219
    }
220
221
    /**
222
     * Hook
223
     * 
224
     * IN  $params['type_of_search']
225
     * OUT $params['output']
226
     * 
227
     * @param Array $params
228
     * 
229
     * @return void
230
     */
231
    function layout_search_entry($params) {
232
        $params['search_entries'][] = array(
233
            'value'    => 'people_ldap',
234
            'label'    => $GLOBALS['Language']->getText('plugin_ldap', 'people_ldap'),
235
            'selected' => $params['type_of_search'] == 'people_ldap',
236
        );
237
    }
238
239
    /**
240
     * Hook
241
     * 
242
     * IN  $params['codendiUserOnly']
243
     * IN  $params['limit']
244
     * IN  $params['searchToken']
245
     * IN  $params['validEmail']
246
     * OUT $params['userList']
247
     * OUT $params['pluginAnswered']
248
     * 
249
     * @param Array $params
250
     * 
251
     * @return void
252
     */
253
    function ajax_search_user($params) {
254
        if($this->isLDAPUserManagementEnabled() && !$params['codendiUserOnly']) {
255
            $params['pluginAnswered'] = true;
256
257
            $validEmail = isset($params['validEmail']) ? $params['validEmail'] : false;
258
259
            $ldap = $this->getLdap();
260
            $lri  = $ldap->searchUserAsYouType($params['searchToken'], $params['limit'], $validEmail);
261
            $sync = LDAP_UserSync::instance();
262
            foreach($lri as $lr) {
263
                if ($lr->exist() && $lr->valid()) {
264
                    $params['userList'][] = $sync->getCommonName($lr).' ('.$lr->getLogin().')';
265
                }
266
            }
267
            if($ldap->getErrno() == LDAP::ERR_SIZELIMIT) {
268
                $params['userList'][] = "<strong>...</strong>";
269
            }
270
        }
271
    }
272
273
    /**
274
     * @see Event::SEARCH_TYPE
275
     */
276
    public function search_type($params) {
277
        $query  = $params['query'];
278
        $result = $params['results'];
279
280
        if ($GLOBALS['sys_auth_type'] == 'ldap' && $query->getTypeOfSearch() == Search_SearchPeople::NAME) {
281
            $search = new LDAP_SearchPeople(UserManager::instance(), $this->getLdap());
282
            $presenter = $search->search($query, $query->getNumberOfResults(), $result);
283
            $result->setResultsHtml($this->getSearchTemplateRenderer()->renderToString($presenter->getTemplate(), $presenter));
284
        }
285
    }
286
287
    public function getSearchTemplateRenderer() {
288
        return TemplateRendererFactory::build()->getRenderer(
289
            array(
290
                dirname(__FILE__).'/../templates',
291
                ForgeConfig::get('codendi_dir') .'/src/templates/search',
292
            )
293
        );
294
    }
295
296
    /**
297
     * Hook
298
     * 
299
     * @params $params $params['login']
300
     *                 $params['password']
301
     *                 $params['auth_success']
302
     *                 $params['auth_user_id']
303
     *                 $params['auth_user_status']
304
     */
305
    function authenticate($params) {
306
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
307
            try {
308
                $params['auth_success'] = false;
309
310
                $user = $this->getLdapUserManager()->authenticate($params['loginname'], $params['passwd']);
311
                if ($user) {
312
                    $params['auth_user_id']     = $user->getId();
313
                    $params['auth_user_status'] = $user->getStatus();
314
                    $params['auth_success']     = true;
315
                }
316
            } catch (LDAP_UserNotFoundException $exception) {
317
                $GLOBALS['Response']->addFeedback(Feedback::ERROR, $exception->getMessage());
318
            } catch (LDAP_AuthenticationFailedException $exception) {
319
                $logger = new BackendLogger();
320
                $logger->info("[LDAP] User ".$params['loginname']." failed to authenticate");
321
            }
322
        }
323
    }
324
325
    /** Hook
326
     * When redirection after login happens, check if user as already filled
327
     * his personal info or not. If it's not the case, it means that the
328
     * account was automatically created and user must complete his
329
     * registeration.
330
     */
331
    function account_redirect_after_login($params) {
332
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
333
            $ldapUserDao = new LDAP_UserDao(CodendiDataAccess::instance());
334
            if(!$ldapUserDao->alreadyLoggedInOnce(user_getid())) {
335
                $return_to_arg = "";
336
                if($params['request']->existAndNonEmpty('return_to')) {
337
                    $return_to_arg ='?return_to='.urlencode($params['request']->get('return_to'));
338
                    if (isset($pv) && $pv == 2) $return_to_arg .= '&pv='.$pv;
0 ignored issues
show
The variable $pv seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
339
                } else {
340
                    if (isset($pv) && $pv == 2) $return_to_arg .= '?pv='.$pv;
341
                }
342
                $params['request']->set('return_to', '/plugins/ldap/welcome.php'.$return_to_arg);
343
            }
344
        }
345
    }
346
347
    /**
348
     * @params $params $params['user'] IN
349
     *                 $params['allow_codendi_login'] IN/OUT
350
     */
351
    function allowCodendiLogin($params) {
352
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
353
354
            if ($params['user']->getLdapId() != null) {
355
                $params['allow_codendi_login'] = false;
356
                return;
357
            }
358
359
            $ldapUm = $this->getLdapUserManager();
360
            $lr = $ldapUm->getLdapFromUserId($params['user']->getId());
361
            if($lr) {
362
                $params['allow_codendi_login'] = false;
363
                $GLOBALS['feedback'] .= ' '.$GLOBALS['Language']->getText('plugin_ldap',
364
                                                                          'login_pls_use_ldap',
365
                                                                          array($GLOBALS['sys_name']));
366
            }
367
            else {
368
                $params['allow_codendi_login'] = true;
369
            }
370
        }
371
372
        if ($this->hasLDAPWrite() && $params['user']->getLdapId() == null) {
373
            try {
374
                $this->getLDAPUserWrite()->updateWithUser($params['user']);
375
            } catch (Exception $exception) {
376
                $this->getLogger()->error('An error occured while registering user (session_after_login): '.$exception->getMessage());
377
            }
378
        }
379
    }
380
381
    /**
382
     * Get a User object from an LDAP iterator
383
     * 
384
     * @param LDAPResultIterator $lri An LDAP result iterator
385
     * 
386
     * @return PFUser
387
     */
388
    protected function getUserFromLdapIterator($lri) {
389
        if($lri && count($lri) === 1) {
390
            $ldapUm = $this->getLdapUserManager();
391
            return $ldapUm->getUserFromLdap($lri->current()); 
392
        }
393
        return null;
394
    }
395
396
    /**
397
     * Hook
398
     * Params:
399
     *  IN  $params['ident']
400
     *  IN/OUT  $params['user'] User object if found or null.
401
     */
402
    function user_manager_find_user($params) {
403
        if ($this->isLDAPUserManagementEnabled()) {
404
            $ldap = $this->getLdap();
405
            // First, test if its provided by autocompleter: "Common Name (login name)"
406
            $matches = array();
407
            if(preg_match('/^(.*) \((.*)\)$/', $params['ident'], $matches)) {
408
                if(trim($matches[2]) != '') {
409
                    $lri  = $ldap->searchLogin($matches[2]);
410
                } else {
411
                    $lri  = $ldap->searchCommonName($matches[1]);
412
                }
413
            } else {
414
                // Otherwise, search as defined in config most of the time
415
                // (uid, email, common name)
416
                $lri  = $ldap->searchUser($params['ident']);
417
            }
418
            $params['user'] = $this->getUserFromLdapIterator($lri);
419
        }
420
    }
421
422
    /**
423
     * $params['identifier'] IN
424
     * $params['user'] OUT
425
     * $params['tokenFound'] OUT
426
     *
427
     * @param unknown_type $params
428
     */
429
    function user_manager_get_user_by_identifier($params) {
430
        if ($GLOBALS['sys_auth_type'] == 'ldap' && $this->isLDAPUserManagementEnabled()) {
431
            // identifier = type:value
432
            $separatorPosition = strpos($params['identifier'], ':');
433
            $type = strtolower(substr($params['identifier'], 0, $separatorPosition));
434
            $value = strtolower(substr($params['identifier'], $separatorPosition + 1));
435
            
436
            $ldap = $this->getLdap();
437
            $lri = null;
438
            switch ($type) {
439
                case 'ldapid':
440
                    $params['tokenFound'] = true;
441
                    $lri = $ldap->searchEdUid($value);
442
                    break;
443
                case 'ldapdn':
444
                    $params['tokenFound'] = true;
445
                    $lri = $ldap->searchDn($value);
446
                    break;
447
                case 'ldapuid':
448
                    $params['tokenFound'] = true;
449
                    $lri = $ldap->searchLogin($value);
450
                    break;
451
            }
452
            $params['user'] = $this->getUserFromLdapIterator($lri);
0 ignored issues
show
It seems like $lri defined by null on line 437 can be null; however, LdapPlugin::getUserFromLdapIterator() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
453
        }
454
    }
455
456
    /**
457
     * Hook
458
     * Params:
459
     *  IN  $params['user_id']
460
     *  OUT $params['entry_label']
461
     *  OUT $params['entry_value']
462
     */
463
    function personalInformationEntry($params) {
464
        if($GLOBALS['sys_auth_type'] == 'ldap') {
465
            $params['entry_label'][$this->getId()] = $GLOBALS['Language']->getText('plugin_ldap', 'ldap_login');
466
            $ldapUm = $this->getLdapUserManager();
467
            $lr = $ldapUm->getLdapFromUserId($params['user_id']);
468
            if($lr) {
469
                $link = $this->buildLinkToDirectory($lr, $lr->getLogin());
470
                $params['entry_value'][$this->getId()] = $link;
471
            }
472
            else {
473
                $params['entry_value'][$this->getId()] = $GLOBALS['Language']->getText('plugin_ldap', 'no_ldap_login_found');
474
            }
475
        }
476
    }     
477
478
    /**
479
     * Hook
480
     * Params:
481
     *  IN  $params['user_id']
482
     *  OUT $params['entry_label']
483
     *  OUT $params['entry_value']
484
     *  OUT $params['entry_change']
485
     */
486
    function accountPiEntry($params) {
487
        if($GLOBALS['sys_auth_type'] == 'ldap') {
488
            $ldapUm = $this->getLdapUserManager();
489
            $lr = $ldapUm->getLdapFromUserId($params['user']->getId());
490
            if($lr) {
491
                $params['user_info'][] = new User_ImmutableInfoPresenter(
492
                    $GLOBALS['Language']->getText('plugin_ldap', 'ldap_login'),
493
                    $lr->getLogin()
494
                );
495
            } else {
496
                $params['user_info'][] = new User_ImmutableInfoPresenter(
497
                    $GLOBALS['Language']->getText('plugin_ldap', 'ldap_login'),
498
                    $GLOBALS['Language']->getText('plugin_ldap', 'no_ldap_login_found')
499
                );
500
            }
501
        }
502
    }
503
504
    /**
505
     * Hook
506
     */
507
    function personalInformationTail($params) {
508
        print '<TR>';
509
        $this->displayUserDetails($params['showdir']
510
                                  ,$params['user_name']);
511
        print '</TR>';
512
    }
513
514
    function buildLinkToDirectory(&$lr, $value='') {
515
        if($value === '') {
516
            $value = $lr->getLogin();
517
        }
518
519
        include_once($GLOBALS['Language']->getContent('directory_redirect', 'en_US', 'ldap'));
520
        if(function_exists('custom_build_link_to_directory')) {
521
            $link = custom_build_link_to_directory($lr, $value);
522
        }
523
        else {
524
            $link = $value;
525
        }
526
        return $link;
527
    }
528
529
    function displayUserDetails($showdir, $user_name) {
530
        include($GLOBALS['Language']->getContent('user_home', null, 'ldap'));
531
532
        if (!$showdir && $my_html_ldap_format) {
533
            echo '<td colspan="2" align="center"><a href="/users/'.$user_name.'/?showdir=1"><hr>[ '.$GLOBALS['Language']->getText('plugin_ldap','more_from_directory',$GLOBALS['sys_org_name']).'... ]</a><td>';
534
535
        } else {
536
            $ldapUm = $this->getLdapUserManager();
537
            $lr = $ldapUm->getLdapFromUserName($user_name);
538
539
            if (!$lr) {
540
                //$feedback = $GLOBALS['sys_org_name'].' '.$Language->getText('plugin_ldap','directory').': '.$ldap->getErrorMessage();
541
                echo '<td colspan="2" align="center"><hr><b>'.$feedback.'</b></td>';
0 ignored issues
show
The variable $feedback does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
542
            } else {
543
                // Format LDAP output based on templates given in user_home.php
544
545
                if ($my_html_ldap_format) {
546
                    preg_match_all("/%([\w\d\-\_]+)%/", $my_html_ldap_format, $matches);
0 ignored issues
show
The variable $my_html_ldap_format seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
547
                    foreach($matches[1] as $field) {
548
                        $value = $lr->get($field) ? $lr->get($field) : "-";
549
                        $my_html_ldap_format  = str_replace("%$field%", $value, $my_html_ldap_format);
550
                    }
551
                    echo $my_html_ldap_format;
552
                }
553
            }
554
        }
555
    }
556
557
    /**
558
     * Hook
559
     */
560
    function cancelChange($params) {
561
        if($GLOBALS['sys_auth_type'] == 'ldap') {
562
            exit_permission_denied();
563
        }
564
    }
565
566
    /**
567
     * Hook
568
     */
569
    function cancelChangeAndUserLdap($params) {
570
        $um = UserManager::instance();
571
        $user = $um->getCurrentUser();
572
        if($GLOBALS['sys_auth_type'] == 'ldap' && $user->getLdapId() != '') {
573
            if (! $this->hasLDAPWrite()) {
574
                exit_permission_denied();
575
            }
576
        }
577
    }
578
    
579
580
    function before_register($params) {
581
        if ($GLOBALS['sys_auth_type'] == 'ldap' && ! $this->hasLDAPWrite()) {
582
            if (isset($GLOBALS['sys_https_host']) && ($GLOBALS['sys_https_host'] != "")) {
583
                $host = 'https://'.$GLOBALS['sys_https_host'];
584
            } else {
585
                $host = 'http://'.$GLOBALS['sys_default_domain'];
586
            }
587
            util_return_to($host.'/account/login.php');
588
        }
589
    }
590
591
    function warnNoPwChange($params) {
592
        global $Language;
593
        if($GLOBALS['sys_auth_type'] == 'ldap') {
594
            // Won't change the LDAP password!
595
            echo "<p><b><span class=\"feedback\">".$Language->getText('admin_user_changepw','ldap_warning')."</span></b>";
596
        }
597
    }
598
599
    function addLdapInput($params) {
600
        global $Language;
601
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
602
            echo $Language->getText('admin_usergroup','ldap_id').': <INPUT TYPE="TEXT" NAME="ldap_id" VALUE="'.$params['row_user']['ldap_id'].'" SIZE="35" MAXLENGTH="55">
603
<P>';
604
        }
605
    }
606
607
    /**
608
     * Hook
609
     * 
610
     * $params['user_id']
611
     * 
612
     * @param $params
613
     * 
614
     * @return void
615
     */
616
    function updateLdapID($params) {
617
        global $Language;
618
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
619
            $request = HTTPRequest::instance();
620
            $ldapId = $request->getValidated('ldap_id', 'string', false);
621
            if($ldapId !== false) {
622
                $result = db_query("UPDATE user SET ldap_id='".db_es($ldapId)."' WHERE user_id=".db_ei($params['user_id']));
623
            }
624
            if (!$result) {
625
                $GLOBALS['feedback'] .= ' '.$Language->getText('admin_usergroup','error_upd_u');
626
                echo db_error();
627
            } else {
628
                $GLOBALS['feedback'] .= ' '.$Language->getText('admin_usergroup','success_upd_u');
629
            }
630
        }
631
    }
632
633
    /**
634
     * Hook
635
     * 
636
     * $params['allow']
637
     * 
638
     * @param Array $params
639
     * 
640
     * @return void
641
     */
642
    function forbidIfLdapAuth($params) {
643
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
644
            if (! $this->hasLDAPWrite()) {
645
                $params['allow'] = false;
646
            }
647
        }
648
    }
649
650
    /**
651
     * Hook
652
     * 
653
     * OUT $params['allow']
654
     * 
655
     * @param Array $params
656
     * 
657
     * @return void
658
     */
659
    function forbidIfLdapAuthAndUserLdap($params) {
660
        $um = UserManager::instance();
661
        $user = $um->getCurrentUser();
662
        if ($GLOBALS['sys_auth_type'] == 'ldap' && $user->getLdapId() != '') {
663
            if (! $this->hasLDAPWrite()) {
664
                $params['allow'] = false;
665
            }
666
        }
667
    }
668
669
    /**
670
     * @see Event::SVN_INTRO
671
     */
672
    public function svn_intro($params) {
673
        $ldap_project_manager = new LDAP_ProjectManager();
674
675
        if (ForgeConfig::get('sys_auth_type') === 'ldap' &&
676
           isset($params['group_id']) &&
677
           $ldap_project_manager->hasSVNLDAPAuth($params['group_id'])
678
        ) {
679
            $params['svn_intro_in_plugin'] = true;
680
            $params['svn_intro_info']      = $this->getLdapUserManager()->getLdapFromUserId(
681
                $params['user_id']
682
            );
683
        }
684
    }
685
686
    /**
687
     * Modify the user name before to check if user has access to given
688
     * ldap ressource (because users in .SVNAccessFile are defined with their
689
     * ldap login
690
     *
691
     * $params['project_svnroot']
692
     * $params['username']
693
     */
694
    function svn_check_access_username($params) {
695
        $svnProjectManager = new LDAP_ProjectManager();
696
        if($GLOBALS['sys_auth_type'] == 'ldap'
697
           && isset($params['project_svnroot'])
698
           && $svnProjectManager->hasSVNLDAPAuthByName(basename($params['project_svnroot']))) {
699
               $ldapUm = $this->getLdapUserManager();
700
               $lr     = $ldapUm->getLdapFromUserName($params['username']);
701
               if($lr !== false) {
702
                   // Must lower the username because LDAP is case insensitive
703
                   // while svn permission comparator is case sensitive and in
704
                   // backend the .SVNAccessFile is generated with lowercase
705
                   // usernames
706
                   $params['username'] = strtolower($lr->getLogin());
707
               }
708
        }
709
    }
710
711
    /**
712
     * Hook in upgroup edition
713
     * $params['row'] A row from ugroup table
714
     *
715
     * @param Array $params
716
     */
717
    function ugroup_table_row($params) {
718
        if($GLOBALS['sys_auth_type'] == 'ldap' && $this->isLDAPGroupsUsageEnabled()) {
719
            // No ldap for project 100
720
            if($params['row']['group_id'] != 100) {
721
                $hp = Codendi_HTMLPurifier::instance();
722
                $ldapUserGroupManager = new LDAP_UserGroupManager($this->getLdap());
723
                
724
                $baseUrl = $this->getPluginPath().'/ugroup_edit.php?ugroup_id='.$params['row']['ugroup_id'];
725
726
                $urlAdd = $this->getPluginPath().'/ugroup_add_user.php?ugroup_id='.$params['row']['ugroup_id'].'&func=add_user';
727
                $linkAdd = '<a href="'.$urlAdd.'">- '.$GLOBALS['Language']->getText('plugin_ldap', 'ugroup_list_add_users').'</a><br/>';
728
                if (!$ldapUserGroupManager->isMembersUpdateAllowed($params['row']['ugroup_id'])) {
729
                    $linkAdd = '';
730
                }
731
732
                $ldapGroup = $ldapUserGroupManager->getLdapGroupByGroupId($params['row']['ugroup_id']);
733
                if($ldapGroup !== null) {
734
                    $grpName = $hp->purify($ldapGroup->getCommonName());
735
                    $title = $GLOBALS['Language']->getText('plugin_ldap', 'ugroup_list_add_upd_binding', $grpName);
736
                } else {
737
                    $title = $GLOBALS['Language']->getText('plugin_ldap', 'ugroup_list_add_set_binding');
738
                }
739
                
740
                $urlBind = $this->getPluginPath().'/ugroup_edit.php?ugroup_id='.$params['row']['ugroup_id'].'&func=bind_with_group';
741
                $linkBind = '<a href="'.$urlBind.'">- '.$title.'</a>';
742
                
743
                $params['html'] .= '<br />'.$linkAdd.$linkBind;
744
            }
745
        }
746
    }
747
748
    /**
749
     * Display form elements to bind project members and an LDAP group
750
     *
751
     * @param array $params
752
     * 
753
     * @return void
754
     */
755
    function project_admin_add_user_form(array $params) {
756
        if ($this->isLDAPGroupsUsageEnabled()) {
757
            $projectMembersManager = new LDAP_ProjectGroupManager($this->getLdap());
758
            $ldapGroup = $projectMembersManager->getLdapGroupByGroupId($params['groupId']);
759
            if ($ldapGroup) {
760
                $groupName = $ldapGroup->getCommonName();
761
            } else {
762
                $groupName = '';
763
            }
764
765
            $html = '<hr />'.PHP_EOL;
766
767
            $html .= '<form method="post" class="link-with-ldap" action="'.$this->getPluginPath().'/admin.php?group_id='.$params['groupId'].'">'.PHP_EOL;
768
            $html .= '<div class="control-group">
769
                        <label class="control-label" for="add_user">'.$GLOBALS['Language']->getText('plugin_ldap', 'project_admin_add_ugroup').'</label>
770
                        <div class="controls">
771
                            <input type="text" value="'.$groupName.'" name="ldap_group" id="project_admin_add_ldap_group" size="60" />
772
                        </div>
773
                    </div>';
774
            $html .= '<label class="checkbox" for="preserve_members"><input type="checkbox" id="preserve_members" name="preserve_members" checked="checked" />'.$GLOBALS['Language']->getText('plugin_ldap', 'ugroup_edit_group_preserve_members_option').' ('.$GLOBALS['Language']->getText('plugin_ldap', 'ugroup_edit_group_preserve_members_info').')</label>'.PHP_EOL;
775
            $html .= '<br />'.PHP_EOL;
776
            $html .= '<input type="submit" name="delete" value="'.$GLOBALS['Language']->getText('global', 'btn_delete').'" />'.PHP_EOL;
777
            $html .= '<input type="submit" name="check" value="'.$GLOBALS['Language']->getText('global', 'btn_update').'" />'.PHP_EOL;
778
            $html .= '</form>'.PHP_EOL;
779
780
            $GLOBALS['Response']->includeFooterJavascriptFile($this->getPluginPath().'/scripts/autocomplete.js');
781
            $js = "new LdapGroupAutoCompleter('project_admin_add_ldap_group',
782
                            '".$this->getPluginPath()."',
783
                            '".util_get_dir_image_theme()."',
784
                            'project_admin_add_ldap_group',
785
                            false);";
786
            $GLOBALS['Response']->includeFooterJavascriptSnippet($js);
787
788
            echo $html;
789
        }
790
    }
791
792
    /**
793
     * Check if adding or deleting users from the ugroup is allowed
794
     *
795
     * @param Array $params
796
     *
797
     * @return Void
798
     */
799
    function ugroup_update_users_allowed(array $params) {
800
        if ($params['ugroup_id']) {
801
            $ldapUserGroupManager = new LDAP_UserGroupManager($this->getLdap());
802
            if (!$ldapUserGroupManager->isMembersUpdateAllowed($params['ugroup_id'])) {
803
                $params['allowed'] = false;
804
            }
805
        }
806
    }
807
808
    /**
809
     * Project creation hook
810
     * 
811
     * If set, activate LDAP based authentication for this new project
812
     *
813
     * @param Array $params
814
     */
815
    function register_project_creation(array $params)
816
    {
817
        if($GLOBALS['sys_auth_type'] == 'ldap' && $this->getLdap()->getLDAPParam('svn_auth') == 1) {
818
            $svnProjectManager = new LDAP_ProjectManager();
819
            $svnProjectManager->setLDAPAuthForSVN($params['group_id']);
820
        }
821
    }
822
823
    /**
824
     * Hook
825
     * 
826
     * @param Array $params
827
     * 
828
     * @return void
829
     */
830
    function backend_factory_get_svn(array $params) {
831
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
832
            $params['base']  = 'LDAP_BackendSVN';
833
            $params['setup'] = array($this->getLdap());
834
        }
835
    }
836
    
837
    public function svn_apache_auth($params) {
838
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
839
            $ldapProjectManager = new LDAP_ProjectManager();
840
            if ($ldapProjectManager->hasSVNLDAPAuth($params['project_info']['group_id'])) {
841
                if ($params['svn_conf_auth'] === SVN_Apache_SvnrootConf::CONFIG_SVN_AUTH_PERL ||
842
                    $params['project_authorizes_tokens']
843
                ) {
844
                    $params['svn_apache_auth'] = new LDAP_SVN_Apache_ModPerl($this->getLdap(), $params['project_info']);
845
                } else {
846
                    $params['svn_apache_auth'] = new LDAP_SVN_Apache($this->getLdap(), $params['project_info']);
847
                }
848
            }
849
        }
850
    }
851
852
    /**
853
     * Hook
854
     *
855
     * @param Array $params
856
     *
857
     * @return void
858
     */
859
    function codendi_daily_start($params) {
860
        if ($GLOBALS['sys_auth_type'] == 'ldap' && $this->isDailySyncEnabled()) {
861
            $ldapQuery = new LDAP_DirectorySynchronization($this->getLdap(), $this->getLogger());
862
            $ldapQuery->syncAll();
863
864
            $retentionPeriod = $this->getLdap()->getLDAPParam('daily_sync_retention_period');
865
            if($retentionPeriod != NULL && $retentionPeriod!= "") {
866
                $ldapCleanUpManager = new LDAP_CleanUpManager($retentionPeriod);
867
                $ldapCleanUpManager->cleanAll();
868
            }
869
870
            //Synchronize the ugroups with the ldap ones
871
            $ldapUserGroupManager = new LDAP_UserGroupManager($this->getLdap());
872
            $ldapUserGroupManager->synchronizeUgroups();
873
            return true;
874
        }
875
    }
876
877
    /**
878
     * The daily synchro is enabled if the variable is not defined or if the variable is defined to 1
879
     * 
880
     * This is for backward compatibility (when daily_sync was not yet defined).
881
     * 
882
     * @return Boolean
883
     */
884
    protected function isDailySyncEnabled() {
885
        return $this->isParamEnabled('daily_sync');
886
    }
887
    
888
    protected function isLDAPUserManagementEnabled() {
889
        return $this->isParamEnabled('user_management');
890
    }
891
    
892
    protected function isLDAPGroupsUsageEnabled() {
893
        return $this->isParamEnabled('grp_enabled');
894
    }
895
    
896
    /**
897
     * Return true if the parameter is defined and enabled or not defined at all.
898
     * 
899
     * @param String $key
900
     * 
901
     * @return Boolean 
902
     */
903
    protected function isParamEnabled($key) {
904
        $value = $this->getLDAP()->getLDAPParam($key);
905
        if ($value === null || $value == 1) {
906
            return true;
907
        }
908
        return false;
909
    }
910
    
911
    public function system_event_get_types_for_default_queue($params) {
912
        $params['types'][] = 'PLUGIN_LDAP_UPDATE_LOGIN';
913
    }
914
    
915
    public function get_system_event_class($params) {
916
        switch($params['type']) {
917
            case 'PLUGIN_LDAP_UPDATE_LOGIN' :
918
                include_once dirname(__FILE__).'/system_event/SystemEvent_PLUGIN_LDAP_UPDATE_LOGIN.class.php';
919
                $params['class'] = 'SystemEvent_PLUGIN_LDAP_UPDATE_LOGIN';
920
                $params['dependencies'] = array(
921
                    UserManager::instance(),
922
                    Backend::instance(Backend::SVN),
923
                    ProjectManager::instance(),
924
                    new LDAP_ProjectManager()
925
                );
926
                break;
927
        }
928
    }
929
930
    public function get_ldap_login_name_for_user($params) {
931
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
932
            $params['ldap_user'] = $this->getLdapUserManager()->getLDAPUserFromUser($params['user']);
933
        }
934
    }
935
936
    public function login_presenter($params) {
937
        if ($GLOBALS['sys_auth_type'] == 'ldap') {
938
            include_once dirname(__FILE__).'/LoginPresenter.class.php';
939
            $params['authoritative'] = true;
940
            $params['presenter']     = new LDAP_LoginPresenter($params['presenter']);
941
        }
942
    }
943
944
    /**
945
     * @see Event::USER_MANAGER_UPDATE_DB
946
     */
947
    public function user_manager_update_db(array $params) {
948
        try {
949
            $this->getLDAPUserWrite()->updateWithPreviousUser($params['old_user'], $params['new_user']);
950
        } catch (LDAP_Exception_NoWriteException $exception) {
951
            $this->getLogger()->debug('User info not updated in LDAP, no write LDAP configured');
952
        } catch (Exception $exception) {
953
            $this->getLogger()->error('An error occured while updating user settings (user_manager_update_db): '.$exception->getMessage());
954
        }
955
    }
956
957
    /**
958
     *
959
     * @see Event::USER_MANAGER_CREATE_ACCOUNT
960
     */
961
    public function user_manager_create_account(array $params) {
962
        try {
963
            $this->getLDAPUserWrite()->updateWithUser($params['user']);
964
        } catch (LDAP_Exception_NoWriteException $exception) {
965
            $this->getLogger()->debug('User info not updated in LDAP, no write LDAP configured');
966
        } catch (Exception $exception) {
967
            $this->getLogger()->error('An error occured while activating user as site admin (project_admin_activate_user): '.$exception->getMessage());
968
        }
969
    }
970
971
    private function getLDAPUserWrite() {
972
        return new LDAP_UserWrite(
973
            $this->getLDAPWrite(),
974
            UserManager::instance(),
975
            new UserDao(),
976
            new LDAP_UserDao(),
977
            $this->getLogger()
978
        );
979
    }
980
981
    /**
982
     * @see GIT_EVENT_PLATFORM_CAN_USE_GERRIT
983
     */
984
    public function git_event_platform_can_use_gerrit($params) {
985
        $ldap_params = $this->getLDAPParams();
986
987
        $platform_uses_ldap_for_authentication = ForgeConfig::get('sys_auth_type') === ForgeConfig::AUTH_TYPE_LDAP;
988
        $ldap_write_server_is_configured       = isset($ldap_params['write_server']) && trim($ldap_params['write_server']) != '';
989
990
        if ($platform_uses_ldap_for_authentication || $ldap_write_server_is_configured) {
991
            $params['platform_can_use_gerrit'] = true;
992
        }
993
    }
994
995
    public function getAdministrationOptions() {
996
        $this->updateAdministrationOptions();
997
998
        if (! file_exists($this->getConfigFilePath())) {
999
            $presenter = new LDAP_AdministrationPresenter($this->getId());
1000
            $renderer  = TemplateRendererFactory::build()->getRenderer(LDAP_TEMPLATE_DIR);
1001
            return $renderer->renderToString('ldap-administration', $presenter);
1002
        }
1003
    }
1004
1005
    private function updateAdministrationOptions() {
1006
        $request   = HTTPRequest::instance();
1007
        $ldap_type = $request->getValidated('ldap_type', 'string', false);
1008
1009
        if (! $ldap_type) {
1010
            return;
1011
        }
1012
1013
        if ($ldap_type === LDAP::SERVER_TYPE_ACTIVE_DIRECTORY) {
1014
            $config_file = $this->getEtcDir().LDAP::SERVER_TYPE_ACTIVE_DIRECTORY.'.inc';
1015
        } else {
1016
            $config_file = $this->getEtcDir().LDAP::SERVER_TYPE_OPEN_LDAP.'.inc';
1017
        }
1018
1019
        if (! file_exists($this->getConfigFilePath())) {
1020
            copy($config_file, $this->getConfigFilePath());
1021
            $GLOBALS['Response']->redirect('/plugins/pluginsadministration//?view=properties&plugin_id='.$this->getId());
1022
        }
1023
    }
1024
1025
    private function getEtcDir() {
1026
        return $GLOBALS['sys_custompluginsroot'] .'ldap/etc/';
1027
    }
1028
1029
    private function getConfigFilePath() {
1030
        return $this->getEtcDir().'ldap.inc';
1031
    }
1032
}
1033