Subversion Repositories oidplus

Rev

Rev 427 | Rev 454 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2019 Daniel Marschall, ViaThinkSoft
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
class OIDplusAuthUtils {
21
 
14 daniel-mar 22
        // RA authentication functions
2 daniel-mar 23
 
24
        public static function raLogin($email) {
25
                if (strpos($email, '|') !== false) return;
26
 
42 daniel-mar 27
                $ses = OIDplus::sesHandler();
2 daniel-mar 28
                $list = $ses->getValue('oidplus_logged_in');
29
                if (is_null($list)) $list = '';
30
 
31
                $ary = ($list == '') ? array() : explode('|', $list);
32
                if (!in_array($email, $ary)) $ary[] = $email;
33
                $list = implode('|', $ary);
34
 
35
                $ses->setValue('oidplus_logged_in', $list);
36
        }
37
 
38
        public static function raLogout($email) {
42 daniel-mar 39
                $ses = OIDplus::sesHandler();
2 daniel-mar 40
                $list = $ses->getValue('oidplus_logged_in');
41
                if (is_null($list)) $list = '';
42
 
43
                $ary = ($list == '') ? array() : explode('|', $list);
44
                $key = array_search($email, $ary);
45
                if ($key !== false) unset($ary[$key]);
46
                $list = implode('|', $ary);
47
 
48
                $ses->setValue('oidplus_logged_in', $list);
85 daniel-mar 49
 
179 daniel-mar 50
                if (($list == '') && (!self::isAdminLoggedIn())) {
85 daniel-mar 51
                        // Nobody logged in anymore. Destroy session cookie to make GDPR people happy
52
                        $ses->destroySession();
53
                }
2 daniel-mar 54
        }
55
 
329 daniel-mar 56
        public static function raCheckPassword($ra_email, $password) {
57
                $ra = new OIDplusRA($ra_email);
453 daniel-mar 58
 
59
                $salt = null;
60
                $authkey = null;
61
                list($salt, $authkey) = $ra->getAuthInfo();
62
 
63
                $plugins = OIDplus::getAuthPlugins();
64
                if (count($plugins) == 0) {
65
                        throw new OIDplusException(_L('No RA authentication plugins found'));
66
                }
67
                foreach ($plugins as $plugin) {
68
                        if ($plugin->verify($authkey, $salt, $password)) return true;
69
                }
70
 
71
                return false;
329 daniel-mar 72
        }
73
 
85 daniel-mar 74
        public static function raNumLoggedIn() {
329 daniel-mar 75
                return count(self::loggedInRaList());
85 daniel-mar 76
        }
77
 
2 daniel-mar 78
        public static function raLogoutAll() {
42 daniel-mar 79
                $ses = OIDplus::sesHandler();
2 daniel-mar 80
                $ses->setValue('oidplus_logged_in', '');
81
        }
82
 
83
        public static function loggedInRaList() {
329 daniel-mar 84
                if (self::forceAllLoggedOut()) {
282 daniel-mar 85
                        return array();
86
                }
329 daniel-mar 87
 
42 daniel-mar 88
                $ses = OIDplus::sesHandler();
2 daniel-mar 89
                $list = $ses->getValue('oidplus_logged_in');
90
                if (is_null($list)) $list = '';
115 daniel-mar 91
 
92
                $res = array();
329 daniel-mar 93
                foreach (array_unique(explode('|',$list)) as $ra_email) {
115 daniel-mar 94
                        if ($ra_email == '') continue;
95
                        $res[] = new OIDplusRA($ra_email);
96
                }
97
                return $res;
2 daniel-mar 98
        }
99
 
100
        public static function isRaLoggedIn($email) {
115 daniel-mar 101
                foreach (self::loggedInRaList() as $ra) {
102
                        if ($email == $ra->raEmail()) return true;
103
                }
104
                return false;
2 daniel-mar 105
        }
106
 
14 daniel-mar 107
        // Admin authentication functions
2 daniel-mar 108
 
109
        public static function adminLogin() {
42 daniel-mar 110
                $ses = OIDplus::sesHandler();
2 daniel-mar 111
                $ses->setValue('oidplus_admin_logged_in', '1');
112
        }
113
 
114
        public static function adminLogout() {
42 daniel-mar 115
                $ses = OIDplus::sesHandler();
85 daniel-mar 116
                $ses->setValue('oidplus_admin_logged_in', '0');
117
 
118
                if (self::raNumLoggedIn() == 0) {
119
                        // Nobody logged in anymore. Destroy session cookie to make GDPR people happy
120
                        $ses->destroySession();
121
                }
2 daniel-mar 122
        }
123
 
124
        public static function adminCheckPassword($password) {
421 daniel-mar 125
                $passwordData = OIDplus::baseConfig()->getValue('ADMIN_PASSWORD', '');
126
                if (empty($passwordData)) {
360 daniel-mar 127
                        throw new OIDplusException(_L('No admin password set in %1','userdata/baseconfig/config.inc.php'));
261 daniel-mar 128
                }
421 daniel-mar 129
                if (strpos($passwordData, '$') !== false) {
130
                        list($s_salt, $hash) = explode('$', $passwordData, 2);
131
                } else {
132
                        $s_salt = '';
133
                        $hash = $passwordData;
134
                }
135
                return strcmp(sha3_512($s_salt.$password, true), base64_decode($hash)) === 0;
2 daniel-mar 136
        }
137
 
138
        public static function isAdminLoggedIn() {
329 daniel-mar 139
                if (self::forceAllLoggedOut()) {
282 daniel-mar 140
                        return false;
141
                }
42 daniel-mar 142
                $ses = OIDplus::sesHandler();
2 daniel-mar 143
                return $ses->getValue('oidplus_admin_logged_in') == '1';
144
        }
145
 
310 daniel-mar 146
        // Authentication keys for validating arguments (e.g. sent by mail)
2 daniel-mar 147
 
148
        public static function makeAuthKey($data) {
424 daniel-mar 149
                $data = OIDplus::baseConfig()->getValue('SERVER_SECRET') . '/AUTHKEY/' . $data;
421 daniel-mar 150
                $calc_authkey = sha3_512($data, false);
2 daniel-mar 151
                return $calc_authkey;
152
        }
153
 
154
        public static function validateAuthKey($data, $auth_key) {
421 daniel-mar 155
                return strcmp(self::makeAuthKey($data), $auth_key) === 0;
2 daniel-mar 156
        }
157
 
329 daniel-mar 158
        // "Veto" functions to force logout state
159
 
160
        public static function forceAllLoggedOut() {
161
                if (isset($_SERVER['SCRIPT_FILENAME']) && (basename($_SERVER['SCRIPT_FILENAME']) == 'sitemap.php')) {
162
                        // The sitemap may not contain any confidential information,
163
                        // even if the user is logged in, because the admin could
164
                        // accidentally copy-paste the sitemap to a
165
                        // search engine control panel while they are logged in
166
                        return true;
167
                } else {
168
                        return false;
169
                }
170
        }
427 daniel-mar 171
 
424 daniel-mar 172
        // CSRF functions
427 daniel-mar 173
 
424 daniel-mar 174
        private $enable_csrf = true;
427 daniel-mar 175
 
424 daniel-mar 176
        public function enableCSRF() {
177
                $this->enable_csrf = true;
178
        }
427 daniel-mar 179
 
424 daniel-mar 180
        public function disableCSRF() {
181
                $this->enable_csrf = false;
182
        }
427 daniel-mar 183
 
424 daniel-mar 184
        public function genCSRFToken() {
185
                return uniqid(mt_rand(), true);
186
        }
427 daniel-mar 187
 
424 daniel-mar 188
        public function checkCSRF() {
427 daniel-mar 189
                if (!$this->enable_csrf) return;
424 daniel-mar 190
                if (!isset($_REQUEST['csrf_token']) || !isset($_COOKIE['csrf_token']) || ($_REQUEST['csrf_token'] != $_COOKIE['csrf_token'])) {
191
                        throw new Exception(_L('Wrong CSRF Token'));
192
                }
193
        }
329 daniel-mar 194
 
421 daniel-mar 195
        // Generate RA passwords
196
 
197
        public static function raGeneratePassword($password) {
453 daniel-mar 198
                $def_method = OIDplus::config()->getValue('default_ra_auth_method');
199
 
200
                $plugins = OIDplus::getAuthPlugins();
201
                foreach ($plugins as $plugin) {
202
                        if (basename($plugin->getPluginDirectory()) === $def_method) {
203
                                return $plugin->generate($password);
204
                        }
205
                }
206
                throw new OIDplusException(_L('Default RA auth method/plugin "%1" not found',$def_method));
421 daniel-mar 207
        }
208
 
209
        // Generate admin password
210
 
211
        /* Nothing here; the admin password will be generated in setup_base.js */
212
 
213
}