getDevice()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 16
nc 7
nop 0
dl 0
loc 21
rs 8.8333
c 1
b 0
f 0
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
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 ignore-call  annotation

95
        $errtext = addslashes(/** @scrutinizer ignore-call */ __('Invalid credentials!'));
Loading history...
96
    } elseif (preg_match('/404 Not Found/', $out)) {
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

96
    } elseif (preg_match('/404 Not Found/', /** @scrutinizer ignore-type */ $out)) {
Loading history...
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
Bug introduced by
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 ignore-call  annotation

139
        $errtext = addslashes(/** @scrutinizer ignore-call */ __('Invalid PIN.'));
Loading history...
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 &ndash; 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
        &ndash; <?=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