]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/security/LoginManager.php
Apply PHP Code Beautifier on source code for linter automatic fixes
[github/shaarli/Shaarli.git] / application / security / LoginManager.php
CommitLineData
44acf706 1<?php
53054b2b 2
fab87c26 3namespace Shaarli\Security;
44acf706 4
cc2ded54 5use Exception;
b38a1b02 6use Psr\Log\LoggerInterface;
c7721487
V
7use Shaarli\Config\ConfigManager;
8
44acf706
V
9/**
10 * User login management
11 */
12class LoginManager
13{
1b28c66c 14 /** @var array A reference to the $_GLOBALS array */
44acf706 15 protected $globals = [];
1b28c66c
V
16
17 /** @var ConfigManager Configuration Manager instance **/
44acf706 18 protected $configManager = null;
1b28c66c
V
19
20 /** @var SessionManager Session Manager instance **/
63ea23c2 21 protected $sessionManager = null;
1b28c66c 22
b49a04f7
A
23 /** @var BanManager Ban Manager instance **/
24 protected $banManager;
1b28c66c
V
25
26 /** @var bool Whether the user is logged in **/
63ea23c2 27 protected $isLoggedIn = false;
1b28c66c
V
28
29 /** @var bool Whether the Shaarli instance is open to public edition **/
63ea23c2 30 protected $openShaarli = false;
44acf706 31
c689e108
V
32 /** @var string User sign-in token depending on remote IP and credentials */
33 protected $staySignedInToken = '';
c4ad3d4f
A
34 /** @var CookieManager */
35 protected $cookieManager;
b38a1b02
A
36 /** @var LoggerInterface */
37 protected $logger;
c689e108 38
44acf706
V
39 /**
40 * Constructor
41 *
b38a1b02 42 * @param ConfigManager $configManager Configuration Manager instance
63ea23c2 43 * @param SessionManager $sessionManager SessionManager instance
b38a1b02
A
44 * @param CookieManager $cookieManager CookieManager instance
45 * @param BanManager $banManager
46 * @param LoggerInterface $logger Used to log login attempts
44acf706 47 */
b38a1b02
A
48 public function __construct(
49 ConfigManager $configManager,
50 SessionManager $sessionManager,
51 CookieManager $cookieManager,
52 BanManager $banManager,
53 LoggerInterface $logger
54 ) {
44acf706 55 $this->configManager = $configManager;
63ea23c2 56 $this->sessionManager = $sessionManager;
c4ad3d4f 57 $this->cookieManager = $cookieManager;
b38a1b02
A
58 $this->banManager = $banManager;
59 $this->logger = $logger;
b49a04f7 60
704637bf 61 if ($this->configManager->get('security.open_shaarli') === true) {
63ea23c2
V
62 $this->openShaarli = true;
63 }
64 }
65
c689e108
V
66 /**
67 * Generate a token depending on deployment salt, user password and client IP
68 *
69 * @param string $clientIpAddress The remote client IP address
70 */
71 public function generateStaySignedInToken($clientIpAddress)
72 {
d9ba1cdd
A
73 if ($this->configManager->get('security.session_protection_disabled') === true) {
74 $clientIpAddress = '';
75 }
c689e108
V
76 $this->staySignedInToken = sha1(
77 $this->configManager->get('credentials.hash')
78 . $clientIpAddress
79 . $this->configManager->get('credentials.salt')
80 );
81 }
82
83 /**
84 * Return the user's client stay-signed-in token
85 *
86 * @return string User's client stay-signed-in token
87 */
88 public function getStaySignedInToken()
89 {
90 return $this->staySignedInToken;
91 }
92
63ea23c2
V
93 /**
94 * Check user session state and validity (expiration)
95 *
84742084 96 * @param string $clientIpId Client IP address identifier
63ea23c2 97 */
c4ad3d4f 98 public function checkLoginState($clientIpId)
63ea23c2
V
99 {
100 if (! $this->configManager->exists('credentials.login')) {
101 // Shaarli is not configured yet
102 $this->isLoggedIn = false;
103 return;
104 }
105
c4ad3d4f 106 if ($this->staySignedInToken === $this->cookieManager->getCookieParameter(CookieManager::STAY_SIGNED_IN)) {
704637bf
V
107 // The user client has a valid stay-signed-in cookie
108 // Session information is updated with the current client information
c7721487 109 $this->sessionManager->storeLoginInfo($clientIpId);
53054b2b
A
110 } elseif (
111 $this->sessionManager->hasSessionExpired()
c7721487 112 || $this->sessionManager->hasClientIpChanged($clientIpId)
63ea23c2 113 ) {
51f0128c 114 $this->sessionManager->logout();
63ea23c2
V
115 $this->isLoggedIn = false;
116 return;
117 }
118
8edd7f15 119 $this->isLoggedIn = true;
c7721487 120 $this->sessionManager->extendSession();
63ea23c2
V
121 }
122
123 /**
124 * Return whether the user is currently logged in
125 *
126 * @return true when the user is logged in, false otherwise
127 */
efb7d21b 128 public function isLoggedIn(): bool
63ea23c2
V
129 {
130 if ($this->openShaarli) {
131 return true;
132 }
133 return $this->isLoggedIn;
134 }
135
136 /**
137 * Check user credentials are valid
138 *
84742084
V
139 * @param string $clientIpId Client IP address identifier
140 * @param string $login Username
141 * @param string $password Password
63ea23c2
V
142 *
143 * @return bool true if the provided credentials are valid, false otherwise
144 */
b38a1b02 145 public function checkCredentials($clientIpId, $login, $password)
63ea23c2 146 {
cc2ded54
SN
147 // Check credentials
148 try {
21e5df5e 149 $useLdapLogin = !empty($this->configManager->get('ldap.host'));
53054b2b
A
150 if (
151 $login === $this->configManager->get('credentials.login')
b38a1b02
A
152 && (
153 (false === $useLdapLogin && $this->checkCredentialsFromLocalConfig($login, $password))
154 || (true === $useLdapLogin && $this->checkCredentialsFromLdap($login, $password))
155 )
21e5df5e 156 ) {
b38a1b02
A
157 $this->sessionManager->storeLoginInfo($clientIpId);
158 $this->logger->info(format_log('Login successful', $clientIpId));
159
160 return true;
cc2ded54 161 }
53054b2b 162 } catch (Exception $exception) {
b38a1b02 163 $this->logger->info(format_log('Exception while checking credentials: ' . $exception, $clientIpId));
63ea23c2
V
164 }
165
b38a1b02
A
166 $this->logger->info(format_log('Login failed for user ' . $login, $clientIpId));
167
cc2ded54
SN
168 return false;
169 }
170
171
172 /**
173 * Check user credentials from local config
174 *
175 * @param string $login Username
176 * @param string $password Password
177 *
178 * @return bool true if the provided credentials are valid, false otherwise
179 */
53054b2b
A
180 public function checkCredentialsFromLocalConfig($login, $password)
181 {
cc2ded54
SN
182 $hash = sha1($password . $login . $this->configManager->get('credentials.salt'));
183
184 return $login == $this->configManager->get('credentials.login')
185 && $hash == $this->configManager->get('credentials.hash');
186 }
187
188 /**
189 * Check user credentials are valid through LDAP bind
190 *
191 * @param string $remoteIp Remote client IP address
192 * @param string $clientIpId Client IP address identifier
193 * @param string $login Username
194 * @param string $password Password
195 *
196 * @return bool true if the provided credentials are valid, false otherwise
197 */
198 public function checkCredentialsFromLdap($login, $password, $connect = null, $bind = null)
199 {
53054b2b 200 $connect = $connect ?? function ($host) {
8694e841
A
201 $resource = ldap_connect($host);
202
203 ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3);
204
205 return $resource;
206 };
53054b2b 207 $bind = $bind ?? function ($handle, $dn, $password) {
8694e841
A
208 return ldap_bind($handle, $dn, $password);
209 };
a69cfe0d
SN
210
211 return $bind(
212 $connect($this->configManager->get('ldap.host')),
8694e841 213 sprintf($this->configManager->get('ldap.dn'), $login),
a69cfe0d
SN
214 $password
215 );
44acf706
V
216 }
217
44acf706
V
218 /**
219 * Handle a failed login and ban the IP after too many failed attempts
220 *
221 * @param array $server The $_SERVER array
222 */
223 public function handleFailedLogin($server)
224 {
b49a04f7 225 $this->banManager->handleFailedAttempt($server);
44acf706
V
226 }
227
228 /**
229 * Handle a successful login
230 *
231 * @param array $server The $_SERVER array
232 */
233 public function handleSuccessfulLogin($server)
234 {
b49a04f7 235 $this->banManager->clearFailures($server);
44acf706
V
236 }
237
238 /**
239 * Check if the user can login from this IP
240 *
241 * @param array $server The $_SERVER array
242 *
243 * @return bool true if the user is allowed to login
244 */
245 public function canLogin($server)
246 {
b49a04f7 247 return ! $this->banManager->isBanned($server);
44acf706
V
248 }
249}