Bernd Wurst commited on 2012-09-14 14:43:20
Zeige 8 geänderte Dateien mit 653 Einfügungen und 2 Löschungen.
... | ... |
@@ -0,0 +1,201 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+/** |
|
4 |
+ * PHP Class for handling Google Authenticator 2-factor authentication |
|
5 |
+ * |
|
6 |
+ * @author Michael Kliewe |
|
7 |
+ * @copyright 2012 Michael Kliewe |
|
8 |
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
|
9 |
+ * @link http://www.phpgangsta.de/ |
|
10 |
+ */ |
|
11 |
+ |
|
12 |
+class PHPGangsta_GoogleAuthenticator |
|
13 |
+{ |
|
14 |
+ protected $_codeLength = 6; |
|
15 |
+ |
|
16 |
+ /** |
|
17 |
+ * Create new secret. |
|
18 |
+ * 16 characters, randomly chosen from the allowed base32 characters. |
|
19 |
+ * |
|
20 |
+ * @param int $secretLength |
|
21 |
+ * @return string |
|
22 |
+ */ |
|
23 |
+ public function createSecret($secretLength = 16) |
|
24 |
+ { |
|
25 |
+ $validChars = $this->_getBase32LookupTable(); |
|
26 |
+ unset($validChars[32]); |
|
27 |
+ |
|
28 |
+ $secret = ''; |
|
29 |
+ for ($i = 0; $i < $secretLength; $i++) { |
|
30 |
+ $secret .= $validChars[array_rand($validChars)]; |
|
31 |
+ } |
|
32 |
+ return $secret; |
|
33 |
+ } |
|
34 |
+ |
|
35 |
+ /** |
|
36 |
+ * Calculate the code, with given secret and point in time |
|
37 |
+ * |
|
38 |
+ * @param string $secret |
|
39 |
+ * @param int|null $timeSlice |
|
40 |
+ * @return string |
|
41 |
+ */ |
|
42 |
+ public function getCode($secret, $timeSlice = null) |
|
43 |
+ { |
|
44 |
+ if ($timeSlice === null) { |
|
45 |
+ $timeSlice = floor(time() / 30); |
|
46 |
+ } |
|
47 |
+ |
|
48 |
+ $secretkey = $this->_base32Decode($secret); |
|
49 |
+ |
|
50 |
+ // Pack time into binary string |
|
51 |
+ $time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice); |
|
52 |
+ // Hash it with users secret key |
|
53 |
+ $hm = hash_hmac('SHA1', $time, $secretkey, true); |
|
54 |
+ // Use last nipple of result as index/offset |
|
55 |
+ $offset = ord(substr($hm, -1)) & 0x0F; |
|
56 |
+ // grab 4 bytes of the result |
|
57 |
+ $hashpart = substr($hm, $offset, 4); |
|
58 |
+ |
|
59 |
+ // Unpak binary value |
|
60 |
+ $value = unpack('N', $hashpart); |
|
61 |
+ $value = $value[1]; |
|
62 |
+ // Only 32 bits |
|
63 |
+ $value = $value & 0x7FFFFFFF; |
|
64 |
+ |
|
65 |
+ $modulo = pow(10, $this->_codeLength); |
|
66 |
+ return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT); |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ /** |
|
70 |
+ * Get QR-Code URL for image, from google charts |
|
71 |
+ * |
|
72 |
+ * @param string $name |
|
73 |
+ * @param string $secret |
|
74 |
+ * @return string |
|
75 |
+ */ |
|
76 |
+ public function getQRCodeGoogleUrl($name, $secret) { |
|
77 |
+ $urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.''); |
|
78 |
+ return 'https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl='.$urlencoded.''; |
|
79 |
+ } |
|
80 |
+ |
|
81 |
+ /** |
|
82 |
+ * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now |
|
83 |
+ * |
|
84 |
+ * @param string $secret |
|
85 |
+ * @param string $code |
|
86 |
+ * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after) |
|
87 |
+ * @return bool |
|
88 |
+ */ |
|
89 |
+ public function verifyCode($secret, $code, $discrepancy = 1) |
|
90 |
+ { |
|
91 |
+ $currentTimeSlice = floor(time() / 30); |
|
92 |
+ |
|
93 |
+ for ($i = -$discrepancy; $i <= $discrepancy; $i++) { |
|
94 |
+ $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i); |
|
95 |
+ if ($calculatedCode == $code ) { |
|
96 |
+ return true; |
|
97 |
+ } |
|
98 |
+ } |
|
99 |
+ |
|
100 |
+ return false; |
|
101 |
+ } |
|
102 |
+ |
|
103 |
+ /** |
|
104 |
+ * Set the code length, should be >=6 |
|
105 |
+ * |
|
106 |
+ * @param int $length |
|
107 |
+ * @return PHPGangsta_GoogleAuthenticator |
|
108 |
+ */ |
|
109 |
+ public function setCodeLength($length) |
|
110 |
+ { |
|
111 |
+ $this->_codeLength = $length; |
|
112 |
+ return $this; |
|
113 |
+ } |
|
114 |
+ |
|
115 |
+ /** |
|
116 |
+ * Helper class to decode base32 |
|
117 |
+ * |
|
118 |
+ * @param $secret |
|
119 |
+ * @return bool|string |
|
120 |
+ */ |
|
121 |
+ protected function _base32Decode($secret) |
|
122 |
+ { |
|
123 |
+ if (empty($secret)) return ''; |
|
124 |
+ |
|
125 |
+ $base32chars = $this->_getBase32LookupTable(); |
|
126 |
+ $base32charsFlipped = array_flip($base32chars); |
|
127 |
+ |
|
128 |
+ $paddingCharCount = substr_count($secret, $base32chars[32]); |
|
129 |
+ $allowedValues = array(6, 4, 3, 1, 0); |
|
130 |
+ if (!in_array($paddingCharCount, $allowedValues)) return false; |
|
131 |
+ for ($i = 0; $i < 4; $i++){ |
|
132 |
+ if ($paddingCharCount == $allowedValues[$i] && |
|
133 |
+ substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) return false; |
|
134 |
+ } |
|
135 |
+ $secret = str_replace('=','', $secret); |
|
136 |
+ $secret = str_split($secret); |
|
137 |
+ $binaryString = ""; |
|
138 |
+ for ($i = 0; $i < count($secret); $i = $i+8) { |
|
139 |
+ $x = ""; |
|
140 |
+ if (!in_array($secret[$i], $base32chars)) return false; |
|
141 |
+ for ($j = 0; $j < 8; $j++) { |
|
142 |
+ $x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); |
|
143 |
+ } |
|
144 |
+ $eightBits = str_split($x, 8); |
|
145 |
+ for ($z = 0; $z < count($eightBits); $z++) { |
|
146 |
+ $binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:""; |
|
147 |
+ } |
|
148 |
+ } |
|
149 |
+ return $binaryString; |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ /** |
|
153 |
+ * Helper class to encode base32 |
|
154 |
+ * |
|
155 |
+ * @param string $secret |
|
156 |
+ * @param bool $padding |
|
157 |
+ * @return string |
|
158 |
+ */ |
|
159 |
+ protected function _base32Encode($secret, $padding = true) |
|
160 |
+ { |
|
161 |
+ if (empty($secret)) return ''; |
|
162 |
+ |
|
163 |
+ $base32chars = $this->_getBase32LookupTable(); |
|
164 |
+ |
|
165 |
+ $secret = str_split($secret); |
|
166 |
+ $binaryString = ""; |
|
167 |
+ for ($i = 0; $i < count($secret); $i++) { |
|
168 |
+ $binaryString .= str_pad(base_convert(ord($secret[$i]), 10, 2), 8, '0', STR_PAD_LEFT); |
|
169 |
+ } |
|
170 |
+ $fiveBitBinaryArray = str_split($binaryString, 5); |
|
171 |
+ $base32 = ""; |
|
172 |
+ $i = 0; |
|
173 |
+ while ($i < count($fiveBitBinaryArray)) { |
|
174 |
+ $base32 .= $base32chars[base_convert(str_pad($fiveBitBinaryArray[$i], 5, '0'), 2, 10)]; |
|
175 |
+ $i++; |
|
176 |
+ } |
|
177 |
+ if ($padding && ($x = strlen($binaryString) % 40) != 0) { |
|
178 |
+ if ($x == 8) $base32 .= str_repeat($base32chars[32], 6); |
|
179 |
+ elseif ($x == 16) $base32 .= str_repeat($base32chars[32], 4); |
|
180 |
+ elseif ($x == 24) $base32 .= str_repeat($base32chars[32], 3); |
|
181 |
+ elseif ($x == 32) $base32 .= $base32chars[32]; |
|
182 |
+ } |
|
183 |
+ return $base32; |
|
184 |
+ } |
|
185 |
+ |
|
186 |
+ /** |
|
187 |
+ * Get array with all 32 characters for decoding from/encoding to base32 |
|
188 |
+ * |
|
189 |
+ * @return array |
|
190 |
+ */ |
|
191 |
+ protected function _getBase32LookupTable() |
|
192 |
+ { |
|
193 |
+ return array( |
|
194 |
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7 |
|
195 |
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15 |
|
196 |
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23 |
|
197 |
+ 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31 |
|
198 |
+ '=' // padding char |
|
199 |
+ ); |
|
200 |
+ } |
|
201 |
+} |
... | ... |
@@ -289,9 +289,9 @@ function encode_querystring($querystring) |
289 | 289 |
} |
290 | 290 |
|
291 | 291 |
|
292 |
-function addnew($file, $label, $querystring = '') |
|
292 |
+function addnew($file, $label, $querystring = '', $attribs = '') |
|
293 | 293 |
{ |
294 |
- output('<p class="addnew">'.internal_link($file, $label, $querystring).'</p>'); |
|
294 |
+ output('<p class="addnew">'.internal_link($file, $label, $querystring, $attribs).'</p>'); |
|
295 | 295 |
} |
296 | 296 |
|
297 | 297 |
|
... | ... |
@@ -0,0 +1,53 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+require_once('inc/base.php'); |
|
18 |
+require_role(ROLE_SYSTEMUSER); |
|
19 |
+ |
|
20 |
+require_once('googleauth.php'); |
|
21 |
+ |
|
22 |
+$username = urldecode($_REQUEST['username']); |
|
23 |
+ |
|
24 |
+$oldpw = $_REQUEST['oldpw']; |
|
25 |
+$newpw = $_REQUEST['newpw']; |
|
26 |
+ |
|
27 |
+if (! validate_password($username, $oldpw)) { |
|
28 |
+ system_failure('Ihr bestehendes Mailbox-Passwort hat nicht gestimmt.'); |
|
29 |
+} |
|
30 |
+ |
|
31 |
+store_webmail_password($username, $oldpw, $newpw); |
|
32 |
+$secret = generate_secret($username); |
|
33 |
+ |
|
34 |
+title("Sicherer Zugang zum Webmailer"); |
|
35 |
+ |
|
36 |
+output('<p>Bitte geben Sie den folgenden Initialisierungs-Code in Ihre Google-Authenticator-Software ein oder Scannen Sie den QR-Code mit der Google-Authenticator-App Ihres Mobiltelefons.</p>'); |
|
37 |
+ |
|
38 |
+$qrcode_image = generate_qrcode_image($secret); |
|
39 |
+ |
|
40 |
+output('<h4>Ihr Initialisierungs-Code</h4><p style="font-size: 120%;">'.$secret.'</p><p><img src="data:image/png;base64,'.base64_encode($qrcode_image).'" /></p>'); |
|
41 |
+ |
|
42 |
+output('<h3>Testen Sie es...</h3><p>Nachdem Sie den Startwert in Ihren Google-Authenticator eingegeben haben bzw. den QRCode eingescannt haben, erhalten Sie umgehend einen Zugangscode. Geben Sie diesen hier ein um die Funktion zu testen:</p>'); |
|
43 |
+ |
|
44 |
+$form = '<p>Ihr Webmail-Benutzername: <input type="text" name="username" value="'.filter_input_general($username).'" /></p> |
|
45 |
+<p>Ihr neues Webmail-Passwort: <input type="password" name="webmailpass" /></p> |
|
46 |
+<p>Der aktuellste Einmal-Code von Google-Authenticator: <input type="text" name="ga_code" /></p> |
|
47 |
+<p><input type="submit" value="Prüfen!" /></p>'; |
|
48 |
+ |
|
49 |
+ |
|
50 |
+output(html_form('googleauth_test', 'test', '', $form)); |
|
51 |
+ |
|
52 |
+ |
|
53 |
+?> |
... | ... |
@@ -0,0 +1,168 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+ |
|
18 |
+function account_has_googleauth($username) |
|
19 |
+{ |
|
20 |
+ $username = mysql_real_escape_string($username); |
|
21 |
+ $result = db_query("SELECT id FROM mail.webmail_googleauth WHERE email='{$username}'"); |
|
22 |
+ if (mysql_num_rows($result) > 0) { |
|
23 |
+ $tmp = mysql_fetch_assoc($result); |
|
24 |
+ $id = $tmp['id']; |
|
25 |
+ return $id; |
|
26 |
+ } else { |
|
27 |
+ return false; |
|
28 |
+ } |
|
29 |
+} |
|
30 |
+ |
|
31 |
+ |
|
32 |
+ |
|
33 |
+function validate_password($username, $password) |
|
34 |
+{ |
|
35 |
+ $username = mysql_real_escape_string($username); |
|
36 |
+ $result = db_query("SELECT account, cryptpass FROM mail.courier_mailaccounts WHERE account='{$username}' UNION SELECT account, cryptpass FROM mail.courier_virtual_accounts WHERE account='{$username}'"); |
|
37 |
+ if (mysql_num_rows($result) != 1) { |
|
38 |
+ // Kein Account mit dem Namen oder Name nicht eindeutig |
|
39 |
+ return false; |
|
40 |
+ } |
|
41 |
+ $account = mysql_fetch_assoc($result); |
|
42 |
+ return (crypt($password, $account['cryptpass']) == $account['cryptpass']); |
|
43 |
+} |
|
44 |
+ |
|
45 |
+ |
|
46 |
+function store_webmail_password($username, $oldpw, $newpw) |
|
47 |
+{ |
|
48 |
+ $secret = $newpw; |
|
49 |
+ if (strlen($oldpw) > strlen($newpw)) { |
|
50 |
+ $secret = str_pad($newpw, strlen($oldpw), $newpw); |
|
51 |
+ } |
|
52 |
+ if (strlen($oldpw) < strlen($newpw)) { |
|
53 |
+ $newpw = substr($newpw, 0, strlen($oldpw)); |
|
54 |
+ } |
|
55 |
+ if (strlen($oldpw) != strlen($secret)) { |
|
56 |
+ system_failure('Interner Fehler: Passwörter sind nicht gleich lang'); |
|
57 |
+ } |
|
58 |
+ $code = ''; |
|
59 |
+ for ($i = 0 ; $i != strlen($oldpw) ; $i++) { |
|
60 |
+ $code .= chr( ord($oldpw[$i]) ^ ord($secret[$i]) ); |
|
61 |
+ } |
|
62 |
+ $code = base64_encode($code); |
|
63 |
+ DEBUG(array($oldpw, $newpw, $code)); |
|
64 |
+ |
|
65 |
+ |
|
66 |
+ db_query("REPLACE INTO mail.webmail_googleauth (email, webmailpass) VALUES ('{$username}', '{$code}')"); |
|
67 |
+} |
|
68 |
+ |
|
69 |
+ |
|
70 |
+function decode_webmail_password($crypted, $webmailpw) |
|
71 |
+{ |
|
72 |
+ $crypted = base64_decode($crypted); |
|
73 |
+ $secret = $webmailpw; |
|
74 |
+ if (strlen($crypted) > strlen($webmailpw)) { |
|
75 |
+ $secret = str_pad($webmailpw, strlen($crypted), $webmailpw); |
|
76 |
+ } |
|
77 |
+ if (strlen($crypted) < strlen($webmailpw)) { |
|
78 |
+ $webmailpw = substr($webmailpw, 0, strlen($crypted)); |
|
79 |
+ } |
|
80 |
+ $clear = ''; |
|
81 |
+ for ($i = 0 ; $i != strlen($crypted) ; $i++) { |
|
82 |
+ $clear .= chr( ord($crypted[$i]) ^ ord($secret[$i]) ); |
|
83 |
+ } |
|
84 |
+ DEBUG('decrypted: '.$clear); |
|
85 |
+ return $clear; |
|
86 |
+} |
|
87 |
+ |
|
88 |
+ |
|
89 |
+function check_webmail_password($username, $webmailpass) |
|
90 |
+{ |
|
91 |
+ $username = mysql_real_escape_string($username); |
|
92 |
+ $result = db_query("SELECT webmailpass FROM mail.webmail_googleauth WHERE email='{$username}'"); |
|
93 |
+ $tmp = mysql_fetch_assoc($result); |
|
94 |
+ |
|
95 |
+ $crypted = $tmp['webmailpass']; |
|
96 |
+ |
|
97 |
+ $clear = decode_webmail_password($crypted, $webmailpass); |
|
98 |
+ |
|
99 |
+ return validate_password($username, $clear); |
|
100 |
+ |
|
101 |
+} |
|
102 |
+ |
|
103 |
+ |
|
104 |
+function generate_secret($username) |
|
105 |
+{ |
|
106 |
+ $username = mysql_real_escape_string($username); |
|
107 |
+ require_once('external/googleauthenticator/GoogleAuthenticator.php'); |
|
108 |
+ $ga = new PHPGangsta_GoogleAuthenticator(); |
|
109 |
+ |
|
110 |
+ $secret = $ga->createSecret(); |
|
111 |
+ DEBUG('GA-Secret: '.$secret); |
|
112 |
+ DEBUG('QrCode: '.$ga->getQRCodeGoogleUrl('Blog', $secret)); |
|
113 |
+ db_query("UPDATE mail.webmail_googleauth SET ga_secret='{$secret}' WHERE email='{$username}'"); |
|
114 |
+ return $secret; |
|
115 |
+} |
|
116 |
+ |
|
117 |
+function check_googleauth($username, $code) { |
|
118 |
+ $username = mysql_real_escape_string($username); |
|
119 |
+ |
|
120 |
+ $result = db_query("SELECT ga_secret FROM mail.webmail_googleauth WHERE email='{$username}'"); |
|
121 |
+ $tmp = mysql_fetch_assoc($result); |
|
122 |
+ $secret = $tmp['ga_secret']; |
|
123 |
+ |
|
124 |
+ require_once('external/googleauthenticator/GoogleAuthenticator.php'); |
|
125 |
+ $ga = new PHPGangsta_GoogleAuthenticator(); |
|
126 |
+ |
|
127 |
+ $checkResult = $ga->verifyCode($secret, $code, 2); // 2 = 2*30sec clock tolerance |
|
128 |
+ if ($checkResult) { |
|
129 |
+ DEBUG('OK'); |
|
130 |
+ } else { |
|
131 |
+ DEBUG('FAILED'); |
|
132 |
+ } |
|
133 |
+ return $checkResult; |
|
134 |
+ |
|
135 |
+} |
|
136 |
+ |
|
137 |
+function generate_qrcode_image($secret) { |
|
138 |
+ $url = 'otpauth://totp/Webmail?secret='.$secret; |
|
139 |
+ |
|
140 |
+ $descriptorspec = array( |
|
141 |
+ 0 => array("pipe", "r"), // STDIN ist eine Pipe, von der das Child liest |
|
142 |
+ 1 => array("pipe", "w"), // STDOUT ist eine Pipe, in die das Child schreibt |
|
143 |
+ 2 => array("pipe", "w") |
|
144 |
+ ); |
|
145 |
+ |
|
146 |
+ $process = proc_open('qrencode -t PNG -s 5 -o -', $descriptorspec, $pipes); |
|
147 |
+ |
|
148 |
+ if (is_resource($process)) { |
|
149 |
+ // $pipes sieht nun so aus: |
|
150 |
+ // 0 => Schreibhandle, das auf das Child STDIN verbunden ist |
|
151 |
+ // 1 => Lesehandle, das auf das Child STDOUT verbunden ist |
|
152 |
+ |
|
153 |
+ fwrite($pipes[0], $url); |
|
154 |
+ fclose($pipes[0]); |
|
155 |
+ |
|
156 |
+ $pngdata = stream_get_contents($pipes[1]); |
|
157 |
+ fclose($pipes[1]); |
|
158 |
+ |
|
159 |
+ // Es ist wichtig, dass Sie alle Pipes schließen bevor Sie |
|
160 |
+ // proc_close aufrufen, um Deadlocks zu vermeiden |
|
161 |
+ $return_value = proc_close($process); |
|
162 |
+ |
|
163 |
+ return $pngdata; |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ |
|
167 |
+} |
|
168 |
+ |
... | ... |
@@ -0,0 +1,24 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+$role = $_SESSION['role']; |
|
18 |
+ |
|
19 |
+if ($role & (ROLE_SYSTEMUSER | ROLE_MAILACCOUNT | ROLE_VMAIL_ACCOUNT)) { |
|
20 |
+ $menu["googleauth_overview"] = array("label" => "Sicheres Webmail", "file" => "overview", "weight" => 5, "submenu" => "email_vmail" ); |
|
21 |
+} |
|
22 |
+ |
|
23 |
+ |
|
24 |
+?> |
... | ... |
@@ -0,0 +1,108 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+require_once('googleauth.php'); |
|
18 |
+require_role(ROLE_SYSTEMUSER); |
|
19 |
+ |
|
20 |
+title("Sicherer Zugang zum Webmailer"); |
|
21 |
+ |
|
22 |
+output('<p>Sie können bei '.config('company_name').' den Zugang zum Webmailer mit einem Zwei-Faktor-Prozess mit abweichendem Passwort schützen.</p> |
|
23 |
+<p>Dieses System schützt Sie vor mitgelesenen Tastatureingaben in nicht vertrauenswürdiger Umgebung z.B. in einem Internet-Café.</p> |
|
24 |
+<p>Beim Zwei-Faktor-Prozess müssen Sie zum Login ein festes Webmail-Passwort und zusätzlich ein variabler Code, den beispielsweise Ihr Smartphone erzeugen kann, eingeben. Da sich dieser Code alle 30 Sekunden ändert, kann ein Angreifer sich nicht später mit einem abgehörten Passwort noch einmal anmelden. Zum Erzeugen des Einmal-Codes benötigen Sie ein Gerät, das <strong>Google-Authenticator</strong>-Codes erzeugen kann. Meist ist dies ein Smartphne mit einer entsprechenden App.</p> |
|
25 |
+<p><strong>Beachten Sie:</strong> Die Zwei-Faktor-Authentifizierung funktioniert nur für Webmail, beim Login via IMAP wird weiterhin nur das Passwort Ihres Postfachs benötigt. Damit dieses Passwort von einem Angreifer nicht mitgelesen werden kann, müssen Sie zur Zwei-Faktor-Authentifizierung unbedingt ein separates Passwort festlegen.</p> |
|
26 |
+<h3>Fügen Sie Zwei-Faktor-Authentifizierung zu Ihren bestehenden Postfächern hinzu</h3> |
|
27 |
+'); |
|
28 |
+ |
|
29 |
+ |
|
30 |
+require_once('modules/email/include/hasaccount.php'); |
|
31 |
+require_once('modules/email/include/vmail.php'); |
|
32 |
+ |
|
33 |
+if (! (user_has_accounts() || count(get_vmail_accounts())>0)) { |
|
34 |
+ |
|
35 |
+ output('<p><em>Bisher haben Sie kein Postfach. Bitte erstellen sie zunächst ein Postfach.</em></p>'); |
|
36 |
+} |
|
37 |
+else |
|
38 |
+{ |
|
39 |
+ |
|
40 |
+/* VMAIL */ |
|
41 |
+ |
|
42 |
+$domains = get_vmail_domains(); |
|
43 |
+$vmail_accounts = get_vmail_accounts(); |
|
44 |
+ |
|
45 |
+$sorted_by_domains = array(); |
|
46 |
+foreach ($vmail_accounts AS $account) |
|
47 |
+{ |
|
48 |
+ if ($account['password'] == '') { |
|
49 |
+ continue; |
|
50 |
+ } |
|
51 |
+ if (array_key_exists($account['domain'], $sorted_by_domains)) |
|
52 |
+ array_push($sorted_by_domains[$account['domain']], $account); |
|
53 |
+ else |
|
54 |
+ $sorted_by_domains[$account['domain']] = array($account); |
|
55 |
+} |
|
56 |
+ |
|
57 |
+DEBUG($sorted_by_domains); |
|
58 |
+ |
|
59 |
+if (count($sorted_by_domains) > 0) |
|
60 |
+{ |
|
61 |
+ foreach ($sorted_by_domains as $accounts_on_domain) |
|
62 |
+ { |
|
63 |
+ if (count($sorted_by_domains) > 2) { |
|
64 |
+ output('<h4>'.$accounts_on_domain[0]['domainname'].'</h4>'); |
|
65 |
+ } |
|
66 |
+ |
|
67 |
+ foreach ($accounts_on_domain AS $this_account) |
|
68 |
+ { |
|
69 |
+ $username = $this_account['local'].'@'.$this_account['domainname']; |
|
70 |
+ output('<div style="margin-left: 2em;"><p style="margin-left: -2em;"><strong>'.$username.'</strong></p>'); |
|
71 |
+ $id = account_has_googleauth($username); |
|
72 |
+ if ($id) { |
|
73 |
+ output(addnew('delete', 'Sicheren Zugang für dieses Postfach abschalten', 'username='.urlencode($username), 'style="background-image: url('.$prefix.'images/delete.png); color: red;"')); |
|
74 |
+ } else { |
|
75 |
+ output(addnew('setup', 'Sicheren Zugang für dieses Postfach aktivieren', 'username='.urlencode($username))); |
|
76 |
+ } |
|
77 |
+ output('</div>'); |
|
78 |
+ } |
|
79 |
+ } |
|
80 |
+} |
|
81 |
+ |
|
82 |
+/* Mailaccounts */ |
|
83 |
+ |
|
84 |
+require_once('modules/email/include/mailaccounts.php'); |
|
85 |
+ |
|
86 |
+$accounts = mailaccounts($_SESSION['userinfo']['uid']); |
|
87 |
+ |
|
88 |
+if (count($accounts) > 0) { |
|
89 |
+ |
|
90 |
+if (count($sorted_by_domains) > 0) { |
|
91 |
+ output('<h3>IMAP/POP3-Accounts</h3>'); |
|
92 |
+} |
|
93 |
+ |
|
94 |
+ |
|
95 |
+foreach ($accounts AS $acc) { |
|
96 |
+ if ($acc['mailbox']) { |
|
97 |
+ output('<div style="margin-left: 2em;"><p style="margin-left: -2em;"><strong>'.$acc['account'].'</strong></p>'); |
|
98 |
+ output(addnew('setup', 'Sicheren Zugang für dieses Postfach aktivieren', 'username='.urlencode($acc['account']))); |
|
99 |
+ output('</div>'); |
|
100 |
+ } |
|
101 |
+} |
|
102 |
+ |
|
103 |
+ |
|
104 |
+} |
|
105 |
+ |
|
106 |
+} |
|
107 |
+ |
|
108 |
+?> |
... | ... |
@@ -0,0 +1,38 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+require_once('inc/base.php'); |
|
18 |
+require_once('inc/security.php'); |
|
19 |
+require_role(ROLE_SYSTEMUSER); |
|
20 |
+ |
|
21 |
+$username = urldecode($_REQUEST['username']); |
|
22 |
+ |
|
23 |
+title("Sicherer Zugang zum Webmailer"); |
|
24 |
+ |
|
25 |
+output('<p><strong>Hinweise:</strong></p><ul><li>Nach Einrichtung der Zwei-Faktor-Authentifizierung funktioniert bei der Anmeldung über <a href="'.config('webmail_url').'">die zentrale Webmail-Login-Seite</a> nur noch dieses Passwort zusammen mit dem Einmal-Code, der mit dem Google-Authenticator erzeugt wird.</li> |
|
26 |
+<li>Ihr bestehendes IMAP-Passwort wird mit dem neuen Passwort verschlüsselt.</li><li>Über IMAP bzw. POP3 kann weiterhin nur mit dem bisherigen Passwort zugegriffen werden.</li><li>Wenn Sie ihr IMAP-Passwort ändern, wird diese Zwei-Faktor-Authentifizierung automatisch abgeschaltet.</li></ul>'); |
|
27 |
+ |
|
28 |
+$form = '<p>Geben Sie zunächst bitte das bestehende Passwort des Postfachs <strong>'.filter_input_general($username).'</strong> ein:</p> |
|
29 |
+<p>Postfach-Passwort: <input type="password" name="oldpw" /></p>'; |
|
30 |
+ |
|
31 |
+$form .= '<p>Geben sie hier bitte das neue Passwort ein, mit dem sich der Benutzer <strong>'.filter_input_general($username).'</strong> zukünftig anmelden muss.</p> |
|
32 |
+<p>Neues Webmail-Passwort: <input type="password" name="newpw" /></p>'; |
|
33 |
+ |
|
34 |
+$form .= '<p><input type="submit" value="Einrichten" /></p>'; |
|
35 |
+ |
|
36 |
+output(html_form('googleauth_setup', 'generate', 'username='.urlencode($username), $form)); |
|
37 |
+ |
|
38 |
+?> |
... | ... |
@@ -0,0 +1,59 @@ |
1 |
+<?php |
|
2 |
+/* |
|
3 |
+This file belongs to the Webinterface of schokokeks.org Hosting |
|
4 |
+ |
|
5 |
+Written 2008-2012 by schokokeks.org Hosting, namely |
|
6 |
+ Bernd Wurst <bernd@schokokeks.org> |
|
7 |
+ Hanno Böck <hanno@schokokeks.org> |
|
8 |
+ |
|
9 |
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. |
|
10 |
+ |
|
11 |
+You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see |
|
12 |
+http://creativecommons.org/publicdomain/zero/1.0/ |
|
13 |
+ |
|
14 |
+Nevertheless, in case you use a significant part of this code, we ask (but not require, see the license) that you keep the authors' names in place and return your changes to the public. We would be especially happy if you tell us what you're going to do with this code. |
|
15 |
+*/ |
|
16 |
+ |
|
17 |
+require_once('inc/base.php'); |
|
18 |
+require_once('inc/icons.php'); |
|
19 |
+require_role(ROLE_SYSTEMUSER); |
|
20 |
+ |
|
21 |
+require_once('googleauth.php'); |
|
22 |
+ |
|
23 |
+$username = $_REQUEST['username']; |
|
24 |
+$webmailpw = $_REQUEST['webmailpass']; |
|
25 |
+$ga_code = $_REQUEST['ga_code']; |
|
26 |
+ |
|
27 |
+$success = true; |
|
28 |
+ |
|
29 |
+if (! check_webmail_password($username, $webmailpw)) { |
|
30 |
+ input_error('Das Webmail-Passwort hat nicht gestimmt.'); |
|
31 |
+ $success = false; |
|
32 |
+} |
|
33 |
+ |
|
34 |
+if (! check_googleauth($username, $ga_code)) { |
|
35 |
+ input_error('Der Google-Authenticator-Code wurde nicht akzeptiert.'); |
|
36 |
+ $success = false; |
|
37 |
+} |
|
38 |
+ |
|
39 |
+title('Test der Zwei-Faktor-authentifizierung'); |
|
40 |
+ |
|
41 |
+if ($success) { |
|
42 |
+ output('<p>'.icon_ok().' Der Test war erfolgreich!'); |
|
43 |
+} else { |
|
44 |
+ output('<p>'.icon_error().' Der Test war leider nicht erfolgreich.'); |
|
45 |
+} |
|
46 |
+ |
|
47 |
+ |
|
48 |
+output('<h3>Weiterer Test</h3>'); |
|
49 |
+ |
|
50 |
+$form = '<p>Ihr Webmail-Benutzername: <input type="text" name="username" value="'.filter_input_general($username).'" /></p> |
|
51 |
+<p>Ihr neues Webmail-Passwort: <input type="password" name="webmailpass" /></p> |
|
52 |
+<p>Der aktuellste Einmal-Code von Google-Authenticator: <input type="text" name="ga_code" /></p> |
|
53 |
+<p><input type="submit" value="Prüfen!" /></p>'; |
|
54 |
+ |
|
55 |
+ |
|
56 |
+output(html_form('googleauth_test', 'test', '', $form)); |
|
57 |
+ |
|
58 |
+ |
|
59 |
+?> |
|
0 | 60 |