Skip to content
This repository was archived by the owner on Aug 9, 2021. It is now read-only.

Commit 9c6f00e

Browse files
committed
feat(m2m): m2m authentication with HTTP backend
Signed-off-by: Thierry Bugier <[email protected]>
1 parent aa9c6c5 commit 9c6f00e

File tree

5 files changed

+316
-15
lines changed

5 files changed

+316
-15
lines changed

front/mosquitto-authenticate.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
/**
3+
* LICENSE
4+
*
5+
* Copyright © 2016-2018 Teclib'
6+
* Copyright © 2010-2018 by the FusionInventory Development Team.
7+
*
8+
* This file is part of Flyve MDM Plugin for GLPI.
9+
*
10+
* Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
11+
* device management software.
12+
*
13+
* Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
14+
* modify it under the terms of the GNU Affero General Public License as published
15+
* by the Free Software Foundation, either version 3 of the License, or
16+
* (at your option) any later version.
17+
* Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
23+
* ------------------------------------------------------------------------------
24+
* @author Thierry Bugier
25+
* @copyright Copyright © 2018 Teclib
26+
* @license AGPLv3+ http://www.gnu.org/licenses/agpl.txt
27+
* @link https://github.com/flyve-mdm/glpi-plugin
28+
* @link https://flyve-mdm.com/
29+
* ------------------------------------------------------------------------------
30+
*/
31+
32+
// Workaround CSRF checks
33+
$postData = $_POST;
34+
unset($_POST);
35+
include '../../../inc/includes.php';
36+
$plugin = new Plugin();
37+
if (!$plugin->isActivated('flyvemdm')) {
38+
http_response_code(404);
39+
}
40+
$_POST = $postData;
41+
$flyvemdmM2mApi = new PluginFlyvemdmMosquittoAuth();
42+
$answer = $flyvemdmM2mApi->authenticate($_POST);
43+
44+
http_response_code($answer);

inc/m2mauthinterface.class.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* LICENSE
4+
*
5+
* Copyright © 2016-2018 Teclib'
6+
* Copyright © 2010-2018 by the FusionInventory Development Team.
7+
*
8+
* This file is part of Flyve MDM Plugin for GLPI.
9+
*
10+
* Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
11+
* device management software.
12+
*
13+
* Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
14+
* modify it under the terms of the GNU Affero General Public License as published
15+
* by the Free Software Foundation, either version 3 of the License, or
16+
* (at your option) any later version.
17+
* Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
23+
* ------------------------------------------------------------------------------
24+
* @author Thierry Bugier
25+
* @copyright Copyright © 2018 Teclib
26+
* @license AGPLv3+ http://www.gnu.org/licenses/agpl.txt
27+
* @link https://github.com/flyve-mdm/glpi-plugin
28+
* @link https://flyve-mdm.com/
29+
* ------------------------------------------------------------------------------
30+
*/
31+
32+
if (!defined('GLPI_ROOT')) {
33+
die("Sorry. You can't access this file directly");
34+
}
35+
36+
interface PluginFlyvemdmM2mAuthInterface {
37+
/**
38+
* Challenges an authentication attempt from Mosquitto
39+
* @see https://github.com/rabbitmq/rabbitmq-auth-backend-http/blob/v3.7.5/README.md
40+
*
41+
* @param array $input POST data
42+
*
43+
* @return integer HTTP response code
44+
*/
45+
public function authenticate($input);
46+
}

inc/mosquittoauth.class.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/**
3+
* LICENSE
4+
*
5+
* Copyright © 2016-2018 Teclib'
6+
* Copyright © 2010-2018 by the FusionInventory Development Team.
7+
*
8+
* This file is part of Flyve MDM Plugin for GLPI.
9+
*
10+
* Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
11+
* device management software.
12+
*
13+
* Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
14+
* modify it under the terms of the GNU Affero General Public License as published
15+
* by the Free Software Foundation, either version 3 of the License, or
16+
* (at your option) any later version.
17+
* Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
23+
* ------------------------------------------------------------------------------
24+
* @author Thierry Bugier
25+
* @copyright Copyright © 2018 Teclib
26+
* @license AGPLv3+ http://www.gnu.org/licenses/agpl.txt
27+
* @link https://github.com/flyve-mdm/glpi-plugin
28+
* @link https://flyve-mdm.com/
29+
* ------------------------------------------------------------------------------
30+
*/
31+
32+
if (!defined('GLPI_ROOT')) {
33+
die("Sorry. You can't access this file directly");
34+
}
35+
36+
class PluginFlyvemdmMosquittoAuth implements PluginFlyvemdmM2mAuthInterface {
37+
public function authenticate($input) {
38+
if (!isset($input['username']) || !isset($input['password'])) {
39+
// No credentials or credentials incomplete
40+
return 404;
41+
}
42+
43+
$remoteIp = Toolbox::getRemoteIpAddress();
44+
$config = Config::getConfigurationValues('flyvemdm', ['mqtt_broker_internal_address']);
45+
if ($config['mqtt_broker_internal_address'] != $remoteIp) {
46+
return 403;
47+
}
48+
49+
$mqttUser = new PluginFlyvemdmMqttUser();
50+
if (!$mqttUser->getByUser($input['username'])) {
51+
return 404;
52+
}
53+
$input['password'] = Toolbox::stripslashes_deep($input['password']);
54+
if ($mqttUser->comparePasswords($input['password'])) {
55+
return 200;
56+
}
57+
58+
return 404;
59+
}
60+
}

inc/mqttuser.class.php

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@
3838
*/
3939
class PluginFlyvemdmMqttuser extends CommonDBTM {
4040

41+
private $pbdkf2Settings = [
42+
'algorithm' => 'sha256',
43+
'iterations' => 901,
44+
'saltSize' => 12,
45+
'keyLength' => 48,
46+
];
47+
4148
/**
4249
* @see CommonDBTM::prepareInputForAdd()
4350
*/
@@ -112,34 +119,61 @@ public function post_updateItem($history = 1) {
112119
}
113120
}
114121

122+
115123
/**
116124
* Hash a password
117125
* @param string $clearPassword
118126
* @return string PBKDF2 hashed password
119127
*/
120-
protected function hashPassword($clearPassword) {
128+
public function hashPassword($clearPassword) {
121129
// These parameters may be added to the function as a future improvement
122-
$algorithm = 'sha256';
123-
$saltSize = 12;
124-
$keyLength = 24;
125-
$salt = base64_encode(openssl_random_pseudo_bytes($saltSize));
126-
$iterations = 901;
127-
$rawOutput = true;
128-
129-
if ($rawOutput) {
130-
$keyLength *= 2;
131-
}
130+
$algorithm = $this->pbdkf2Settings['algorithm'];
131+
$keyLength = $this->pbdkf2Settings['keyLength'];
132+
$salt = base64_encode(openssl_random_pseudo_bytes($this->pbdkf2Settings['saltSize']));
133+
$iterations = $this->pbdkf2Settings['iterations'];
134+
135+
$hashed = hash_pbkdf2('sha256', $clearPassword, $salt, $iterations, $keyLength, true);
136+
137+
return implode(
138+
'$',
139+
[
140+
'PBKDF2',
141+
$algorithm,
142+
$iterations,
143+
$salt,
144+
base64_encode($hashed)
145+
]
146+
);
147+
}
132148

133-
$hashed = hash_pbkdf2('sha256', $clearPassword, $salt, $iterations, $keyLength, $rawOutput);
149+
/**
150+
* Challenge a password against tha hashed password stored in database
151+
*
152+
* @param string $challenged
153+
*
154+
* @return boolean true if the password matches the hashed password
155+
*/
156+
public function comparePasswords($challenged) {
157+
if ($this->isNewItem()) {
158+
return false;
159+
}
134160

135-
return 'PBKDF2$' . $algorithm . '$' . $iterations . '$' . $salt . '$' . base64_encode($hashed);
161+
$pbdkf2 = explode('$', $this->fields['password']);
162+
$algorithm = $pbdkf2[1];
163+
$salt = $pbdkf2[3];
164+
$iterations = $pbdkf2[2];
165+
$keyLength = strlen(base64_decode($pbdkf2[4]));
166+
$hashed = hash_pbkdf2($algorithm, $challenged, $salt, $iterations, $keyLength, true);
167+
return $hashed === base64_decode($pbdkf2[4]);
136168
}
137169

138170
/**
139-
* Generate a random password havind a determined set pf chars
140-
* http://stackoverflow.com/a/31284266
171+
* Generate a random password havind a determined set of chars
172+
* @see http://stackoverflow.com/a/31284266
173+
*
141174
* @param integer $length password length to generate
142175
* @param string $keyspace characters available to build the password
176+
*
143177
* @return string
144178
* @throws Exception
145179
*/
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
/**
3+
* LICENSE
4+
*
5+
* Copyright © 2016-2018 Teclib'
6+
* Copyright © 2010-2018 by the FusionInventory Development Team.
7+
*
8+
* This file is part of Flyve MDM Plugin for GLPI.
9+
*
10+
* Flyve MDM Plugin for GLPI is a subproject of Flyve MDM. Flyve MDM is a mobile
11+
* device management software.
12+
*
13+
* Flyve MDM Plugin for GLPI is free software: you can redistribute it and/or
14+
* modify it under the terms of the GNU Affero General Public License as published
15+
* by the Free Software Foundation, either version 3 of the License, or
16+
* (at your option) any later version.
17+
* Flyve MDM Plugin for GLPI is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with Flyve MDM Plugin for GLPI. If not, see http://www.gnu.org/licenses/.
23+
* ------------------------------------------------------------------------------
24+
* @author Domingo Oropeza
25+
* @copyright Copyright © 2018 Teclib
26+
* @license AGPLv3+ http://www.gnu.org/licenses/agpl.txt
27+
* @link https://github.com/flyve-mdm/glpi-plugin
28+
* @link https://flyve-mdm.com/
29+
* ------------------------------------------------------------------------------
30+
*/
31+
namespace tests\units;
32+
33+
use Flyvemdm\Tests\CommonTestCase;
34+
35+
class PluginFlyvemdmMosquittoAuth extends CommonTestCase {
36+
37+
private $mqttUser = null;
38+
39+
public function beforeTestMethod($method) {
40+
switch ($method) {
41+
case 'testAuthenticate':
42+
$this->mqttUser = new \PluginFlyvemdmMqttUser();
43+
$this->mqttUser->add([
44+
'user' => 'john',
45+
'password' => 'doe',
46+
]);
47+
break;
48+
}
49+
}
50+
51+
public function afterTestMethod($method) {
52+
switch ($method) {
53+
case 'testAuthenticate':
54+
$this->mqttUser->delete($this->mqttUser->fields, 1);
55+
break;
56+
}
57+
}
58+
59+
public function providerAuthenticate() {
60+
return [
61+
[
62+
'input' => [
63+
'username' => 'foo',
64+
'password' => 'bar',
65+
],
66+
'repoteIp' => '127.0.0.1',
67+
'expected' => [
68+
'httpCode' => '404',
69+
]
70+
],
71+
[
72+
'input' => [
73+
'username' => 'john',
74+
'password' => 'doe',
75+
],
76+
'repoteIp' => '127.0.0.1',
77+
'expected' => [
78+
'httpCode' => '200',
79+
]
80+
],
81+
[
82+
'input' => [
83+
'username' => 'john',
84+
'password' => 'bar',
85+
],
86+
'repoteIp' => '127.0.0.1',
87+
'expected' => [
88+
'httpCode' => '404',
89+
]
90+
],
91+
[
92+
'input' => [
93+
'username' => 'john',
94+
'password' => 'doe',
95+
],
96+
'repoteIp' => '10.0.0.1',
97+
'expected' => [
98+
'httpCode' => '403',
99+
]
100+
],
101+
];
102+
}
103+
104+
/**
105+
* @dataProvider providerAuthenticate
106+
*/
107+
public function testAuthenticate($input, $remoteIp, $expected) {
108+
$backupServer = $_SERVER;
109+
$_SERVER['REMOTE_ADDR'] = $remoteIp;
110+
111+
$instance = new \PluginFlyvemdmMosquittoAuth();
112+
$output = $instance->authenticate($input);
113+
$this->integer((int) $output)->isEqualTo($expected['httpCode']);
114+
115+
$_SERVER = $backupServer;
116+
}
117+
}

0 commit comments

Comments
 (0)