1 | <?php |
||||
2 | |||||
3 | // Copyright (C) 2014-2018 Universitätsbibliothek Mannheim |
||||
4 | // See file LICENSE for license details. |
||||
5 | |||||
6 | // This file implements user authorization. |
||||
7 | |||||
8 | // PalMA installation can authorize users by a PIN, by a |
||||
9 | // user name and by a password. |
||||
10 | |||||
11 | // The PIN is a four digit random number which is changed for |
||||
12 | // every new session. |
||||
13 | |||||
14 | // Authorization with a user name and a password requires code |
||||
15 | // which implements the authorization mechanism (for example |
||||
16 | // proxy based authorization, LDAP, Shibboleth, fixed password). |
||||
17 | // Password authorization can optionally be disabled. |
||||
18 | |||||
19 | // Connect to database and get configuration constants. |
||||
20 | require_once('DBConnector.class.php'); |
||||
21 | $dbcon = new palma\DBConnector(); |
||||
22 | |||||
23 | require_once('i12n.php'); |
||||
24 | require_once('globals.php'); |
||||
25 | |||||
26 | $errtext = false; |
||||
27 | |||||
28 | function getDevice() |
||||
29 | { |
||||
30 | // Try to determine the user's device type. The device which is |
||||
31 | // returned is used to select the matching icon for the user list. |
||||
32 | $agent = $_SERVER["HTTP_USER_AGENT"]; |
||||
33 | if (preg_match('/iPad/', $agent)) { |
||||
34 | $device = 'tablet'; |
||||
35 | } elseif (preg_match('/iPhone/', $agent)) { |
||||
36 | $device = 'mobile'; |
||||
37 | } elseif (preg_match('/Android/', $agent)) { |
||||
38 | $device = 'android'; |
||||
39 | } elseif (preg_match('/Linux/', $agent)) { |
||||
40 | $device = 'linux'; |
||||
41 | } elseif (preg_match('/OS X/', $agent)) { |
||||
42 | $device = 'apple'; |
||||
43 | } elseif (preg_match('/Windows/', $agent)) { |
||||
44 | $device = 'windows'; |
||||
45 | } else { |
||||
46 | $device = 'laptop'; |
||||
47 | } |
||||
48 | return $device; |
||||
49 | } |
||||
50 | |||||
51 | function checkCredentials($username, $password) |
||||
52 | { |
||||
53 | // Check username + password against fixed internal value and |
||||
54 | // external proxy with authentisation. |
||||
55 | |||||
56 | global $errtext; |
||||
57 | |||||
58 | $remote = $_SERVER['REMOTE_ADDR']; |
||||
59 | if ($username == 'chef' && $password == 'chef') { |
||||
60 | if ($remote == '::1' || $remote == '127.0.0.1' || |
||||
61 | preg_match('/^134[.]155[.]36[.]/', $remote) && |
||||
62 | $remote != '134.155.36.48') { |
||||
63 | // Allow test access for restricted remote hosts (localhost, |
||||
64 | // UB Mannheim library staff, but not via proxy server). |
||||
65 | // TODO: PalMA installations which are accessible from |
||||
66 | // the Internet may want to remove this test access. |
||||
67 | return true; |
||||
68 | } else { |
||||
69 | trace("Test access not allowed for IP address $remote"); |
||||
70 | return false; |
||||
71 | } |
||||
72 | } |
||||
73 | |||||
74 | if ($username == '' || $password == '') { |
||||
75 | // Don't allow empty user name or password. |
||||
76 | // Proxy authentisation can fail with empty values. |
||||
77 | trace("access denied for user '$username'"); |
||||
78 | return false; |
||||
79 | } |
||||
80 | // TODO: testurl sollte auf einem lokalen Server liegen. |
||||
81 | $testurl = 'http://www.weilnetz.de/proxytest'; |
||||
82 | $proxy = 'proxy.bib.uni-mannheim.de:3150'; |
||||
83 | $curl = curl_init($testurl); |
||||
84 | curl_setopt($curl, CURLOPT_HEADER, true); |
||||
85 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
||||
86 | curl_setopt($curl, CURLOPT_PROXY, $proxy); |
||||
87 | curl_setopt($curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); |
||||
88 | curl_setopt($curl, CURLOPT_PROXYUSERPWD, "$username:$password"); |
||||
89 | //~ trace("Start curl"); |
||||
90 | $out = curl_exec($curl); |
||||
91 | curl_close($curl); |
||||
92 | |||||
93 | if (!$out) { |
||||
94 | trace("curl failed for user '$username'"); |
||||
95 | $errtext = addslashes(__('Invalid credentials!')); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
96 | } elseif (preg_match('/404 Not Found/', $out)) { |
||||
0 ignored issues
–
show
It seems like
$out can also be of type true ; however, parameter $subject of preg_match() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
97 | return true; |
||||
98 | } elseif (preg_match('/Could not resolve proxy/', $out)) { |
||||
99 | trace('proxy authentisation was not possible'); |
||||
100 | $errtext = addslashes(__('Cannot check credentials, sorry!')); |
||||
101 | } elseif (preg_match('/Cache Access Denied/', $out)) { |
||||
102 | trace("access denied for user '$username'"); |
||||
103 | $errtext = addslashes(__('Invalid credentials!')); |
||||
104 | } else { |
||||
105 | trace("access not possible for user '$username'"); |
||||
106 | $errtext = addslashes(__('Invalid credentials!')); |
||||
107 | } |
||||
108 | return false; |
||||
109 | } |
||||
110 | |||||
111 | $username = ''; |
||||
112 | $pin = ''; |
||||
113 | $posted_pin = ''; |
||||
114 | if (isset($_REQUEST['pin'])) { |
||||
115 | $posted_pin = escapeshellcmd($_REQUEST['pin']); |
||||
116 | } |
||||
117 | |||||
118 | require_once('globals.php'); |
||||
119 | monitor("login.php: page loaded"); |
||||
120 | if ($_SERVER['REQUEST_METHOD'] == 'POST') { |
||||
121 | session_start(); |
||||
122 | $username = escapeshellcmd($_POST['username']); |
||||
123 | $password = ''; |
||||
124 | if (CONFIG_PASSWORD) { |
||||
125 | // The password must not be escaped. |
||||
126 | $password = $_POST['userpassword']; |
||||
127 | } |
||||
128 | if (CONFIG_PIN) { |
||||
129 | $posted_pin = escapeshellcmd($_POST['pin']); |
||||
130 | $pin = $dbcon->querySingle("SELECT value FROM setting WHERE key = 'pin'"); |
||||
131 | } |
||||
132 | |||||
133 | if (CONFIG_PASSWORD && !checkCredentials($username, $password)) { |
||||
134 | monitor("login.php: access denied for user '$username'"); |
||||
135 | // Invalid username or password. |
||||
136 | } elseif (CONFIG_PIN && ($pin != $posted_pin)) { |
||||
137 | monitor("login.php: access denied for user '$username': invalid pin"); |
||||
138 | trace("access denied for user '$username', wrong pin $posted_pin"); |
||||
139 | $errtext = addslashes(__('Invalid PIN.')); |
||||
0 ignored issues
–
show
The function
__ was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
140 | } else { |
||||
141 | // Successfully checked username, password and PIN. |
||||
142 | monitor("login.php: access granted for user '$username'"); |
||||
143 | trace("access granted for user '$username'"); |
||||
144 | $_SESSION['username'] = $username; |
||||
145 | $_SESSION['address'] = $dbcon->ipAddress(); |
||||
146 | $_SESSION['pin'] = $pin; |
||||
147 | $_SESSION['starturl'] = CONFIG_START_URL; |
||||
148 | $_SESSION['monitor'] = CONFIG_STATIONNAME; |
||||
149 | $dbcon->addUser($username, $dbcon->ipAddress(), getDevice()); |
||||
150 | |||||
151 | // Weiterleitung zur geschützten Startseite |
||||
152 | if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') { |
||||
153 | if (php_sapi_name() == 'cgi') { |
||||
154 | header('Status: 303 See Other'); |
||||
155 | } else { |
||||
156 | header('HTTP/1.1 303 See Other'); |
||||
157 | } |
||||
158 | } |
||||
159 | trace(CONFIG_START_URL); |
||||
160 | header('Location: ' . CONFIG_START_URL); |
||||
161 | exit; |
||||
162 | } |
||||
163 | } |
||||
164 | ?> |
||||
165 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
||||
166 | "http://www.w3.org/TR/html4/strict.dtd"> |
||||
167 | |||||
168 | <html lang="de"> |
||||
169 | |||||
170 | <head> |
||||
171 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
||||
172 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
173 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
174 | <title><?=addslashes(__("PalMA – Login"))?></title> |
||||
175 | |||||
176 | <link rel="icon" href="theme/<?=CONFIG_THEME?>/favicon.ico" type="image/x-icon"> |
||||
177 | <link rel="stylesheet" href="font-awesome/css/font-awesome.min.css"> |
||||
178 | <link rel="stylesheet" href="pure-min.css"> |
||||
179 | <link rel="stylesheet" href="palma.css"> |
||||
180 | |||||
181 | </head> |
||||
182 | |||||
183 | <!-- |
||||
184 | |||||
185 | Copyright (C) 2014 Stefan Weil, Universitätsbibliothek Mannheim |
||||
186 | |||||
187 | TODO: |
||||
188 | * Use 'placeholder' attribute for input fields. |
||||
189 | |||||
190 | --> |
||||
191 | |||||
192 | <body onLoad="document.forms.auth.username.focus()"> |
||||
193 | <div id="login_mask"> |
||||
194 | |||||
195 | <form name="auth" class="pure-form pure-form-aligned" action="login.php" method="post"> |
||||
196 | |||||
197 | <fieldset class="login"> |
||||
198 | <legend> |
||||
199 | <img src="theme/<?=CONFIG_THEME?>/palma-logo-67x25.png" alt="PalMA" height="25"/> |
||||
200 | – <?=addslashes(__("Login"))?> |
||||
201 | </legend> |
||||
202 | <div id="login_fields"> |
||||
203 | <div class="pure-control-group"> |
||||
204 | <label for="username"><?=addslashes(__("User name"))?></label |
||||
205 | ><input id="username" name="username" type="text" value="<?=htmlspecialchars($username)?>"> |
||||
206 | </div> |
||||
207 | <?php |
||||
208 | if (CONFIG_PASSWORD) { |
||||
209 | ?> |
||||
210 | <div class="pure-control-group"> |
||||
211 | <label for="userpassword"><?=addslashes(__("Password"))?></label |
||||
212 | ><input id="userpassword" name="userpassword" type="password"> |
||||
213 | </div> |
||||
214 | <?php |
||||
215 | } |
||||
216 | if (CONFIG_PIN) { |
||||
217 | ?> |
||||
218 | <div class="pure-control-group"> |
||||
219 | <label for="pin"><?=addslashes(__("PIN"))?></label |
||||
220 | ><input id="pin" name="pin" type="text" value="<?=htmlspecialchars($posted_pin)?>"> |
||||
221 | </div> |
||||
222 | <?php |
||||
223 | } |
||||
224 | ?> |
||||
225 | </div> |
||||
226 | <div class="pure-controls"> |
||||
227 | <button type="submit" class="pure-button pure-button-primary"><?=addslashes(__("Log in"))?><i class="fa fa-sign-in"></i></button> |
||||
228 | </div> |
||||
229 | </fieldset> |
||||
230 | |||||
231 | </form> |
||||
232 | |||||
233 | <?php |
||||
234 | if ($errtext) { |
||||
235 | echo("<p>$errtext</p>"); |
||||
236 | } |
||||
237 | if (defined('CONFIG_POLICY')) { |
||||
238 | echo('<div class="policy">' . CONFIG_POLICY . '</div>'); |
||||
239 | } |
||||
240 | ?> |
||||
241 | |||||
242 | </div> |
||||
243 | |||||
244 | </body> |
||||
245 | </html> |
||||
246 |