Testing DNS Redirect code snippet

Hi Jon,

very good - this code must be really stable, make sure you break it! :sunglasses:

But I still haven’t found a way to execute /etc/rc.d/init.d/firewall restart via GUI.

It seems that the rights available via GUI are - per design - not sufficient to rewrite the settings AND execute a root script.

Best,
Matthias

Curious - What is the code behind Apply changes? Will that help?

Hi Jon,

in detail, its this piece of code (optionsfw.cgi, line 72-95) which does the ‘Save and Restart’:

if ($settings{'ACTION'} eq $Lang::tr{'fw settings save and restart'}) {
if ($settings{'defpol'} ne '1'){
	$errormessage .= $Lang::tr{'new optionsfw later'};
	&General::writehash($filename, \%settings);             # Save good settings
	system("/usr/local/bin/firewallctrl");
}else{
	if ($settings{'POLICY'} ne ''){
		$fwdfwsettings{'POLICY'} = $settings{'POLICY'};
	}
	if ($settings{'POLICY1'} ne ''){
		$fwdfwsettings{'POLICY1'} = $settings{'POLICY1'};
	}
	my $MODE = $fwdfwsettings{'POLICY'};
	my $MODE1 = $fwdfwsettings{'POLICY1'};
	%fwdfwsettings = ();
	$fwdfwsettings{'POLICY'} = "$MODE";
	$fwdfwsettings{'POLICY1'} = "$MODE1";
	&General::writehash("${General::swroot}/firewall/settings", \%fwdfwsettings);
	&General::readhash("${General::swroot}/firewall/settings", \%fwdfwsettings);
	system("/usr/local/bin/firewallctrl");
	system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");  # <=== THIS IS NOT WORKING!
}
&General::readhash($filename, \%settings);             # Load good settings

}

Its nearly the same as the code from line 48-70. I added just one line:

system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");

This should call the firewall init script, which then starts adding the choosen iptables rules.

As I see it, its not possible to run such a script through the GUI because it has to be run with root privileges. Didn’t find a solution, yet.

Best,
Matthias

Wild suggestion… Instead of doing this:

system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");

Maybe do this:

system("/usr/local/bin/firewallctrl");

found here:


 

 

Second suggestion…

I’ve look at the code a few time but I am having a terrible time following it all (the existing firewall code. not your updated code).

The only “cheap and dirty” solution I can suggest is to copy the code segments from either this:

-or this-

and have the user click Apply changes on the firewall.cgi page.

It may not be the best way but it is the current and it is familiar…

Concerning the wild guess…

It looks? like this system("/usr/local/bin/firewallctrl") is firewallctrl.c.

And firewallctrl.c just runs safe_system("/usr/lib/firewall/rules.pl") and resets a file flag.

And looks like rules.pl reloads the firewall rules. Hopefully helping the new code of Redirect DNS.

Hi Jon,

···

On 19.12.2020 23:28, Jon via IPFire Community wrote:

Wild suggestion… Instead of doing this:

system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");

Maybe do this:

system("/usr/local/bin/firewallctrl");

found here:
https://github.com/ipfire/ipfire-2.x/blob/master/config/cfgroot/general-functions.pl#L1147-L1149
 


 

BTDT. :wink:

I created ‘optionsfwctrl.c’ - it looks like this:

/* This file is part of the IPFire Firewall.
 *
 * This program is distributed under the terms of the GNU General Public
 * Licence.  See the file COPYING for details.
 *
 */

#include <stdlib.h>
#include "setuid.h"

int main(void)
{
	if (!(initsetuid()))
		exit(1);

	safe_system("/etc/rc.d/init.d/firewall restart");

	return 0;
}

Same behavior. The ‘save’ command is OK, but ‘optionsfwctrl.c’ doesn’t
run from GUI. From a root console: OK.

Second suggestion…

I’ve look at the code a few time but I am having a terrible time following it all (the existing firewall code. not your updated code).

I’m with you. It’s not easy…

The only “cheap and dirty” solution I can suggest is to copy the code segments from either this:

https://github.com/ipfire/ipfire-2.x/blob/master/html/cgi-bin/location-block.cgi#L76-L91

-or this-

https://github.com/ipfire/ipfire-2.x/blob/master/html/cgi-bin/p2p-block.cgi#L67-L79

and have the user click Apply changes on the firewall.cgi page. It may not be the best way but it is the current and it is familiar…

The way I see it, this is not sufficient.

The problem is I can’t start a program from GUI which needs root
rights. In this case I need a complete restart of the firewall init
script, including ‘iptables’.

What I’m trying to achieve:

  1. Open GUI, Pick your choices (Force DNS ON/OFF, whatever).

  2. Write this settings to the settings file.
    No problem until here.

  3. Then I must run '/etc/rc.d/init.d/firewall restart, including all
    kinds of ‘iptables’-commands.
    And this is were the trouble begins. I’m not allowed to do this from
    GUI. I must be root to do this.

Workaround could be:
The CGI writes the settings file and a signal-file while another
process looks for the existence of this file and restarts the firewall.
Could perhaps be done with a minutely (or ‘cyclic’ = every five
minutes) cron job.

Something like:
if exist FORCE_DNS_SIGNAL-file then;
restart firewall and delete FORCE_DNS_SIGNAL-file. :wink:
fi

I hadn’t much time in the last weeks, but I’m still at it…I have a few
ideas…

Best,
Matthias

Hi,

Concerning the wild guess…

It looks? like this system("/usr/local/bin/firewallctrl") is firewallctrl.c.

Exactly.

And firewallctrl.c just runs safe_system("/usr/lib/firewall/rules.pl") and resets a file flag.

Yep.

And looks like rules.pl reloads the firewall rules.

Yep. But I need a complete firewall restart, including ‘iptables’.

Hopefully helping the new code of Redirect DNS.

I had the same idea. Not working yet - see my previous mail.

Best,
Matthias

I was working my way thru the development mailing list post and I saw a post from Leo. Maybe Leo can help? We can invite him to this thread.

Or I can make this entire thread “public” instead of “private”. But I won’t do this without your OK.

Hi,

I was working my way thru the development mailing list post and I saw a post from Leo. Maybe Leo can help? We can invite him to this thread.

Go on.

Or I can make this entire thread “public” instead of “private”. But I won’t do this without your OK.

No problem! => “OK”. :wink:

Best,
Matthias

···

On 22.12.2020 21:48, Jon via IPFire Community wrote:

Hi Leo @luani -
I invited you to this thread hoping we can tap into your expertise with the WebGUI and specifically optionsfw.cgi page.

Do you have time to assist?

Best regards, Jon

I think it would need a new file in src/misc-progs - there doesn’t seem to be an existing file that does the firewall restart, but it’s easy enough to add a new one.

Hi Jon,
I just got your mail. So if I understand you correctly, you need a “Restart Firewall” button (which executes system('/etc/rc.d/init.d/firewall restart >/dev/null');) added to optionsfw.cgi?
Regards, Leo

Leo - You may want to read thru the above. When the above command runs nothing happens.

Hi,

@luani:

Just to clear things up: the Save and Restart-button already exists.

He should do (Code snippet from above):

    system("/usr/local/bin/firewallctrl");
	system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");  # <=== THIS IS NOT WORKING FROM GUI!

The line /usr/local/bin/firwallctrl is working. Settings are saved.

The problem comes with either /etc/rc.d/init.d/firewall restart or with a new command system("/usr/local/bin/optionsfw.ctrl"); You mentioned this.

Code for optionsfwctrl.c can be found here.

The second command(s) only run from a root console.

I’m searching for a practical and safe solution for this…

Best,
Matthias

Hi Jon, hi Matthias,
I’m sorry, I misread your last messages and thought you got it working. Thanks for the clarification.

So actually you are looking for a secure way to execute specific root commands from the web interface?

Hi Leo,

Exactly.

I have a few ideas - but no breakthrough…

Hi Matthias,
I had a quick look around the sources and I think I have an idea.
There is a file called “unboundctrl.c” which apparently is able to call init scripts. So I tried to figure out what they did differently.

This unboundctrl is used in three CGIs and I’m pretty sure it works as intended.

Now I think the missing piece of the puzzle is hidden in the Makefile. There is a list called “SUID_PROGS”:

I think your “optionsfwctrl.c” must be included in this list…? And then it should work. At least, I hope you haven’t tried that yet :sweat_smile:
I am not at all familiar with the IPFire 2 build system, so I could be wrong. Might be worth investigating though.

1 Like

Hi Leo,

Many thanks for this tip - but sorry, I did this. But since I didn’t know it better, I used firewallctrl.c as “source” file.

Result (optionsfwctrl.c):

/* This file is part of the IPFire Firewall.
 *
 * This program is distributed under the terms of the GNU General Public
 * Licence.  See the file COPYING for details.
 *
 */

#include <stdlib.h>
#include "setuid.h"

int main(void)
{
	if (!(initsetuid()))
		exit(1);

	safe_system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1");

	return 0;
}

The compiled file doesn’t work from GUI - but as root from a root console.

Did I miss something? In the ‘include’-lines? Or syntax?