Reverse the logic when detecting tftpserver existence and path

- write a sentinel probe file to the known/possible distro tftp directories
 - try fetching it through tftp
 - if we manage to fetch the file, we have the correct path
 - remove sentinel probe file

When creating directories in tftpboot directory we should not set write permissions, using 0755 instead.
This commit is contained in:
dkgroot 2021-06-26 23:19:53 +00:00
parent 3a03815daf
commit 838ff633aa
3 changed files with 56 additions and 42 deletions

View file

@ -1,4 +1,4 @@
AS<?php <?php
if (!defined('FREEPBX_IS_AUTH')) { if (!defined('FREEPBX_IS_AUTH')) {
die_freepbx('No direct script access allowed'); die_freepbx('No direct script access allowed');
@ -887,32 +887,46 @@ function checkTftpServer() {
global $extconfigs; global $extconfigs;
global $thisInstaller; global $thisInstaller;
$confDir = $cnf_int->get('ASTETCDIR'); $confDir = $cnf_int->get('ASTETCDIR');
// TODO: add option to use external server $tftpRootPath = "";
$remoteFile = "TestFileXXX111.txt"; // should not exist
$thisInstaller->tftp_put_test_file();
// TODO: add option to use external server
$remoteFileName = ".sccp_manager_installer_probe_sentinel_temp".mt_rand(0, 9999999);
$remoteFileContent = "# This is a test file created by Sccp_Manager. It can be deleted without impact";
$possibleFtpDirs = array('/srv', '/srv/tftp','/var/lib/tftp', '/tftpboot'); $possibleFtpDirs = array('/srv', '/srv/tftp','/var/lib/tftp', '/tftpboot');
// write a couple of sentinels to different distro tftp locations in the filesystem
foreach ($possibleFtpDirs as $dirToTest) { foreach ($possibleFtpDirs as $dirToTest) {
if (file_exists("{$dirToTest}/{$remoteFile}")) { if (is_dir($dirToTest) && is_writable($dirToTest) && empty($tftpRootPath)) {
$tftpRootPath = $dirToTest; $tempFile = "${dirToTest}/{$remoteFileName}";
unlink("{$dirToTest}/{$remoteFile}"); $FH = fopen($tempFile, "w");
outn("<li>" . _("Found ftp root dir at {$dirToTest}") . "</li>"); if ($FH == null) {
if ($settingsFromDb['tftp_path']['data'] != $tftpRootPath) { continue;
$settingsToDb["tftp_path"] =array( 'keyword' => 'tftp_path', 'seq' => 2, 'type' => 0, 'data' => $tftpRootPath); }
// Need to set the new value here to pass to extconfigs below fwrite($FH, $remoteFileContent);
$settingsFromDb['tftp_path']['data'] = $tftpRootPath; fclose($FH);
// try to pull the written file through tftp.
// this way we can determine if tftp server is active, and what it's
// source directory is.
if ($remoteFileContent == $thisInstaller->tftpReadTestFile($remoteFileName)) {
$tftpRootPath = $dirToTest;
outn("<li>" . _("Found ftp root dir at {$tftpRootPath}") . "</li>");
if ($settingsFromDb['tftp_path']['data'] != $tftpRootPath) {
$settingsToDb["tftp_path"] = array( 'keyword' => 'tftp_path', 'seq' => 2, 'type' => 0, 'data' => $tftpRootPath);
// Need to set the new value here to pass to extconfigs below
$settingsFromDb['tftp_path']['data'] = $tftpRootPath;
}
}
// remove all sentinel file
if (file_exists($tempFile)) {
unlink($tempFile);
} }
break;
} }
} }
if (empty($tftpRootPath)) { if (empty($tftpRootPath)) {
die_freepbx(_("Either TFTP server is down or TFTP root is non standard. Please fix, refresh, and try again")); die_freepbx(_("Either TFTP server is down or TFTP root is non standard. Please fix, refresh, and try again"));
} }
if (!is_writeable($tftpRootPath)) {
die_freepbx(_("{$tftpRootPath} is not writable by user asterisk. Please fix, refresh and try again"));
}
$settingsToDb['asterisk_etc_path'] =array( 'keyword' => 'asterisk_etc_path', 'seq' => 20, 'type' => 0, 'data' => $confDir); $settingsToDb['asterisk_etc_path'] =array( 'keyword' => 'asterisk_etc_path', 'seq' => 20, 'type' => 0, 'data' => $confDir);
foreach ($settingsToDb as $settingToSave) { foreach ($settingsToDb as $settingToSave) {
@ -933,7 +947,6 @@ function checkTftpServer() {
die_freepbx(_("Error updating sccpsettings. $sql")); die_freepbx(_("Error updating sccpsettings. $sql"));
} }
} }
return; return;
} }

View file

@ -326,8 +326,8 @@ class extconfigs
$base_config[$key] = $adv_config[$value]; $base_config[$key] = $adv_config[$value];
// Save to sccpsettings // Save to sccpsettings
$settingsToDb[$key] =array( 'keyword' => $key, 'seq' => 20, 'type' => 0, 'data' => $adv_config[$value]); $settingsToDb[$key] =array( 'keyword' => $key, 'seq' => 20, 'type' => 0, 'data' => $adv_config[$value]);
if (!file_exists($base_config[$key])) { if (!is_dir($base_config[$key])) {
if (!mkdir($base_config[$key], 0777, true)) { if (!mkdir($base_config[$key], 0755, true)) {
die_freepbx(_('Error creating dir : ' . $base_config[$key])); die_freepbx(_('Error creating dir : ' . $base_config[$key]));
} }
} }

View file

@ -161,34 +161,35 @@ trait helperfunctions {
return $result; return $result;
} }
public function tftp_put_test_file() function tftpReadTestFile($remoteFileName)
{ {
// https://datatracker.ietf.org/doc/html/rfc1350 // https://datatracker.ietf.org/doc/html/rfc1350
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$host = "127.0.0.1"; // TODO: Should consider remote TFT Servers in future if ($socket) {
$host = "127.0.0.1"; // TODO: Should consider remote TFT Servers in future
$port = 69;
// create the WRQ request packet // create the RRQ request packet
$packet = chr(0) . chr(2) . "TestFileXXX111.txt" . chr(0) . 'netascii' . chr(0); $packet = chr(0) . chr(1) . $remoteFileName . chr(0) . 'netascii' . chr(0);
// UDP is connectionless, so we just send it. // UDP is connectionless, so we just send it.
socket_sendto($socket, $packet, strlen($packet), MSG_EOR, $host, 69); socket_sendto($socket, $packet, strlen($packet), MSG_EOR, $host, $port);
$buffer = ''; $buffer = null;
$port = ''; $port = "";
$ret = ''; $ret = "";
// Should now receive an ack packet // fetch file content
socket_recvfrom($socket, $buffer, 4, MSG_PEEK, $host, $port); $numbytes = socket_recvfrom($socket, $buffer, 84, MSG_WAITALL, $host, $port);
// unpack the returned buffer and discard the first two bytes
$pkt = unpack("n2/a*data", $buffer);
// Then should send our data packet socket_close($socket);
$packet = chr(0) . chr(3) . chr(0) . chr(1) . 'This is a test file created by Sccp_Manager. It can be deleted without any impact'; if ($numbytes) {
socket_sendto($socket, $packet, strlen($packet), MSG_EOR, $host, $port); return $pkt["data"];
}
// finally will recieve an ack packet }
socket_recvfrom($socket, $buffer, 4, MSG_PEEK, $host, $port); return false;
socket_close($socket);
return;
} }
public function initVarfromXml() { public function initVarfromXml() {