Issues (4868)

login.php (4 issues)

1
<?php
2
/**
3
 * EGroupware - Login
4
 *
5
 * @link http://www.egroupware.org
6
 * @author Dan Kuykendall <[email protected]>
7
 * @author Joseph Engo <[email protected]>
8
 * @license http://opensource.org/licenses/lgpl-license.php LGPL - GNU Lesser General Public License
9
 * @package api
10
 * @subpackage authentication
11
 * @version $Id$
12
 */
13
14
use EGroupware\Api;
15
use EGroupware\Api\Framework;
16
use EGroupware\Api\Egw;
17
18
$submit = False;			// set to some initial value
19
20
$GLOBALS['egw_info'] = array('flags' => array(
21
	'disable_Template_class'  => True,
22
	'login'                   => True,
23
	'currentapp'              => 'login',
24
));
25
26
if(file_exists('./header.inc.php'))
27
{
28
	include('./header.inc.php');
29
	if(!function_exists('CreateObject'))
30
	{
31
		Header('Location: setup/index.php');
32
		exit;
33
	}
34
}
35
else
36
{
37
	Header('Location: setup/index.php');
38
	exit;
39
}
40
41
/*
42
 * Destroy any existing anonymous session.
43
 * Copied from logout.php. Maybe make it a common function?
44
 */
45
if(isset($GLOBALS['sitemgr_info']) && $GLOBALS['egw_info']['user']['userid'] == $GLOBALS['sitemgr_info']['anonymous_user'])
46
{
47
	if($GLOBALS['egw']->session->verify())
48
	{
49
		Api\Hooks::process('logout');
50
		$GLOBALS['egw']->session->destroy($GLOBALS['sessionid'],$GLOBALS['kp3']);
51
	}
52
}
53
54
// CAS :
55
if($GLOBALS['egw_info']['server']['auth_type'] == 'cas')
56
{
57
	ob_end_clean();
58
59
	require_once('CAS/CAS.php');
60
61
	//phpCAS::setDebug('/var/log/log_phpcas.php');
62
63
	if($GLOBALS['egw_info']['server']['cas_authentication_mode'] == 'Proxy')
64
	{
65
		phpCAS::proxy(CAS_VERSION_2_0,
0 ignored issues
show
The type phpCAS was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
The constant CAS_VERSION_2_0 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
66
			$GLOBALS['egw_info']['server']['cas_server_host_name'],
67
			(int) $GLOBALS['egw_info']['server']['cas_server_port'],
68
			$GLOBALS['egw_info']['server']['cas_server_uri'] );
69
	}
70
	else
71
	{
72
		phpCAS::client(CAS_VERSION_2_0,
73
			$GLOBALS['egw_info']['server']['cas_server_host_name'],
74
			(int) $GLOBALS['egw_info']['server']['cas_server_port'],
75
			$GLOBALS['egw_info']['server']['cas_server_uri'] );
76
	}
77
78
	if($GLOBALS['egw_info']['server']['cas_ssl_validation'] == 'PEMCertificate')
79
	{
80
		// Set the certificate of the CAS server (PEM Certificate)
81
		phpCAS::setCasServerCert($GLOBALS['egw_info']['server']['cas_cert']);
82
	}
83
	elseif($GLOBALS['egw_info']['server']['cas_ssl_validation'] == 'CACertificate')
84
	{
85
		// Set the CA certificate of the CAS server
86
		phpCAS::setCasServerCACert($GLOBALS['egw_info']['server']['cas_cert']);
87
	}
88
	elseif($GLOBALS['egw_info']['server']['cas_ssl_validation'] == 'No')
89
	{
90
		// no SSL validation for the CAS server
91
		phpCAS::setNoCasServerValidation();
92
	}
93
94
	phpCAS::forceAuthentication();
95
96
	ob_start();
97
98
	$login = phpCAS::getUser();
99
	$password = phpCAS::retrievePT("imap://".$GLOBALS['egw_info']['server']['mail_server'],$err_code,$output);
100
	$GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($login,$password,'text');
101
102
	/* set auth_cookie */
103
	$GLOBALS['egw']->redirect_link($forward,$extra_vars);
104
}
105
else
106
{
107
	// allow template to overide login-template (without modifying header.inc.php) by setting default or forced pref
108
	$prefs = new Api\Preferences();
109
	$prefs->account_id = Api\Preferences::DEFAULT_ID;
110
	$prefs->read_repository();
111
112
	$class = $prefs->data['common']['template_set'].'_framework';
113
	if (class_exists($class) && @constant($class.'::LOGIN_TEMPLATE_SET'))
114
	{
115
		$GLOBALS['egw_info']['server']['template_set'] =
116
			$GLOBALS['egw_info']['login_template_set'] = $prefs->data['common']['template_set'];
117
	}
118
	if ($GLOBALS['egw_info']['login_template_set'] == 'idots')
119
	{
120
		$GLOBALS['egw_info']['server']['template_set'] =
121
			$GLOBALS['egw_info']['login_template_set'] = 'default';
122
	}
123
	unset($prefs); unset($class);
124
125
	$GLOBALS['egw']->framework = Framework::factory();
126
127
	// This is used for system downtime, to prevent new logins.
128
	if($GLOBALS['egw_info']['server']['deny_all_logins'])
129
	{
130
	   echo $GLOBALS['egw']->framework->denylogin_screen();
0 ignored issues
show
Are you sure the usage of $GLOBALS['egw']->framework->denylogin_screen() targeting EGroupware\Api\Framework::denylogin_screen() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
131
	   exit;
132
	}
133
134
	/* Program starts here */
135
136
	// some apache mod_auth_* modules use REMOTE_USER instead of PHP_AUTH_USER, thanks to Sylvain Beucler
137
	if ($GLOBALS['egw_info']['server']['auth_type'] == 'http' && !isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['REMOTE_USER']))
138
	{
139
		$_SERVER['PHP_AUTH_USER'] = $_SERVER['REMOTE_USER'];
140
	}
141
	$passwd = get_magic_quotes_gpc() ? stripslashes($_POST['passwd']) : $_POST['passwd'];
142
	$passwd_type = $_POST['passwd_type'];
143
144
	// forced password change
145
	if($GLOBALS['egw']->session->cd_reason == Api\Session::CD_FORCE_PASSWORD_CHANGE)
146
	{
147
		// no automatic login
148
	}
149
	// authentication via Apache
150
	elseif ($GLOBALS['egw_info']['server']['auth_type'] == 'http' && isset($_SERVER['PHP_AUTH_USER']))
151
	{
152
		$submit = True;
153
		$login  = $_SERVER['PHP_AUTH_USER'];
154
		$passwd = $_SERVER['PHP_AUTH_PW'];
155
		$passwd_type = 'text';
156
	}
157
	# Apache + mod_ssl style SSL certificate authentication
158
	# Certificate (chain) verification occurs inside mod_ssl
159
	elseif($GLOBALS['egw_info']['server']['auth_type'] == 'sqlssl' && isset($_SERVER['SSL_CLIENT_S_DN']) && !isset($_GET['cd']))
160
	{
161
	   // an X.509 subject looks like:
162
	   // CN=john.doe/OU=Department/O=Company/C=xx/[email protected]/L=City/
163
	   // the username is deliberately lowercase, to ease LDAP integration
164
	   $sslattribs = explode('/',$_SERVER['SSL_CLIENT_S_DN']);
165
	   # skip the part in front of the first '/' (nothing)
166
	   while(($sslattrib = next($sslattribs)))
167
	   {
168
		  list($key,$val) = explode('=',$sslattrib);
169
		  $sslattributes[$key] = $val;
170
	   }
171
172
	   if(isset($sslattributes['Email']))
173
	   {
174
		  $submit = True;
175
176
		  # login will be set here if the user logged out and uses a different username with
177
		  # the same SSL-certificate.
178
		  if(!isset($_POST['login'])&&isset($sslattributes['Email']))
179
		  {
180
			 $login = $sslattributes['Email'];
181
			 # not checked against the database, but delivered to authentication module
182
			 $passwd = $_SERVER['SSL_CLIENT_S_DN'];
183
		  }
184
	   }
185
	   unset($key);
186
	   unset($val);
187
	   unset($sslattributes);
188
	}
189
	else
190
	{
191
		// check if we have a sufficient access-token as cookie and no forced password change
192
		if ($GLOBALS['egw']->session->cd_reason != Api\Session::CD_FORCE_PASSWORD_CHANGE &&
193
			$GLOBALS['egw']->session->skipPasswordAuth($_COOKIE[Api\Session::REMEMBER_ME_COOKIE], $account_id))
194
		{
195
			$_SERVER['PHP_AUTH_USER'] = $login = Api\Accounts::id2name($account_id);
196
			$submit = true;
197
		}
198
199
		if(!$passwd && ($GLOBALS['egw_info']['server']['auto_anon_login']) && !$_GET['cd'])
200
		{
201
			$_SERVER['PHP_AUTH_USER'] = $login = 'anonymous';
202
			$_SERVER['PHP_AUTH_PW'] =  $passwd = 'anonymous';
203
			$passwd_type = 'text';
204
			$submit = True;
205
		}
206
	}
207
208
209
	if (isset($passwd_type) || $submit)
210
	{
211
		if($_SERVER['REQUEST_METHOD'] != 'POST' &&
212
			!isset($_SERVER['PHP_AUTH_USER']) && !isset($_SERVER['SSL_CLIENT_S_DN']))
213
		{
214
			Egw::redirect_link('/login.php','cd=5');
215
		}
216
217
		// don't get login data again when $submit is true
218
		if($submit == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
219
		{
220
			$login = $_POST['login'];
221
		}
222
223
		//conference - for strings like [email protected]@default , allows
224
		//that user have a login that is his e-mail. (viniciuscb)
225
		// remove blanks
226
		$login_parts = array_map('trim',explode('@',$login));
227
		$login = implode('@',$login_parts);
228
229
		$got_login = false;
230
		if (count($login_parts) > 1)
231
		{
232
			//Last part of login string, when separated by @, is a domain name
233
			if (array_key_exists(array_pop($login_parts),$GLOBALS['egw_domain']))
234
			{
235
				$got_login = true;
236
			}
237
		}
238
239
		if (!$got_login)
240
		{
241
			if(isset($_POST['logindomain']))
242
			{
243
				$login .= '@' . $_POST['logindomain'];
244
			}
245
			elseif(!isset($GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]))
246
			{
247
				$login .= '@'.$GLOBALS['egw_info']['server']['default_domain'];
248
			}
249
		}
250
		$GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($login, $passwd,
251
			$passwd_type, false, true, true, $_POST['2fa_code'], $_POST['remember_me']);	// true = let session fail on forced password change
252
253
		if (!$GLOBALS['sessionid'] && $GLOBALS['egw']->session->cd_reason == Api\Session::CD_FORCE_PASSWORD_CHANGE)
254
		{
255
			if (isset($_POST['new_passwd']))
256
			{
257
				if (($errors = preferences_password::do_change($passwd, $_POST['new_passwd'], $_POST['new_passwd2'])))
258
				{
259
					$force_password_change = implode("\n", $errors);
260
				}
261
				else
262
				{
263
					$GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($login,$_POST['new_passwd'],$passwd_type);
264
				}
265
			}
266
			else
267
			{
268
				$force_password_change = $GLOBALS['egw']->session->reason;
269
			}
270
		}
271
		if (isset($force_password_change))
272
		{
273
			// will show new login-screen incl. new password field below
274
		}
275
		elseif (!isset($GLOBALS['sessionid']) || ! $GLOBALS['sessionid'])
276
		{
277
			Egw::redirect_link('/login.php?cd=' . $GLOBALS['egw']->session->cd_reason);
278
		}
279
		else
280
		{
281
			if ($_POST['lang'] && preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$_POST['lang']) &&
282
				$_POST['lang'] != $GLOBALS['egw_info']['user']['preferences']['common']['lang'])
283
			{
284
				$GLOBALS['egw']->preferences->add('common','lang',$_POST['lang'],'session');
285
			}
286
287
			// check if new translations are available
288
			Api\Translation::check_invalidate_cache();
289
290
			$forward = isset($_GET['phpgw_forward']) ? urldecode($_GET['phpgw_forward']) : @$_POST['phpgw_forward'];
291
			if (!$forward)
292
			{
293
				$extra_vars['cd'] = 'yes';
294
				$forward = '/index.php';
295
			}
296
			else
297
			{
298
				list($forward,$extra_vars) = explode('?',$forward,2);
299
				// only append cd=yes, if there is not already a cd value!
300
				if (strpos($extra_vars, 'cd=') === false)
301
				{
302
					$extra_vars .= ($extra_vars ? '&' : '').'cd=yes';
303
				}
304
			}
305
306
			if(strpos($_SERVER['HTTP_REFERER'], $_SERVER['REQUEST_URI']) === false) {
307
				// login requuest does not come from login.php
308
				// redirect to referer on logout
309
				Api\Cache::setSession('login', 'referer', $_SERVER['HTTP_REFERER']);
310
			}
311
			$strength = ($GLOBALS['egw_info']['server']['force_pwd_strength']?$GLOBALS['egw_info']['server']['force_pwd_strength']:false);
312
			if ($strength && $strength>5) $strength =5;
313
			if ($strength && $strength<0) $strength = false;
314
			// Check for save passwd
315
			if($strength && $GLOBALS['egw_info']['server']['check_save_passwd'] && !$GLOBALS['egw']->acl->check('nopasswordchange', 1, 'preferences') &&
316
				($unsave_msg = $GLOBALS['egw']->auth->crackcheck($passwd, $strength)))
317
			{
318
				error_log('login::'.__LINE__.' User '. $login. ' authenticated with an unsave password'.' '.$unsave_msg);
319
				$message = lang('eGroupWare checked your password for safetyness. You have to change your password for the following reason:')."\n";
320
				Egw::redirect_link('/index.php', array(
321
					'menuaction' => 'preferences.uipassword.change',
322
					'message' => $message . $unsave_msg,
323
					'cd' => 'yes',
324
				));
325
			}
326
			else
327
			{
328
				// commiting the session, before redirecting might fix racecondition in session creation
329
				$GLOBALS['egw']->session->commit_session();
330
				Egw::redirect_link($forward,$extra_vars);
331
			}
332
		}
333
	}
334
	// show login screen
335
	if(isset($_COOKIE['last_loginid']))
336
	{
337
		$prefs = new Api\Preferences($GLOBALS['egw']->accounts->name2id($_COOKIE['last_loginid']));
338
339
		if($prefs->account_id)
340
		{
341
			$GLOBALS['egw_info']['user']['preferences'] = $prefs->read_repository();
342
		}
343
	}
344
	if ($_GET['lang'] && preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$_GET['lang']))
345
	{
346
		$GLOBALS['egw_info']['user']['preferences']['common']['lang'] = $_GET['lang'];
347
	}
348
	elseif(!isset($_COOKIE['last_loginid']) || !$prefs->account_id)
349
	{
350
		// If the lastloginid cookies isn't set, we will default to the first language,
351
		// the users browser accepts.
352
		list($lang) = explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
353
		if(strlen($lang) > 2)
354
		{
355
			$lang = substr($lang,0,2);
356
		}
357
		$GLOBALS['egw_info']['user']['preferences']['common']['lang'] = $lang;
358
	}
359
	if ($_COOKIE['eGW_cookie_test'] !== 'enabled')
360
	{
361
		Api\Session::egw_setcookie('eGW_cookie_test','enabled',0);
362
	}
363
	#print 'LANG:' . $GLOBALS['egw_info']['user']['preferences']['common']['lang'] . '<br>';
364
	Api\Translation::init();	// this will set the language according to the (new) set prefs
365
	Api\Translation::add_app('login');
366
	Api\Translation::add_app('loginscreen');
367
	$GLOBALS['loginscreenmessage'] = Api\Translation::translate('loginscreen_message',false,'');
368
	if($GLOBALS['loginscreenmessage'] == 'loginscreen_message' || empty($GLOBALS['loginscreenmessage']))
369
	{
370
		Api\Translation::add_app('loginscreen','en');	// trying the en one
371
		$GLOBALS['loginscreenmessage'] = Api\Translation::translate('loginscreen_message',false,'');
372
	}
373
	if($GLOBALS['loginscreenmessage'] == 'loginscreen_message' || empty($GLOBALS['loginscreenmessage']))
374
	{
375
	   // remove the global var since the lang loginscreen message and its fallback (en) is empty or not set
376
	   unset($GLOBALS['loginscreenmessage']);
377
	}
378
379
	foreach($_GET as $name => $value)
380
	{
381
		if(strpos($name,'phpgw_') !== false)
382
		{
383
			$extra_vars .= '&' . $name . '=' . urlencode($value);
384
		}
385
	}
386
387
	if($extra_vars)
388
	{
389
		$extra_vars = '?' . substr($extra_vars,1);
390
	}
391
392
	$GLOBALS['egw']->framework->login_screen($extra_vars, $force_password_change);
393
}
394