Rev 1102 | Rev 1119 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1102 | Rev 1116 | ||
---|---|---|---|
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | /* |
3 | /* |
4 | * OIDplus 2.0 |
4 | * OIDplus 2.0 |
5 | * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft |
5 | * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft |
6 | * |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | * you may not use this file except in compliance with 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 |
9 | * You may obtain a copy of the License at |
10 | * |
10 | * |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | * |
12 | * |
13 | * Unless required by applicable law or agreed to in writing, software |
13 | * Unless required by applicable law or agreed to in writing, software |
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | * See the License for the specific language governing permissions and |
16 | * See the License for the specific language governing permissions and |
17 | * limitations under the License. |
17 | * limitations under the License. |
18 | */ |
18 | */ |
19 | 19 | ||
20 | use ViaThinkSoft\OIDplus\OIDplusDatabaseConnection; |
20 | use ViaThinkSoft\OIDplus\OIDplusDatabaseConnection; |
- | 21 | use ViaThinkSoft\OIDplus\OIDplusException; |
|
21 | 22 | ||
22 | /** |
23 | /** |
23 | * This function is internally called by oidplus_dbupdate_1002(). |
24 | * This function is internally called by oidplus_dbupdate_1002(). |
24 | * It changes the auth keys A1*# and A2# to VTS-MCF and A3# to BCrypt-MCF. |
25 | * It changes the auth keys A1*# and A2# to VTS-MCF and A3# to BCrypt-MCF. |
25 | * @param OIDplusDatabaseConnection $db is the OIDplusDatabaseConnection class |
26 | * @param OIDplusDatabaseConnection $db is the OIDplusDatabaseConnection class |
- | 27 | * @throws OIDplusException |
|
26 | */ |
28 | */ |
27 | function oidplus_dbupdate_1002_migrate_ra_passwords(OIDplusDatabaseConnection $db) { |
29 | function oidplus_dbupdate_1002_migrate_ra_passwords(OIDplusDatabaseConnection $db) { |
28 | $res = $db->query("select * from ###ra "); |
30 | $res = $db->query("select * from ###ra "); |
29 | while ($row = $res->fetch_array()) { |
31 | while ($row = $res->fetch_array()) { |
30 | $salt = isset($row['salt']) ? $row['salt'] : ''; |
32 | $salt = isset($row['salt']) ? $row['salt'] : ''; |
31 | $new_auth_key = vts_crypt_convert_from_old_oidplus($row['authkey'], $salt); |
33 | $new_auth_key = vts_crypt_convert_from_old_oidplus($row['authkey'], $salt); |
32 | $email = $row['email']; |
34 | $email = $row['email']; |
33 | if ($new_auth_key !== $row['authkey']) { |
35 | if ($new_auth_key !== $row['authkey']) { |
34 | //echo 'Migrate authkey '.$row['authkey'].' to '.$new_auth_key.' for '.$email.'<br><br>'; |
36 | //echo 'Migrate authkey '.$row['authkey'].' to '.$new_auth_key.' for '.$email.'<br><br>'; |
35 | $db->query("update ###ra set authkey = ?, salt = ? where email = ?", array($new_auth_key, '', $email)); |
37 | $db->query("update ###ra set authkey = ?, salt = ? where email = ?", array($new_auth_key, '', $email)); |
36 | } |
38 | } |
37 | } |
39 | } |
38 | } |
40 | } |
39 | 41 | ||
40 | /** |
42 | /** |
41 | * This function converts A1*#, A2#, A3# hashes to Crypt compatible hashes. |
43 | * This function converts A1*#, A2#, A3# hashes to Crypt compatible hashes. |
42 | * @param string $authkey is old database field value "authkey" |
44 | * @param string $authkey is old database field value "authkey" |
43 | * @param string $salt is old database field value "salt" |
45 | * @param string $salt is old database field value "salt" |
44 | * @returns New authkey field (Crypt compatible hash) |
46 | * @returns New authkey field (Crypt compatible hash) |
45 | */ |
47 | */ |
46 | function vts_crypt_convert_from_old_oidplus($authkey, $salt) { |
48 | function vts_crypt_convert_from_old_oidplus($authkey, $salt) { |
47 | if (preg_match('@^A1([abcd])#(.+):(.+)$@', $authkey, $m)) { |
49 | if (preg_match('@^A1([abcd])#(.+):(.+)$@', $authkey, $m)) { |
48 | // A1a#hashalgo:X with X being H(salt+password) in hex- or rfc4648-base64-notation |
50 | // A1a#hashalgo:X with X being H(salt+password) in hex- or rfc4648-base64-notation |
49 | // A1b#hashalgo:X with X being H(password+salt) in hex- or rfc4648-base64-notation |
51 | // A1b#hashalgo:X with X being H(password+salt) in hex- or rfc4648-base64-notation |
50 | // A1c#hashalgo:X with X being H(salt+password+salt) in hex- or rfc4648-base64-notation |
52 | // A1c#hashalgo:X with X being H(salt+password+salt) in hex- or rfc4648-base64-notation |
51 | // A1d#hashalgo:X with X being H_HMAC(password,salt) in hex- or rfc4648-base64-notation |
53 | // A1d#hashalgo:X with X being H_HMAC(password,salt) in hex- or rfc4648-base64-notation |
52 | $mode = ''; // avoid PHPstan warning |
54 | $mode = ''; // avoid PHPstan warning |
53 | if ($m[1] == 'a') $mode = 'sp'; |
55 | if ($m[1] == 'a') $mode = 'sp'; |
54 | else if ($m[1] == 'b') $mode = 'ps'; |
56 | else if ($m[1] == 'b') $mode = 'ps'; |
55 | else if ($m[1] == 'c') $mode = 'sps'; |
57 | else if ($m[1] == 'c') $mode = 'sps'; |
56 | else if ($m[1] == 'd') $mode = 'hmac'; |
58 | else if ($m[1] == 'd') $mode = 'hmac'; |
57 | else assert(false); |
59 | else assert(false); |
58 | $algo = $m[2]; |
60 | $algo = $m[2]; |
59 | $bin_salt = $salt; |
61 | $bin_salt = $salt; |
60 | if (($algo == 'sha3-512') || ($algo == 'sha3-384') || ($algo == 'sha512') || ($algo == 'sha384')) { |
62 | if (($algo == 'sha3-512') || ($algo == 'sha3-384') || ($algo == 'sha512') || ($algo == 'sha384')) { |
61 | $bin_hash = base64_decode($m[3]); |
63 | $bin_hash = base64_decode($m[3]); |
62 | } else { |
64 | } else { |
63 | $bin_hash = hex2bin($m[3]); |
65 | $bin_hash = hex2bin($m[3]); |
64 | } |
66 | } |
65 | return crypt_modular_format_encode(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
67 | return crypt_modular_format_encode(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
66 | } else if (preg_match('@^A2#(.+)$@', $authkey, $m)) { |
68 | } else if (preg_match('@^A2#(.+)$@', $authkey, $m)) { |
67 | // A2#X with X being sha3(salt+password) in rfc4648-base64-notation |
69 | // A2#X with X being sha3(salt+password) in rfc4648-base64-notation |
68 | $mode = 'sp'; |
70 | $mode = 'sp'; |
69 | $algo = 'sha3-512'; |
71 | $algo = 'sha3-512'; |
70 | $bin_salt = $salt; |
72 | $bin_salt = $salt; |
71 | $bin_hash = base64_decode($m[1]); |
73 | $bin_hash = base64_decode($m[1]); |
72 | return crypt_modular_format_encode(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
74 | return crypt_modular_format_encode(OID_MCF_VTS_V1, $bin_salt, $bin_hash, array('a'=>$algo,'m'=>$mode)); |
73 | } else if (preg_match('@^A3#(.+)$@', $authkey, $m)) { |
75 | } else if (preg_match('@^A3#(.+)$@', $authkey, $m)) { |
74 | // A3#X with X being bcrypt [not VTS hash!] |
76 | // A3#X with X being bcrypt [not VTS hash!] |
75 | return $m[1]; |
77 | return $m[1]; |
76 | } else { |
78 | } else { |
77 | // Nothing to convert |
79 | // Nothing to convert |
78 | return $authkey; |
80 | return $authkey; |
79 | } |
81 | } |
80 | } |
82 | } |
81 | 83 | ||
82 | /** |
84 | /** |
83 | * This function will be called by OIDplusDatabaseConnection.class.php at method afterConnect(). |
85 | * This function will be called by OIDplusDatabaseConnection.class.php at method afterConnect(). |
84 | * @param OIDplusDatabaseConnection $db is the OIDplusDatabaseConnection class |
86 | * @param OIDplusDatabaseConnection $db is the OIDplusDatabaseConnection class |
85 | * @return int new version set |
87 | * @return int new version set |
86 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
88 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
87 | */ |
89 | */ |
88 | function oidplus_dbupdate_1002(OIDplusDatabaseConnection $db) { |
90 | function oidplus_dbupdate_1002(OIDplusDatabaseConnection $db) { |
89 | if ($db->transaction_supported()) $db->transaction_begin(); |
91 | if ($db->transaction_supported()) $db->transaction_begin(); |
90 | 92 | ||
91 | if ($db->getSlang()->id() == 'mssql') { |
93 | if ($db->getSlang()->id() == 'mssql') { |
92 | $db->query("alter table ###ra alter column [authkey] [varchar](250) NULL;"); |
94 | $db->query("alter table ###ra alter column [authkey] [varchar](250) NULL;"); |
93 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
95 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
94 | try { |
96 | try { |
95 | $db->query("alter table ###ra drop column [salt];"); |
97 | $db->query("alter table ###ra drop column [salt];"); |
96 | } catch(Exception $e) {} |
98 | } catch(Exception $e) {} |
97 | } |
99 | } |
98 | else if ($db->getSlang()->id() == 'mysql') { |
100 | else if ($db->getSlang()->id() == 'mysql') { |
99 | $db->query("alter table ###ra modify authkey varchar(250) NULL;"); |
101 | $db->query("alter table ###ra modify authkey varchar(250) NULL;"); |
100 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
102 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
101 | try { |
103 | try { |
102 | $db->query("alter table ###ra drop column salt;"); |
104 | $db->query("alter table ###ra drop column salt;"); |
103 | } catch(Exception $e) {} |
105 | } catch(Exception $e) {} |
104 | } |
106 | } |
105 | else if ($db->getSlang()->id() == 'pgsql') { |
107 | else if ($db->getSlang()->id() == 'pgsql') { |
106 | $db->query("alter table ###ra alter column authkey type varchar(250)"); |
108 | $db->query("alter table ###ra alter column authkey type varchar(250)"); |
107 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
109 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
108 | try { |
110 | try { |
109 | $db->query("alter table ###ra drop column salt"); |
111 | $db->query("alter table ###ra drop column salt"); |
110 | } catch(Exception $e) {} |
112 | } catch(Exception $e) {} |
111 | } |
113 | } |
112 | else if ($db->getSlang()->id() == 'oracle') { |
114 | else if ($db->getSlang()->id() == 'oracle') { |
113 | $db->query("alter table ###ra modify authkey varchar2(250)"); |
115 | $db->query("alter table ###ra modify authkey varchar2(250)"); |
114 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
116 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
115 | try { |
117 | try { |
116 | $db->query("alter table ###ra set unused column salt"); |
118 | $db->query("alter table ###ra set unused column salt"); |
117 | $db->query("alter table ###ra set drop unused columns"); |
119 | $db->query("alter table ###ra set drop unused columns"); |
118 | } catch(Exception $e) {} |
120 | } catch(Exception $e) {} |
119 | } |
121 | } |
120 | else if ($db->getSlang()->id() == 'sqlite') { |
122 | else if ($db->getSlang()->id() == 'sqlite') { |
121 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
123 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
122 | try { |
124 | try { |
123 | $db->query("alter table ###ra drop column salt"); |
125 | $db->query("alter table ###ra drop column salt"); |
124 | } catch(Exception $e) {} |
126 | } catch(Exception $e) {} |
125 | } |
127 | } |
126 | else if ($db->getSlang()->id() == 'access') { |
128 | else if ($db->getSlang()->id() == 'access') { |
127 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
129 | oidplus_dbupdate_1002_migrate_ra_passwords($db); |
128 | try { |
130 | try { |
129 | $db->query("alter table ###ra drop column salt"); |
131 | $db->query("alter table ###ra drop column salt"); |
130 | } catch(Exception $e) {} |
132 | } catch(Exception $e) {} |
131 | } |
133 | } |
132 | 134 | ||
133 | // Auth plugins A1 and A2 have been replaced with A5 |
135 | // Auth plugins A1 and A2 have been replaced with A5 |
134 | // Note that you cannot use `value` in the where clause on MSSQL, because "text and varchar" are incompatible... |
136 | // Note that you cannot use `value` in the where clause on MSSQL, because "text and varchar" are incompatible... |
135 | $res = $db->query("SELECT value from ###config where name = 'default_ra_auth_method'"); |
137 | $res = $db->query("SELECT value from ###config where name = 'default_ra_auth_method'"); |
136 | if ($row = $res->fetch_array()) { |
138 | if ($row = $res->fetch_array()) { |
137 | if (($row['value'] == 'A1_phpgeneric_salted_hex') || ($row['value'] == 'A2_sha3_salted_base64')) { |
139 | if (($row['value'] == 'A1_phpgeneric_salted_hex') || ($row['value'] == 'A2_sha3_salted_base64')) { |
138 | $db->query("UPDATE ###config SET value = 'A5_vts_mcf' WHERE name = 'default_ra_auth_method'"); |
140 | $db->query("UPDATE ###config SET value = 'A5_vts_mcf' WHERE name = 'default_ra_auth_method'"); |
139 | } |
141 | } |
140 | } |
142 | } |
141 | 143 | ||
142 | $version = 1002; |
144 | $version = 1002; |
143 | $db->query("UPDATE ###config SET value = ? WHERE name = 'database_version'", array($version)); |
145 | $db->query("UPDATE ###config SET value = ? WHERE name = 'database_version'", array($version)); |
144 | 146 | ||
145 | if ($db->transaction_supported()) $db->transaction_commit(); |
147 | if ($db->transaction_supported()) $db->transaction_commit(); |
146 | 148 | ||
147 | return $version; |
149 | return $version; |
148 | } |
150 | } |
149 | 151 |