Commit 80419563 authored by Côme Chilliet's avatar Côme Chilliet
Browse files

:ambulance: fix(fusioninventory): Improve error handling in collect.php

This returns a 500 error in case of a blocking error when storing
 inventory.
It also puts information in the status line along with the 500 error so
 that the fusioninventory-agent cli tool show the error.
Errors on sub-objects are logged only so that one missing objectClass or
 attribute from the schema does not block the whole inventory, seeing as
 fusioninventory fields seem to evolve each version.

issue #4348
Showing with 141 additions and 145 deletions
+141 -145
......@@ -8,182 +8,178 @@ require_once('variables.inc');
$http_raw_post_data = file_get_contents('php://input');
function returnError($errorText)
{
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol.' 500 '.$errorText);
error_log('Error while collecting inventory: '.$errorText);
exit();
}
if (!$http_raw_post_data) {
return;
return;
}
$compressmode = 'none';
if (strpos($http_raw_post_data, "<?xml") === 0) {
$xml = $http_raw_post_data;
$xml = $http_raw_post_data;
} elseif ($xml = @gzuncompress($http_raw_post_data)) {
$compressmode = "gzcompress";
$compressmode = "gzcompress";
} elseif ($xml = @gzinflate ("\x1f\x8b\x08\x00\x00\x00\x00\x00".$http_raw_post_data)) {
// ** OCS agent 2.0 Compatibility, but return in gzcompress
$compressmode = "gzdeflate";
if (strstr($xml, "<QUERY>PROLOG</QUERY>") && !strstr($xml, "<TOKEN>")) {
$compressmode = "gzcompress";
}
// ** OCS agent 2.0 Compatibility, but return in gzcompress
$compressmode = "gzdeflate";
if (strstr($xml, "<QUERY>PROLOG</QUERY>") && !strstr($xml, "<TOKEN>")) {
$compressmode = "gzcompress";
}
} elseif ($xml = @gzinflate (substr($http_raw_post_data, 2))) {
// ** OCS agent 2.0 Compatibility, but return in gzcompress
$compressmode = "gzdeflate";
if (strstr($xml, "<QUERY>PROLOG</QUERY>") && !strstr($xml, "<TOKEN>")) {
$compressmode = "gzcompress";
}
// ** OCS agent 2.0 Compatibility, but return in gzcompress
$compressmode = "gzdeflate";
if (strstr($xml, "<QUERY>PROLOG</QUERY>") && !strstr($xml, "<TOKEN>")) {
$compressmode = "gzcompress";
}
} else {
$f = tempnam('/tmp', 'gz_fix');
file_put_contents($f, "\x1f\x8b\x08\x00\x00\x00\x00\x00".$http_raw_post_data);
$xml = file_get_contents('compress.zlib://'.$f);
$f = tempnam('/tmp', 'gz_fix');
file_put_contents($f, "\x1f\x8b\x08\x00\x00\x00\x00\x00".$http_raw_post_data);
$xml = file_get_contents('compress.zlib://'.$f);
unlink($f);
unlink($f);
if (strpos($xml, "<?xml") === 0) {
$compressmode = "gzcompress";
} else {
$xml = '';
}
if (strpos($xml, "<?xml") === 0) {
$compressmode = "gzcompress";
} else {
$xml = '';
}
}
if (strpos($xml, "<?xml") !== 0) {
error_log("failed to extract XML content");
error_log("failed to extract XML content");
}
$reply = "";
if (preg_match('/QUERY>PROLOG<\/QUERY/', $xml)) {
$reply= '<?xml version="1.0" encoding="UTF-8"?>
<REPLY>
<RESPONSE>SEND</RESPONSE>
<PROLOG_FREQ>8</PROLOG_FREQ>
</REPLY>';
$reply = '<?xml version="1.0" encoding="UTF-8"?>
<REPLY>
<RESPONSE>SEND</RESPONSE>
<PROLOG_FREQ>8</PROLOG_FREQ>
</REPLY>';
} else {
$reply = '<?xml version="1.0" encoding="UTF-8"?>
<REPLY>
</REPLY>';
$data = xml::xml2array($xml, 1);
$data = $data['REQUEST']['CONTENT'];
$cpus = $data['CPUS'];
if (!is_numeric(key($cpus))) {
$cpus = array($cpus);
}
$os = $data['OPERATINGSYSTEM'];
if (!is_numeric(key($os))) {
$os = array($os);
$reply = '<?xml version="1.0" encoding="UTF-8"?>
<REPLY>
</REPLY>';
$data = xml::xml2array($xml, 1);
$data = $data['REQUEST']['CONTENT'];
$cpus = $data['CPUS'];
if (!is_numeric(key($cpus))) {
$cpus = array($cpus);
}
$os = $data['OPERATINGSYSTEM'];
if (!is_numeric(key($os))) {
$os = array($os);
}
/* Check if CONFIG_FILE is accessible */
if (!is_readable(CONFIG_DIR.'/'.CONFIG_FILE)) {
returnError(sprintf(_('FusionDirectory configuration %s/%s is not readable. Aborted.'), CONFIG_DIR, CONFIG_FILE));
}
$macs = array();
$ips = array();
foreach ($data['NETWORKS'] as $network) {
if (isset($network['MACADDR']) && ($network['MACADDR'] != '00:00:00:00:00:00')) {
$macs[] = $network['MACADDR'];
}
/* Check if CONFIG_FILE is accessible */
if (!is_readable(CONFIG_DIR.'/'.CONFIG_FILE)) {
die(sprintf(_('FusionDirectory configuration %s/%s is not readable. Aborted.'), CONFIG_DIR, CONFIG_FILE));
if (isset($network['IPADDRESS']) && ($network['IPADDRESS'] != '127.0.0.1')) {
$ips[] = $network['IPADDRESS'];
}
$macs = array();
$ips = array();
foreach ($data['NETWORKS'] as $network) {
if (isset($network['MACADDR']) && ($network['MACADDR'] != '00:00:00:00:00:00')) {
$macs[] = $network['MACADDR'];
}
if (isset($network['IPADDRESS']) && ($network['IPADDRESS'] != '127.0.0.1')) {
$ips[] = $network['IPADDRESS'];
}
if (isset($network['IPADDRESS6']) && ($network['IPADDRESS6'] != '::1')) {
$ips[] = $network['IPADDRESS6'];
}
if (isset($network['IPADDRESS6']) && ($network['IPADDRESS6'] != '::1')) {
$ips[] = $network['IPADDRESS6'];
}
$macs = array_values(array_unique($macs));
$ips = array_values(array_unique($ips));
/* Parse configuration file */
$config = new config(CONFIG_DIR.'/'.CONFIG_FILE, $BASE_DIR);
/* Set config server to default one */
$directory = $config->data['MAIN']['DEFAULT'];
if (!isset($config->data['LOCATIONS'][$directory])) {
$directory = key($config->data['LOCATIONS']);
}
$config->set_current($directory);
session::global_set('config', $config);
$ldap = $config->get_ldap_link();
$dn = 'cn='.$_SERVER['REMOTE_ADDR'].','.get_ou('inventoryRDN').$config->current['BASE'];
$ldap->cat($dn);
$msg = "";
if ($ldap->count()) {
/* Emtpy the subtree */
$ldap->rmdir_recursive($dn);
if (!$ldap->success()) {
$msg.="error :".$ldap->get_error()."\n";
}
} else {
/* Make sure branch is existing */
$ldap->cd($config->current['BASE']);
$ldap->create_missing_trees(get_ou('inventoryRDN').$config->current['BASE']);
}
/* Create root node */
$ldap->cd($dn);
$ldap->add(
array(
'cn' => $_SERVER['REMOTE_ADDR'],
'objectClass' => array('fdInventoryContent'),
'macAddress' => $macs,
'ipHostNumber' => $ips,
'fdInventoryVERSIONCLIENT' => $data['VERSIONCLIENT'],
)
);
}
$macs = array_values(array_unique($macs));
$ips = array_values(array_unique($ips));
/* Parse configuration file */
$config = new config(CONFIG_DIR.'/'.CONFIG_FILE, $BASE_DIR);
/* Set config server to default one */
$directory = $config->data['MAIN']['DEFAULT'];
if (!isset($config->data['LOCATIONS'][$directory])) {
$directory = key($config->data['LOCATIONS']);
}
$config->set_current($directory);
session::global_set('config', $config);
$ldap = $config->get_ldap_link();
$dn = 'cn='.$_SERVER['REMOTE_ADDR'].','.get_ou('inventoryRDN').$config->current['BASE'];
$ldap->cat($dn);
if ($ldap->count()) {
/* Emtpy the subtree */
$ldap->rmdir_recursive($dn);
if (!$ldap->success()) {
$msg.="error :".$ldap->get_error()."\n";
returnError('LDAP: '.$ldap->get_error());
}
unset($data['VERSIONCLIENT']);
unset($data['HARDWARE']['ARCHNAME']);
foreach ($data as $key => $objects) {
if (!is_numeric(key($objects))) {
$objects = array($objects);
}
foreach ($objects as $i => $object) {
$cn = strtolower($key).$i;
$ldap_attrs = array(
'cn' => $cn,
'objectClass' => 'fdInventory'.preg_replace('/_/', '', $key),
);
foreach ($object as $attr => $value) {
if (!(is_array($value) && empty($value))) {
$ldap_attrs['fdInventory'.preg_replace('/_/', '', $attr)] = $value;
}
}
$ldap->cd('cn='.$cn.','.$dn);
$ldap->add($ldap_attrs);
if (!$ldap->success()) {
$msg .= print_r($ldap_attrs, TRUE);
$msg .= "error :".$ldap->get_error()."\n";
} else {
/* Make sure branch is existing */
$ldap->cd($config->current['BASE']);
$ldap->create_missing_trees(get_ou('inventoryRDN').$config->current['BASE']);
}
/* Create root node */
$ldap->cd($dn);
$ldap->add(
array(
'cn' => $_SERVER['REMOTE_ADDR'],
'objectClass' => array('fdInventoryContent'),
'macAddress' => $macs,
'ipHostNumber' => $ips,
'fdInventoryVERSIONCLIENT' => $data['VERSIONCLIENT'],
)
);
if (!$ldap->success()) {
returnError('LDAP: '.$ldap->get_error());
}
unset($data['VERSIONCLIENT']);
unset($data['HARDWARE']['ARCHNAME']);
foreach ($data as $key => $objects) {
if (!is_numeric(key($objects))) {
$objects = array($objects);
}
foreach ($objects as $i => $object) {
$cn = strtolower($key).$i;
$ldap_attrs = array(
'cn' => $cn,
'objectClass' => 'fdInventory'.preg_replace('/_/', '', $key),
);
foreach ($object as $attr => $value) {
if (!(is_array($value) && empty($value))) {
$ldap_attrs['fdInventory'.preg_replace('/_/', '', $attr)] = $value;
}
}
}
if (!empty($msg)) {
$invFile = sprintf('/tmp/%s.xml', $_SERVER['REMOTE_ADDR']);
if (!file_put_contents($invFile, "$dn\n$msg\n")) {
error_log("Failed to write ");
$ldap->cd('cn='.$cn.','.$dn);
$ldap->add($ldap_attrs);
if (!$ldap->success()) {
// We cannot stop at every error, or one missing objectClass in the schema will stop inventory
error_log('LDAP: '.$ldap->get_error());
}
http_response_code(500);
print($msg);
exit();
}
}
}
switch($compressmode) {
case 'none':
print $reply;
break;
case 'gzcompress':
print gzcompress($reply);
break;
switch ($compressmode) {
case 'none':
print $reply;
break;
case 'gzencode':
print gzencode($reply);
break;
case 'gzcompress':
print gzcompress($reply);
break;
case 'gzdeflate':
print gzdeflate($reply);
break;
case 'gzencode':
print gzencode($reply);
break;
case 'gzdeflate':
print gzdeflate($reply);
break;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment