Browse code

Google-Auth-Token setzen und QR-Code anzeigen

Bernd Wurst authored on14/09/2012 14:43:20
Showing8 changed files
1 1
new file mode 100644
... ...
@@ -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
 
298 298
new file mode 100644
... ...
@@ -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 54
new file mode 100644
... ...
@@ -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 169
new file mode 100644
... ...
@@ -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 25
new file mode 100644
... ...
@@ -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 109
new file mode 100644
... ...
@@ -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 39
new file mode 100644
... ...
@@ -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
+?>