Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pfSense-pkg-tftpd package improvements #262

Merged
merged 18 commits into from
Jan 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ftp/pfSense-pkg-tftpd/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# $FreeBSD$

PORTNAME= pfSense-pkg-tftpd
PORTVERSION= 0.1.2
PORTVERSION= 0.1.3
CATEGORIES= ftp
MASTER_SITES= # empty
DISTFILES= # empty
Expand All @@ -25,12 +25,15 @@ do-extract:

do-install:
${MKDIR} ${STAGEDIR}${PREFIX}/pkg
${MKDIR} ${STAGEDIR}${PREFIX}/www
${MKDIR} ${STAGEDIR}/etc/inc/priv
${MKDIR} ${STAGEDIR}${DATADIR}
${INSTALL_DATA} -m 0644 ${FILESDIR}${PREFIX}/pkg/tftpd.xml \
${STAGEDIR}${PREFIX}/pkg
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/tftpd.inc \
${STAGEDIR}${PREFIX}/pkg
${INSTALL_DATA} -m 0755 ${FILESDIR}${PREFIX}/www/tftp_files.php \
${STAGEDIR}${PREFIX}/www
${INSTALL_DATA} ${FILESDIR}/etc/inc/priv/tftpd.priv.inc \
${STAGEDIR}/etc/inc/priv
${INSTALL_DATA} ${FILESDIR}${DATADIR}/info.xml \
Expand Down
12 changes: 7 additions & 5 deletions ftp/pfSense-pkg-tftpd/files/etc/inc/priv/tftpd.priv.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* tftpd.priv.inc
*
* part of pfSense (https://www.pfsense.org)
* Copyright (c) 2015-2017 Rubicon Communications, LLC (Netgate)
* Copyright (c) 2016 Stefan Seidel
* All rights reserved.
*
Expand All @@ -21,11 +22,12 @@

global $priv_list;

$priv_list['page-system-tftpd'] = array();
$priv_list['page-system-tftpd']['name'] = "WebCfg - System: tftpd package";
$priv_list['page-system-tftpd']['descr'] = "Allow access to tftpd package GUI";
$priv_list['page-system-tftpd']['match'] = array();
$priv_list['page-services-tftpd'] = array();
$priv_list['page-services-tftpd']['name'] = "WebCfg - Services: tftpd package";
$priv_list['page-services-tftpd']['descr'] = "Allow access to tftpd package GUI";
$priv_list['page-services-tftpd']['match'] = array();

$priv_list['page-system-tftpd']['match'][] = "pkg_edit.php?xml=tftpd.xml*";
$priv_list['page-services-tftpd']['match'][] = "pkg_edit.php?xml=tftpd.xml*";
$priv_list['page-services-tftpd']['match'][] = "tftp_files.php*";

?>
128 changes: 109 additions & 19 deletions ftp/pfSense-pkg-tftpd/files/usr/local/pkg/tftpd.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* tftpd.inc
*
* part of pfSense (https://www.pfsense.org)
* Copyright (c) 2015-2017 Rubicon Communications, LLC (Netgate)
* Copyright (c) 2016 Stefan Seidel
* All rights reserved.
*
Expand All @@ -19,25 +20,83 @@
* limitations under the License.
*/

if (!function_exists("filter_configure")) {
require_once("filter.inc");
}
require_once("globals.inc");
require_once("interfaces.inc");
require_once("notices.inc");
require_once("pfsense-utils.inc");
require_once("service-utils.inc");
require_once("util.inc");

/* Define some locations */
define('BACKUP_DIR', '/root/backup');
define('BACKUP_FILENAME', 'tftp.bak.tgz');
define('BACKUP_PATH', BACKUP_DIR . '/' . BACKUP_FILENAME);
/* Change FILES_DIR below if you really need TFTP files directory elsewhere.
* Note: Such modifications are completely unsupported!
*/
define('FILES_DIR', '/tftpboot');

/* Create backup of the TFTP server directory */
function tftp_create_backup($trigger_download = false) {
conf_mount_rw();
safe_mkdir(BACKUP_DIR);
if (mwexec("/usr/bin/tar -czC / -f " . BACKUP_PATH . " " . FILES_DIR) || !file_exists(BACKUP_PATH)) {
header("Location: tftp_files.php?savemsg=Backup+failed.&result=alert-warning");
} elseif ($trigger_download == false) {
header("Location: tftp_files.php?savemsg=Backup+has+been+created");
}
conf_mount_ro();
}

/* Restore backup of the TFTP server directory */
function tftp_restore_backup() {
if (file_exists(BACKUP_PATH)) {
conf_mount_rw();
mwexec("/usr/bin/tar -xpzC / -f " . BACKUP_PATH);
header("Location: tftp_files.php?savemsg=Backup+has+been+restored.");
conf_mount_ro();
} else {
header("Location: tftp_files.php?savemsg=Restore+failed.+Backup+file+not+found.&result=alert-warning");
}
}

/* Only allow to download files under the FILES_DIR */
function tftp_filesdir_bounds_check($filename, $error_msg) {
$basedirlength = strlen(FILES_DIR);
if (substr($filename, 0, $basedirlength) !== FILES_DIR) {
log_error("[tftpd] {$error_msg}");
file_notice("tftpd", "{$error_msg}", "Packages");
return false;
} else {
return true;
}
}

function install_package_tftpd() {
safe_mkdir("/tftpboot");
safe_mkdir(FILES_DIR);
unlink_if_exists("/usr/local/etc/rc.d/tftpd");
upgrade_config_tftpd();
}

function deinstall_package_tftpd() {
@rmdir("/tftpboot");
// Will only get removed when empty
@rmdir(FILES_DIR);
}

function upgrade_config_tftpd() {
// FILES_DIR is not configurable any more
if (is_array($config['installedpackages']['tftpd'])) {
$tftpd_conf = &$config['installedpackages']['tftpd']['config'][0];
} else {
$tftpd_conf = array();
}
if (!empty($tftpd_conf['datadir']) && $tftpd_conf['datadir'] !== FILES_DIR) {
file_notice("tftpd", "Please, move your TFTP server files from {$tftpd_conf['datadir']} to /tftpboot", "Packages");
unset($config['installedpackages']['tftpd']['config'][0]['datadir']);
}
}

function sync_package_tftpd() {
global $config;
global $g, $config;

conf_mount_rw();

Expand All @@ -56,17 +115,37 @@ function sync_package_tftpd() {
unlink_if_exists('/usr/local/etc/rc.d/tftpd.sh');
return;
}

$datadir = $tftpd_conf['datadir'];

if (!is_dir($datadir)) {
log_error("TFTP files directory {$datadir} does not exist.");
return;
}

// Root directory
$datadir = FILES_DIR;

// TFTP Server Bind IP
if (!empty($tftpd_conf['tftpd_ip'])) {
$address = $tftpd_conf['tftpd_ip'];
if (is_ipaddrv6($address)) {
$address = "-a [{$address}]";
} elseif (is_ipaddrv4($address)) {
$address = "-a {$address}";
} else {
$address = "";
}
}

$pidfile = "{$g['varrun_path']}/tftpd-hpa.pid";

// IPv4 Only?
if ($tftpd_conf['tftpd_ipv4only'] == "on") {
$options = "-4";
}

// Max Block Size
if (!empty($tftpd_conf['tftpd_blocksize'])) {
$options .= " -B " . escapeshellarg($tftpd_conf['tftpd_blocksize']);
}

write_rcfile(array(
"file" => "tftpd.sh",
"start" => "/usr/local/libexec/in.tftpd -l -s {$datadir}",
"start" => "/usr/local/libexec/in.tftpd -l -s {$datadir} {$address} -P {$pidfile} {$options}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, re: escapeshellarg(), except for $options which should be OK already

"stop" => "/usr/bin/killall in.tftpd"
)
);
Expand All @@ -82,13 +161,24 @@ function sync_package_tftpd() {
}

conf_mount_ro();

filter_configure();
}

function validate_form_tftpd($post, &$input_errors) {
if ($post['datadir'] && !is_dir($post['datadir'])) {
$input_errors[] = 'Directory for files does not exist!';
if ($post['tftpd_ip']) {
if ($post['tftpd_ipv4only'] && !is_ipaddrv4($post['tftpd_ip'])) {
$input_errors[] = 'TFTP Server Bind IP must be a valid IPv4 address!';
} elseif (!is_ipaddr($post['tftpd_ip'])) {
$input_errors[] = 'TFTP Server Bind IP must be a valid IP address!';
}
if (!is_ipaddr_configured($post['tftpd_ip'])) {
$input_errors[] = "{$post['tftpd_ip']} TFTP Server Bind IP must be a valid, locally configured IP address!";
}
}

if ($post['tftpd_blocksize']) {
if (!is_numericint($post['tftpd_blocksize']) || ($post['tftpd_blocksize'] < 512) || ($post['tftpd_blocksize'] > 65464)) {
$input_errors[] = 'Max Block Size must be an integer with a permitted range from 512 to 65464!';
}
}
}

Expand Down
55 changes: 46 additions & 9 deletions ftp/pfSense-pkg-tftpd/files/usr/local/pkg/tftpd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* tftpd.xml
*
* part of pfSense (https://www.pfsense.org)
* Copyright (c) 2015-2017 Rubicon Communications, LLC (Netgate)
* Copyright (c) 2016 Stefan Seidel
* All rights reserved.
*
Expand All @@ -30,7 +31,7 @@
<include_file>/usr/local/pkg/tftpd.inc</include_file>
<aftersaveredirect>/pkg_edit.php?xml=tftpd.xml</aftersaveredirect>
<menu>
<name>tftpd</name>
<name>TFTP Server</name>
<section>Services</section>
<url>/pkg_edit.php?xml=tftpd.xml</url>
</menu>
Expand All @@ -40,19 +41,58 @@
<executable>in.tftpd</executable>
<description>TFTP daemon</description>
</service>
<tabs>
<tab>
<text>Settings</text>
<url>/pkg_edit.php?xml=tftpd.xml</url>
<active/>
</tab>
<tab>
<text>Files</text>
<url>/tftp_files.php</url>
</tab>
</tabs>
<fields>
<field>
<fielddescr>Enable TFTP service</fielddescr>
<fieldname>tftpd_enable</fieldname>
<description>Enable the TFTP service?</description>
<description>Check to enable the TFTP service.</description>
<type>checkbox</type>
</field>
<field>
<fielddescr>TFTP Server Bind IP</fielddescr>
<fieldname>tftpd_ip</fieldname>
<description>
<![CDATA[
By default, TFTP server will listen on all local addresses. If this is not desired,
you can restrict this to a specific local address.<br/>
<span class="text-danger">This must be a valid, locally configured IP address.</span>
]]>
</description>
<type>input</type>
</field>
<field>
<fielddescr>IPv4 Only</fielddescr>
<fieldname>tftpd_ipv4only</fieldname>
<description>Check to allow clients to connect with IPv4 only.</description>
<type>checkbox</type>
</field>
<field>
<fielddescr>Directory for files</fielddescr>
<fieldname>datadir</fieldname>
<description>Enter the directory path to the files that the TFTP server should serve. The directory must exist. Default: /tftpboot</description>
<fielddescr>Max Block Size</fielddescr>
<fieldname>tftpd_blocksize</fieldname>
<description>
<![CDATA[
Specifies the maximum permitted block size. <span class="text-info">The permitted range is from 512 to 65464.</span>
<div class="infoblock">
Some embedded clients request large block sizes and yet do not handle fragmented packets
correctly; for these clients, it is recommended to set this value to the smallest MTU
on your network minus 32 bytes (20 bytes for IP, 8 for UDP, and 4 for TFTP; less if you
use IP options on your network.)<br/>
For example, on a standard Ethernet (MTU 1500) a value of 1468 is reasonable.
</div>
]]>
</description>
<type>input</type>
<default_value>/tftpboot</default_value>
</field>
</fields>
<custom_php_install_command>
Expand All @@ -61,9 +101,6 @@
<custom_php_deinstall_command>
deinstall_package_tftpd();
</custom_php_deinstall_command>
<custom_add_php_command>
sync_package_tftpd();
</custom_add_php_command>
<custom_php_resync_config_command>
sync_package_tftpd();
</custom_php_resync_config_command>
Expand Down
Loading