-1

Original Post

I have pfSense 23.01 with FreeBSD 14.0

On the command line, this works fine.

sh
sudo easyrule block lan 192.168.1.20 ; sudo easyrule block lan 192.168.1.21 ;

If I run the same command in a shell script:

#!/bin/sh
sudo easyrule block lan 192.168.1.20 ; sudo easyrule block lan 192.168.1.21 ;

It only runs the first command (.20) and completely ignores the second one (.21).

What am I doing wrong?

PS: I have tinkered with some scripts in bash on Ubuntu, but don't have any experience with FreeBSD or sh. Not sure if this is a pfSense question, or a shell script question.

Update #1

Following @shellter's advice, I tried putting the commands on separate lines in the script like this

#!/bin/sh
sudo easyrule block lan 192.168.1.20 ;
sudo easyrule block lan 192.168.1.21 ;

That worked. Now I am faced with the next problem. How do I construct a string variable by concatenating multiple strings, which eventually need to run the command. I tried the following. The below only runs the first line

command=$command" sudo easyrule block lan 192.168.1.20 ;\n"
command=$command" sudo easyrule block lan 192.168.1.21 ;"
$command

The below also runs only the first line

command=$command" sudo easyrule block lan 192.168.1.20 ;"$'\n'
command=$command" sudo easyrule block lan 192.168.1.21 ;"
$command

This one doesn't run anything.

command=$command" sudo easyrule block lan 192.168.1.20 ;"$'\n'
command=$command" sudo easyrule block lan 192.168.1.21 ;"
"$command"

PS: I could probably install bash and make this work, but Netgate / pfSense doesn't recommend it (for it potentially introduces an additional attack vector). Since this is a critical security node, I am not comfortable taking the risk - no matter how small

Dr Phil
  • 430
  • 5
  • 17
  • Try putting each `;` delimited section on a separate line. Yes, you're right, it should require that, but if it works on separate lines, then you have some new information. Good luck. – shellter Apr 28 '23 at 14:42
  • Thank you. It does work on separate lines. Though since I am concatenating an arbitrary number of commands at run time, I am still struggling to get it right. I will add information to the question to that effect. – Dr Phil Apr 28 '23 at 19:54
  • Does this answer your question? [Why does shell ignore quoting characters in arguments passed to it through variables?](https://stackoverflow.com/questions/12136948/why-does-shell-ignore-quoting-characters-in-arguments-passed-to-it-through-varia) – tripleee Apr 30 '23 at 13:49
  • 1
    In short, don't store commands in string variables. – tripleee Apr 30 '23 at 13:50
  • Thank you @tripleee. I think the recommendation to not store commands in a string is a sound one. Though in my setup I don't have access to arrays. The other solution recommended on that post (eval) does work fine for my use case. – Dr Phil Apr 30 '23 at 15:21
  • 1
    If you don't have Bash, you also don't have `$'\n'`. Perhaps see also [Difference between sh and bash](https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash) – tripleee Apr 30 '23 at 21:44
  • 1
    From what inputs are you constructing the command? The simplest by far would be something like `for ip in 192.168.1.20 192.168.1.21; do sudo easyrule block lan "$ip"; done` or perhaps `printf '%s\n' 192.168.1.20 192.168.1.21 | while read -r ip; do sudo easyrule block lan "$ip"; done` – tripleee Apr 30 '23 at 21:48
  • @triplee, thank you. To answer your question, it is a utility script for me (or others with su access). The script takes in parameters like "blockdevices.sh -atr" and depending on the options chosen, it collects all the IPs that need to be blocked (anywhere between 1 to 100). With "eval" I was concatenating all commands and executing. With your suggestions (both work), I can concatenate all the IPs in a string and run a loop at the end. I can see how in general use cases your recommendation is a lot more secure. – Dr Phil May 01 '23 at 16:15

1 Answers1

0

For the benefit of any future readers who do not have access to bash. Say only sh on FreeBSD (which does not link to bash).

Based on @tripleee's suggestion and this answer, there are two options available to you.

Option 1 (dangerous. Only use if you have complete control over the string)

eval $command

or

Option 2 (better overall)

for ip in $command;
  do sudo easyrule block lan "$ip";
done
Dr Phil
  • 430
  • 5
  • 17