diff --git a/src/etc/inc/services.inc b/src/etc/inc/services.inc index 6c9304a95b..2046a390eb 100644 --- a/src/etc/inc/services.inc +++ b/src/etc/inc/services.inc @@ -2226,6 +2226,66 @@ function services_unbound_configure($restart_dhcp = true) { } } + $python_mode = false; + if (isset($config['unbound']['python']) && !empty($config['unbound']['python_script'])) { + $python_mode = true; + } + + /* Include any additional functions as defined by python script include file */ + if (file_exists("{$g['unbound_chroot_path']}/{$config['unbound']['python_script']}_include.inc")) { + exec("/usr/local/bin/php -l " . escapeshellarg("{$g['unbound_chroot_path']}/{$config['unbound']['python_script']}_include.inc") + . " 2>&1", $py_output, $py_retval); + if ($py_retval == 0) { + require_once("{$g['unbound_chroot_path']}/{$config['unbound']['python_script']}_include.inc"); + } + } + + /* DNS Resolver python integration */ + $base_folder = '/usr/local'; + foreach (array('/bin', '/lib') as $dir) { + $validate = exec("/sbin/mount | /usr/bin/grep " . escapeshellarg("{$g['unbound_chroot_path']}{$base_folder}{$dir} (nullfs") . " 2>&1"); + if ($python_mode) { + + // Add DNS Resolver python integration + if (empty($validate)) { + if (!is_dir("{$g['unbound_chroot_path']}{$base_folder}{$dir}")) { + safe_mkdir("{$g['unbound_chroot_path']}{$base_folder}{$dir}"); + } + $output = $retval = ''; + exec("/sbin/mount_nullfs -o ro " . escapeshellarg("/usr/local{$dir}") . ' ' + . escapeshellarg("{$g['unbound_chroot_path']}{$base_folder}{$dir}") . " 2>&1", $output, $retval); + + // Disable Unbound python on mount failure + if ($retval != 0) { + $config['unbound']['python'] = ''; + $log_msg = "[Unbound-pymod]: Disabling Unbound python due to failed mount"; + write_config($log_msg); + log_error($log_msg); + } + } + } + + // Remove DNS Resolver python integration + elseif (!empty($validate)) { + exec("/sbin/umount -t nullfs " . escapeshellarg("{$g['unbound_chroot_path']}{$base_folder}{$dir}") . " 2>&1", $output, $retval); + if ($retval == 0) { + foreach (array( "/usr/local{$dir}", '/usr/local', '/usr') as $folder) { + if (!empty($g['unbound_chroot_path']) && $g['unbound_chroot_path'] != '/' && is_dir("{$g['unbound_chroot_path']}{$folder}")) { + @rmdir(escapeshellarg("{$g['unbound_chroot_path']}{$folder}")); + } + + // Delete remaining subfolders on next loop + if ($dir == '/bin') { + break; + } + } + } + else { + log_error("[Unbound-pymod]: Failed to unmount!"); + } + } + } + if (platform_booting()) { echo gettext("Starting DNS Resolver..."); } else { diff --git a/src/etc/inc/unbound.inc b/src/etc/inc/unbound.inc index c0d0a4dcd1..8bd39e6cfd 100644 --- a/src/etc/inc/unbound.inc +++ b/src/etc/inc/unbound.inc @@ -116,6 +116,17 @@ function test_unbound_config($unboundcfg, &$output) { unbound_remote_control_setup($cfgsubdir); do_as_unbound_user("unbound-anchor", $cfgsubdir); + // Copy the Python files to the test folder + if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script'])) { + $python_files = glob("{$g['unbound_chroot_path']}/{$unboundcfg['python_script']}.*"); + if (is_array($python_files)) { + foreach ($python_files as $file) { + $file = pathinfo($file, PATHINFO_BASENAME); + @copy("{$g['unbound_chroot_path']}/{$file}", "{$cfgdir}/{$file}"); + } + } + } + $rv = 0; exec("/usr/local/sbin/unbound-checkconf {$cfgdir}/unbound.conf 2>&1", $output, $rv); @@ -157,14 +168,26 @@ function unbound_generate_config_text($unboundcfg = NULL, $cfgsubdir = "") { // Setup optimization $optimization = unbound_optimization(); + $module_config = ''; + + // Setup Python module (pre validator) + if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script']) && $unboundcfg['python_order'] == 'pre_validator') { + $module_config .= 'python '; + } + // Setup DNSSEC support if (isset($unboundcfg['dnssec'])) { - $module_config = "validator iterator"; + $module_config .= 'validator '; $anchor_file = "auto-trust-anchor-file: {$g['unbound_chroot_path']}{$cfgsubdir}/root.key"; - } else { - $module_config = "iterator"; } + // Setup Python module (post validator) + if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script']) && $unboundcfg['python_order'] == 'post_validator') { + $module_config .= 'python '; + } + + $module_config .= 'iterator'; + // Setup DNS Rebinding if (!isset($config['system']['webgui']['nodnsrebindcheck'])) { // Private-addresses for DNS Rebinding @@ -392,6 +415,15 @@ EOD; } } + $python_module = ''; + if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script'])) { + $python_path = ''; + if (!empty($cfgsubdir)) { + $python_path = "{$g['unbound_chroot_path']}{$cfgsubdir}/"; + } + $python_module = "\n# Python Module\npython:\npython-script: {$python_path}{$unboundcfg['python_script']}.py"; + } + $unboundconf = <<addInput(new Form_Checkbox( $pconfig['dnssec'] )); +$section->addInput(new Form_Checkbox( + 'python', + 'Python Module', + 'Enable Python Module', + $pconfig['python'] +))->setHelp('Enable the Python Module.'); + +$python_files = glob("{$g['unbound_chroot_path']}/*.py"); +$python_scripts = array(); +if (!empty($python_files)) { + foreach ($python_files as $file) { + $file = pathinfo($file, PATHINFO_FILENAME); + $python_scripts[$file] = $file; + } +} +else { + $python_scripts = array('' => 'No Python Module scripts found'); +} + +$section->addInput(new Form_Select( + 'python_order', + 'Python Module Order', + $pconfig['python_order'], + [ 'pre_validator' => 'Pre Validator', 'post_validator' => 'Post Validator' ] +))->setHelp('Select the Python Module ordering.'); + +$section->addInput(new Form_Select( + 'python_script', + 'Python Module Script', + $pconfig['python_script'], + $python_scripts +))->setHelp('Select the Python module script to utilize.'); + $section->addInput(new Form_Checkbox( 'forwarding', 'DNS Query Forwarding', @@ -508,6 +560,17 @@ events.push(function() { hideGeneral(); show_advcustom(true); + // When the Python Module 'enable' is clicked, disable/enable the Python Module options + function show_python_script() { + var python = $('#python').prop('checked'); + hideInput('python_order', !python); + hideInput('python_script', !python); + } + show_python_script(); + $('#python').click(function () { + show_python_script(); + }); + }); //]]>