]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - html/cgi-bin/dns.cgi
Hardcode theme to ipfire
[ipfire-2.x.git] / html / cgi-bin / dns.cgi
index f4838b0464959e69cbb516e5dbae9ffa9f7907bd..7dc11358223774a6f2cab732c473afd7f95f7080 100755 (executable)
@@ -27,7 +27,8 @@ use IO::Socket;
 #use CGI::Carp 'fatalsToBrowser';
 
 require '/var/ipfire/general-functions.pl';
-require "${General::swroot}/geoip-functions.pl";
+require "${General::swroot}/location-functions.pl";
+require "${General::swroot}/ids-functions.pl";
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
 
@@ -51,15 +52,20 @@ unless (-f $settings_file) { system("touch $settings_file") };
 unless (-f $servers_file) { system("touch $servers_file") };
 
 # File which stores the ISP assigned DNS servers.
-my @ISP_nameserver_files = ( "${General::swroot}/dns/dns1", "${General::swroot}/dns/dns2" );
+my @ISP_nameserver_files = ( "/var/run/dns1", "/var/run/dns2" );
 
 # File which contains the ca-certificates.
 my $ca_certs_file = "/etc/ssl/certs/ca-bundle.crt";
 
+# Server which is used, to determine if the whole DNS system works properly.
+my $dns_test_server = "ping.ipfire.org";
+
+my $check_servers;
+
 my %color = ();
 my %mainsettings = ();
 &General::readhash("${General::swroot}/main/settings", \%mainsettings);
-&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color);
+&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
 
 &Header::showhttpheaders();
 &Header::getcgihash(\%cgiparams);
@@ -81,8 +87,24 @@ if ($cgiparams{'GENERAL'} eq $Lang::tr{'save'}) {
                $cgiparams{'ENABLE_SAFE_SEARCH'} = "off";
        }
 
-       # Store settings into settings file.
-       &General::writehash("$settings_file", \%cgiparams);
+       if ($cgiparams{'ENABLE_SAFE_SEARCH_YOUTUBE'} ne "on") {
+               $cgiparams{'ENABLE_SAFE_SEARCH_YOUTUBE'} = "off";
+       }
+
+       # Check if using ISP nameservers and TLS is enabled at the same time.
+       if (($cgiparams{'USE_ISP_NAMESERVERS'} eq "on") && ($cgiparams{'PROTO'} eq "TLS")) {
+               $errormessage = $Lang::tr{'dns isp nameservers and tls not allowed'}
+       }
+
+       # Check if there was an error.
+       if ( ! $errormessage) {
+
+               # Store settings into settings file.
+               &General::writehash("$settings_file", \%cgiparams);
+
+               # Call function to handle unbound restart, etc.
+               &_handle_unbound_and_more()
+       }
 }
 
 ###
@@ -95,8 +117,13 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
        # Read-in generic settings.
        &General::readhash("$settings_file", \%settings);
 
+       # Check if an IP-address has been given.
+       if ($cgiparams{"NAMESERVER"} eq "") {
+               $errormessage = "$Lang::tr{'dns no address given'}";
+       }
+
        # Check if the given DNS server is valid.
-       if(!&General::validip($cgiparams{"NAMESERVER"})) {
+       elsif(!&General::validip($cgiparams{"NAMESERVER"})) {
                $errormessage = "$Lang::tr{'invalid ip'}: $cgiparams{'NAMESERVER'}";
        }
 
@@ -112,16 +139,6 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
                }
        }
 
-       # Check the nameserver.
-       my $status = &check_nameserver("$cgiparams{'NAMESERVER'}", "ping.ipfire.org", "$settings{'PROTO'}", "$cgiparams{'TLS_HOSTNAME'}");
-
-       # Assign errormessage, if the nameserver does not support dnssec or any other kind of error happened.
-       if ($status eq "0") {
-               $errormessage = "$Lang::tr{'dns could not add server'} $Lang::tr{'dnssec not supported'}";
-       } elsif (($status ne "1") && ($status ne "2")) {
-               $errormessage = "$Lang::tr{'dns could not add server'} $status";
-       }
-
        # Go further if there was no error.
        if ( ! $errormessage) {
                # Check if a remark has been entered.
@@ -164,7 +181,7 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
 
                        # The first allowed id is 3 to keep space for
                        # possible ISP assigned DNS servers.
-                       if ($id le "2") {
+                       if ($id <= "2") {
                                $id = "3";
                        }
                }
@@ -174,6 +191,9 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
 
                # Write the changed hash to the config file.
                &General::writehasharray($servers_file, \%dns_servers);
+
+               # Call function to handle unbound restart, etc.
+               &_handle_unbound_and_more();
        } else {
                # Switch back to previous mode.
                $cgiparams{'SERVERS'} = $cgiparams{'MODE'};
@@ -210,6 +230,9 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
 
                # Write the changed hash back to the config file.
                &General::writehasharray($servers_file, \%dns_servers);
+
+               # Call function to handle unbound restart, etc.
+               &_handle_unbound_and_more();
        }
 
 ## Remove entry from DNS servers list.
@@ -228,10 +251,19 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
 
        # Write the changed hash to the config file.
        &General::writehasharray($servers_file, \%dns_servers);
+
+       # Call function to handle unbound restart, etc.
+       &_handle_unbound_and_more();
+
+## Handle request to check the servers.
+#
+} elsif ($cgiparams{'SERVERS'} eq $Lang::tr{'dns check servers'}) {
+       $check_servers = 1;
 }
 
 # Hash to store the generic DNS settings.
 my %settings = ();
+$settings{"ENABLE_SAFE_SEARCH_YOUTUBE"} = "on";
 
 # Read-in general DNS settings.
 &General::readhash("$settings_file", \%settings);
@@ -242,7 +274,7 @@ my %dns_servers = ();
 # Read-in config file.
 &General::readhasharray("$servers_file", \%dns_servers);
 
-&Header::openpage($Lang::tr{'dns'}, 1, '');
+&Header::openpage($Lang::tr{'dns title'}, 1, '');
 
 &Header::openbigbox('100%', 'left', '', $errormessage);
 
@@ -283,6 +315,10 @@ $checked{'ENABLE_SAFE_SEARCH'}{'off'} = '';
 $checked{'ENABLE_SAFE_SEARCH'}{'on'} = '';
 $checked{'ENABLE_SAFE_SEARCH'}{$settings{'ENABLE_SAFE_SEARCH'}} = "checked='checked'";
 
+$checked{'ENABLE_SAFE_SEARCH_YOUTUBE'}{'off'} = '';
+$checked{'ENABLE_SAFE_SEARCH_YOUTUBE'}{'on'} = '';
+$checked{'ENABLE_SAFE_SEARCH_YOUTUBE'}{$settings{'ENABLE_SAFE_SEARCH_YOUTUBE'}} = "checked='checked'";
+
 $selected{'PROTO'}{'UDP'} = '';
 $selected{'PROTO'}{'TLS'} = '';
 $selected{'PROTO'}{'TCP'} = '';
@@ -354,6 +390,16 @@ sub show_general_dns_configuration () {
                                </td>
                        </tr>
 
+                       <tr>
+                               <td width="33%">
+                                       &raquo; $Lang::tr{'dns enable safe-search youtube'}
+                               </td>
+
+                               <td>
+                                       <input type="checkbox" name="ENABLE_SAFE_SEARCH_YOUTUBE" $checked{'ENABLE_SAFE_SEARCH_YOUTUBE'}{'on'}>
+                               </td>
+                       </tr>
+
                        <tr>
                                <td colspan="2">
                                        <br>
@@ -389,9 +435,80 @@ END
 # Section to display the configured and used DNS servers.
 #
 sub show_nameservers () {
-       &Header::openbox('100%', 'center', "DNS-Servers");
+       &Header::openbox('100%', 'center', "$Lang::tr{'dns servers'}");
+
+       # Determine if we are running in recursor mode
+       my $recursor = 0;
+       my $unbound_forward = qx(unbound-control forward);
+       if ($unbound_forward =~ m/^off/) {
+               $recursor = 1;
+       }
+
+       my $dns_status_string;
+       my $dns_status_col;
+       my $dns_working;
+
+
+       # Test if the DNS system is working.
+       #
+       # Simple send a request to unbound and check if it can resolve the
+       # DNS test server.
+       my $dns_status_ret = &check_nameserver("127.0.0.1", "$dns_test_server", "UDP", undef, "+timeout=5", "+retry=0");
+
+       if ($dns_status_ret eq "2") {
+               $dns_status_string = "$Lang::tr{'working'}";
+               $dns_status_col = "${Header::colourgreen}";
+               $dns_working = 1;
+       } else {
+               $dns_status_string = "$Lang::tr{'broken'}";
+               $dns_status_col = "${Header::colourred}";
+       }
+
+       if ($recursor) {
+               $dns_status_string .= " (" . $Lang::tr{'dns recursor mode'} . ")";
+       }
+
+       print <<END;
+               <table width='100%'>
+                       <tr>
+                               <td>
+                                       <strong>$Lang::tr{'status'}:&nbsp;</strong>
+                                       <strong><font color='$dns_status_col'>$dns_status_string</font></strong>
+                               </td>
+                       </tr>
+               </table>
+END
+
+       # Check the usage of ISP assigned nameservers is enabled.
+       my $id = 1;
+
+       # Loop through the array which stores the files.
+       foreach my $file (@ISP_nameserver_files) {
+               # Grab the address of the nameserver.
+               my $address = &General::grab_address_from_file($file);
+
+               # Check if we got an address.
+               if ($address) {
+                       # Add the address to the hash of nameservers.
+                       $dns_servers{$id} = [ "$address", "none",
+                               ($settings{'USE_ISP_NAMESERVERS'} eq "on") ? "enabled" : "disabled",
+                               "$Lang::tr{'dns isp assigned nameserver'}" ];
+
+                       # Increase id by one.
+                       $id++;
+               }
+       }
+
+       # Check some DNS servers have been configured. In this case
+       # the hash contains at least one key.
+       my $server_amount;
+       if (keys %dns_servers) {
+               # Sort the keys by their ID and store them in an array.
+               my @keys = sort { $a <=> $b } keys %dns_servers;
+
+               print <<END;
+               <br>
 
-print <<END;
                <table class="tbl" width='100%'>
                        <tr>
                                <td align="center">
@@ -409,10 +526,18 @@ print <<END;
                                <td align="center">
                                        <strong>$Lang::tr{'remark'}</strong>
                                </td>
+END
 
+               # Check if the status should be displayed.
+               if ($check_servers) {
+                       print <<END;
                                <td align="center">
                                        <strong>$Lang::tr{'status'}</strong>
                                </td>
+END
+               }
+
+               print <<END;
 
                                <td align="center" colspan="3">
                                        <strong>$Lang::tr{'action'}</strong>
@@ -420,33 +545,6 @@ print <<END;
                        </tr>
 END
 
-               # Check the usage of ISP assigned nameservers is enabled.
-               if ($settings{'USE_ISP_NAMESERVERS'} eq "on") {
-                       my $id="1";
-
-                       # Loop through the array which stores the files.
-                       foreach my $file (@ISP_nameserver_files) {
-                               # Grab the address of the nameserver.
-                               my $address = &grab_address_from_file($file);
-
-                               # Check if we got an address.
-                               if ($address) {
-                                       # Add the address to the hash of nameservers.
-                                       $dns_servers{$id} = [ "$address", "none", "enabled", "$Lang::tr{'dns isp assigned nameserver'}" ];
-
-                                       # Increase id by one.
-                                       $id++;
-                               }
-                       }
-               }
-
-               # Check some DNS servers have been configured. In this case
-               # the hash contains at least one key.
-               my $server_amount;
-               if (keys %dns_servers) {
-                       # Sort the keys by their ID and store them in an array.
-                       my @keys = sort { $a <=> $b } keys %dns_servers;
-
                        # Loop through all entries of the array/hash.
                        foreach my $id (@keys) {
                                # Inrease server_amount.
@@ -483,11 +581,11 @@ END
                                my $status_colour;
 
                                # Only grab the status if the nameserver is enabled.
-                               if ($enabled eq "enabled") {
+                               if (($check_servers) && ($enabled eq "enabled")) {
                                        $status = &check_nameserver("$nameserver", "ping.ipfire.org", "$settings{'PROTO'}", "$tls_hostname");
                                }
 
-                               if (!$status) {
+                               if (!defined $status) {
                                        $status_short = "$Lang::tr{'disabled'}";
 
                                # DNSSEC Not supported
@@ -515,14 +613,24 @@ END
                                        $status_colour = ${Header::colourred};
                                }
 
-                               # collect more information about name server (rDNS, GeoIP country code)
-                               my $ccode = &GeoIP::lookup($nameserver);
-                               my $flag_icon = &GeoIP::get_flag_icon($ccode);
+                               # collect more information about name server (rDNS, country code)
+                               my $ccode = &Location::Functions::lookup_country_code($nameserver);
+                               my $flag_icon = &Location::Functions::get_flag_icon($ccode);
 
-                               my $iaddr = inet_aton($nameserver);
-                               my $rdns = gethostbyaddr($iaddr, AF_INET);
+                               my $rdns;
 
-                               if (!$rdns) { $rdns = $Lang::tr{'lookup failed'}; }
+                               # Only do the reverse lookup if the system is online.
+                               if ($dns_working) {
+                                       my $iaddr = inet_aton($nameserver);
+                                       $rdns = gethostbyaddr($iaddr, AF_INET);
+                               }
+
+                               if (!$rdns) { $rdns = $Lang::tr{'ptr lookup failed'}; }
+
+                               # Mark ISP name servers as disabled
+                               if ($id <= 2 && $enabled eq "disabled") {
+                                       $nameserver = "<del>$nameserver</del>";
+                               }
 
 print <<END;
                        <tr>
@@ -541,18 +649,24 @@ print <<END;
                                <td align="center" $col>
                                        $remark
                                </td>
-
-                               <td align="center" $col>
-                                       <strong><font color="$status_colour"><abbr title="$status_message">$status_short</abbr></font></strong>
-                               </td>
 END
 ;
+                               # Display server status if requested.
+                               if ($check_servers) {
+print <<END
+                                       <td align="center" $col>
+                                               <strong><font color="$status_colour"><abbr title="$status_message">$status_short</abbr></font></strong>
+                                       </td>
+END
+;
+                               }
+
                                # Check if the id is greater than "2".
                                #
                                # Nameservers with an ID's of one or two are ISP assigned,
                                # and we cannot perform any actions on them, so hide the tools for
                                # them.
-                               if ($id gt "2") {
+                               if ($id > 2) {
 
 print <<END;
                                        <td align='center' width='5%' $col>
@@ -595,7 +709,7 @@ END
                print"<table width='100%'>\n";
 
                # Check if the usage of the ISP nameservers is enabled and there are more than 2 servers.
-               if (($settings{'USE_ISP_NAMESERVERS'} eq "on") && ($server_amount gt "2")) {
+               if (($settings{'USE_ISP_NAMESERVERS'} eq "on") && ($server_amount > 2)) {
 print <<END;
                        <tr>
                                <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
@@ -614,31 +728,25 @@ END
 print <<END;
                        <tr>
                                <form method="post" action="$ENV{'SCRIPT_NAME'}">
-                                       <td colspan="9" align="right"><input type="submit" name="SERVERS" value="$Lang::tr{'add'}"></td>
+                                       <td colspan="9" align="right">
+                                               <input type="submit" name="SERVERS" value="$Lang::tr{'add'}">
+                                               <input type="submit" name="SERVERS" value="$Lang::tr{'dns check servers'}">
+                                       </td>
                                </form>
                        </tr>
                </table>
 END
 ;
-
                } else {
-print <<END;
+                       print <<END;
                <table width="100%">
-                       <tr>
-                               <td colspan="6" align="center">
-                                       <br>$Lang::tr{'guardian no entries'}<br>
-                               </td>
-                       </tr>
-
                        <tr>
                                <form method="post" action="$ENV{'SCRIPT_NAME'}">
                                        <td colspan="6" align="right"><input type="submit" name="SERVERS" value="$Lang::tr{'add'}"></td>
                                </form>
                        </tr>
                </table>
-
 END
-;
                }
 
        &Header::closebox();
@@ -673,6 +781,13 @@ sub show_add_edit_nameserver() {
                &Header::openbox('100%', 'left', $Lang::tr{'dnsforward add a new entry'});
        }
 
+       my $tls_required_image;
+
+       # If the protocol is TLS, dispaly the required image.
+       if ($settings{'PROTO'} eq "TLS") {
+               $tls_required_image = "<img src='/blob.gif' alt='*'>";
+       }
+
        # Add hidden input to store the mode.
        print "<input type='hidden' name='MODE' value='$cgiparams{'SERVERS'}'>\n";
 
@@ -682,20 +797,13 @@ print <<END
                        <td width='20%' class='base'>$Lang::tr{'ip address'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
                        <td><input type='text' name='NAMESERVER' value='$cgiparams{"NAMESERVER"}' size='24' /></td>
                </tr>
-END
-;
-       # If the protocol is TLS, display the TLS hostname input.
-       if ($settings{'PROTO'} eq "TLS") {
-print <<END
+
+
                <tr>
-                       <td width='20%' class='base'>$Lang::tr{'dns tls hostname'}:&nbsp;<img src='/blob.gif' alt='*'></td>
+                       <td width='20%' class='base'>$Lang::tr{'dns tls hostname'}:&nbsp;$tls_required_image</td>
                        <td><input type='text' name='TLS_HOSTNAME' value='$cgiparams{'TLS_HOSTNAME'}' size='24'></td>
                </tr>
-END
-;
-       }
 
-print <<END
 
                <tr>
                        <td width ='20%' class='base'>$Lang::tr{'remark'}:</td>
@@ -724,47 +832,45 @@ END
        &Header::closebox();
 }
 
-# Tiny function to grab an IP-address of a given file.
-sub grab_address_from_file($) {
-       my ($file) = @_;
-
-       my $address;
-
-       # Check if the given file exists.
-       if(-f $file) {
-               # Open the file for reading.
-               open(FILE, $file) or die "Could not read from $file. $!\n";
+# Private function to handle the restart of unbound and more.
+sub _handle_unbound_and_more () {
+       # Check if the IDS is running.
+       if(&IDS::ids_is_running()) {
+               # Re-generate the file which contains the DNS Server
+               # details.
+               &IDS::generate_dns_servers_file();
 
-               # Read the address from the file.
-               $address = <FILE>;
-
-               # Close filehandle.
-               close(FILE);
-
-               # Remove newlines.
-               chomp($address);
-
-               # Check if the obtained address is valid.
-               if (&General::validip($address)) {
-                       # Return the address.
-                       return $address;
-               }
+               # Call suricatactrl to perform a reload.
+               &IDS::call_suricatactrl("restart");
        }
+       # Restart unbound
+       system('/usr/local/bin/unboundctrl reload >/dev/null');
+}
 
-       # Return nothing.
-       return;
+# Check if the system is online (RED is connected).
+sub red_is_active () {
+       # Check if the "active" file is present.
+       if ( -f "${General::swroot}/red/active") {
+               # Return "1" - True.
+               return 1;
+       } else {
+               # Return nothing - False.
+               return;
+       }
 }
 
 # Function to check a given nameserver against propper work.
-sub check_nameserver($$$$) {
-       my ($nameserver, $record, $proto, $tls_hostname) = @_;
+sub check_nameserver($$$$$) {
+       my ($nameserver, $record, $proto, $tls_hostname, @args) = @_;
 
-       # Timout for the query in seconds.
-       my $timeout;
-       my $retry = "+retry=0";
+       # Check if the system is online.
+       unless (&red_is_active()) {
+               return "$Lang::tr{'system is offline'}";
+       }
 
        # Default values.
-       my @command = ("kdig", "$timeout", "$retry", "+dnssec");
+       my @command = ("kdig", "+dnssec",
+               "+bufsize=1232", @args);
 
        # Handle different protols.
        if ($proto eq "TCP") {
@@ -798,10 +904,6 @@ sub check_nameserver($$$$) {
         my $output = join("", @output);
 
        my $status = 0;
-       if ($output =~ m/WARNING: (.*)/) {
-               return $1;
-
-       }
 
        if ($output =~ m/status: (\w+)/) {
                $status = ($1 eq "NOERROR");
@@ -809,6 +911,18 @@ sub check_nameserver($$$$) {
                if (!$status) {
                        return -1;
                }
+       } else {
+               my $warning;
+
+               while ($output =~ m/WARNING: (.*)/g) {
+                       # Add the current grabbed warning to the warning string.
+                       $warning .= "$1\; ";
+               }
+
+               # Return the warning string, if we grabbed at least one.
+               if ($warning) {
+                       return $warning;
+               }
        }
 
        my @flags = ();
@@ -817,7 +931,7 @@ sub check_nameserver($$$$) {
        }
 
        my $aware = ($output =~ m/RRSIG/);
-       my $validating = ("ad;" ~~ @flags);
+       my $validating = (grep(/ad;/, @flags));
 
        return $aware + $validating;
 }