Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

BF: fail2ban client can't handle multi word setcinfo or action[*] values #134

Merged
merged 5 commits into from

2 participants

@grooverdan
Collaborator

BF: allow more than single word for command action[start,stop,ban,unban,check] and for setcinfo too in fail2ban-client. Previously a set

BF: general Exception catch was excessive. Only IOError and OSError are possible and have different meanings

@yarikoptic yarikoptic commented on the diff
server/transmitter.py
@@ -189,7 +189,7 @@ def __commandSet(self, command):
elif command[1] == "setcinfo":
act = command[2]
key = command[3]
- value = command[4]
+ value = " ".join(command[4:])
@yarikoptic Owner

why bother exactly if any given cmdline positional argument could be wrapped into " " or ' ' ?

I do see it as a possible improvement, but that then also requires documentation (--help output) clarification... but still wonder if it is worth it at all

@grooverdan Collaborator

why bother exactly if any given cmdline positional argument could be wrapped into " " or ' ' ?

Because action* is almost always more that one word. Because this is the only case a wrapped argument is needed. Its still not the nicest but it gives consistent results. Because fail2ban currently discarding arguments and not reporting so much as an error.

The testcase:

./fail2ban-client -c config/ -s /tmp/f2b.sock -i start
add test pyinotify
set test addaction iptables
set test actionban iptables echo   >> /tmp/ban
set test actionunban iptables echo   >> /tmp/unban
get test actionban iptables
get test actionunban iptables

Currently this records only the echo as the action.

but that then also requires documentation (--help output) clarification..

So


sets the start command of the action for . Quote with "" or '' if more than a one word command is required.

I do see it as a possible improvement,

but still wonder if it is worth it at all

make up your mind. Unless you knew about quoting you've got a barely usable set action* client interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@yarikoptic yarikoptic commented on the diff
server/filter.py
((7 lines not shown))
logSys.error("Unable to open %s" % filename)
logSys.exception(e)
return False
+ except OSError, e: # pragma: no cover - requires race condition to tigger this
+ logSys.error("Error opening %s" % filename)
+ logSys.exception(e)
+ return False
@yarikoptic Owner

consider me a paranoid or anyone else, I would still prefer to get an additional swallowing 'except Exception, e' at the end with an additional descriptive logSys.exception(e) and possibly logSys.error("This must have never happened") -- just to guarantee that we are not forgetting anything what FileContainer might throw there

@grooverdan Collaborator

ok. good. added commit for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@yarikoptic yarikoptic merged commit 5e5eaaf into from
@yarikoptic
Owner

ok -- looked all good... so I merged to not keep it away for too long

but still would be nice to signal this feature (of joining multiple positional args). may be via '<>' instead of '' in help output with a minimalistic description for that?

@grooverdan grooverdan deleted the branch
@grooverdan
Collaborator

Is there a need? Looking in common/protocol.py I see VALUE, CMD, REGEX and maybe ACTION and JAIL that are likely to contain spaces. If we redo the parsing to closely couple to the commands here we can grab the remainder of the line as the last positional argument and this will solve VALUE, CMD and REGEX. Is supporting spaces in ACTION and JAIL in the command line something you'd like to support?

<> is already used in the action commands for things like <ip> and I don't find it as something that I'd intuitively separate arguments with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
1  common/protocol.py
@@ -40,6 +40,7 @@
["stop", "stops all jails and terminate the server"],
["status", "gets the current status of the server"],
["ping", "tests if the server is alive"],
+["help", "return this output"],
['', "LOGGING", ""],
["set loglevel <LEVEL>", "sets logging level to <LEVEL>. 0 is minimal, 4 is debug"],
["get loglevel", "gets the logging level"],
View
4 config/action.d/dshield.conf
@@ -124,13 +124,13 @@ port = ???
userid = 0
# Option: myip
-# Notes.: TThe target IP for the attack (your public IP). Should be provided
+# Notes.: The target IP for the attack (your public IP). Should be provided
# either in the jail config or in a .local file unless your PUBLIC IP
# is the first IP assigned to eth0
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
# which in most cases will be a private IP, and therefore incorrect
#
-myip = `ip -4 addr show dev eth0 | grep inet | head -1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
+myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
# Option: protocol
# Notes.: The protocol over which the attack is happening
View
4 config/action.d/mynetwatchman.conf
@@ -102,13 +102,13 @@ mnwlogin =
mnwpass =
# Option: myip
-# Notes.: TThe target IP for the attack (your public IP). Should be overridden
+# Notes.: The target IP for the attack (your public IP). Should be overridden
# either in the jail config or in a .local file unless your PUBLIC IP
# is the first IP assigned to eth0
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
# which in most cases will be a private IP, and therefore incorrect
#
-myip = `ip -4 addr show dev eth0 | grep inet | head -1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
+myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
# Option: protocol
# Notes.: The protocol over which the attack is happening
View
4 fail2ban-client
@@ -380,7 +380,9 @@ class Fail2banClient:
if cmd == "exit" or cmd == "quit":
# Exit
return True
- if not cmd == "":
+ if cmd == "help":
+ self.dispUsage()
+ elif not cmd == "":
self.__processCommand(shlex.split(cmd))
except (EOFError, KeyboardInterrupt):
print
View
11 server/filter.py
@@ -477,10 +477,19 @@ def getFailures(self, filename):
# Try to open log file.
try:
container.open()
- except Exception, e:
+ # see http://python.org/dev/peps/pep-3151/
+ except IOError, e:
logSys.error("Unable to open %s" % filename)
logSys.exception(e)
return False
+ except OSError, e: # pragma: no cover - requires race condition to tigger this
+ logSys.error("Error opening %s" % filename)
+ logSys.exception(e)
+ return False
@yarikoptic Owner

consider me a paranoid or anyone else, I would still prefer to get an additional swallowing 'except Exception, e' at the end with an additional descriptive logSys.exception(e) and possibly logSys.error("This must have never happened") -- just to guarantee that we are not forgetting anything what FileContainer might throw there

@grooverdan Collaborator

ok. good. added commit for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ except OSError, e: # pragma: no cover - Requires implemention error in FileContainer to generate
+ logSys.error("Internal errror in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
+ logSys.exception(e)
+ return False
while True:
line = container.readline()
View
12 server/transmitter.py
@@ -189,7 +189,7 @@ def __commandSet(self, command):
elif command[1] == "setcinfo":
act = command[2]
key = command[3]
- value = command[4]
+ value = " ".join(command[4:])
@yarikoptic Owner

why bother exactly if any given cmdline positional argument could be wrapped into " " or ' ' ?

I do see it as a possible improvement, but that then also requires documentation (--help output) clarification... but still wonder if it is worth it at all

@grooverdan Collaborator

why bother exactly if any given cmdline positional argument could be wrapped into " " or ' ' ?

Because action* is almost always more that one word. Because this is the only case a wrapped argument is needed. Its still not the nicest but it gives consistent results. Because fail2ban currently discarding arguments and not reporting so much as an error.

The testcase:

./fail2ban-client -c config/ -s /tmp/f2b.sock -i start
add test pyinotify
set test addaction iptables
set test actionban iptables echo   >> /tmp/ban
set test actionunban iptables echo   >> /tmp/unban
get test actionban iptables
get test actionunban iptables

Currently this records only the echo as the action.

but that then also requires documentation (--help output) clarification..

So


sets the start command of the action for . Quote with "" or '' if more than a one word command is required.

I do see it as a possible improvement,

but still wonder if it is worth it at all

make up your mind. Unless you knew about quoting you've got a barely usable set action* client interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
self.__server.setCInfo(name, act, key, value)
return self.__server.getCInfo(name, act, key)
elif command[1] == "delcinfo":
@@ -199,27 +199,27 @@ def __commandSet(self, command):
return None
elif command[1] == "actionstart":
act = command[2]
- value = command[3]
+ value = " ".join(command[3:])
self.__server.setActionStart(name, act, value)
return self.__server.getActionStart(name, act)
elif command[1] == "actionstop":
act = command[2]
- value = command[3]
+ value = " ".join(command[3:])
self.__server.setActionStop(name, act, value)
return self.__server.getActionStop(name, act)
elif command[1] == "actioncheck":
act = command[2]
- value = command[3]
+ value = " ".join(command[3:])
self.__server.setActionCheck(name, act, value)
return self.__server.getActionCheck(name, act)
elif command[1] == "actionban":
act = command[2]
- value = command[3]
+ value = " ".join(command[3:])
self.__server.setActionBan(name, act, value)
return self.__server.getActionBan(name, act)
elif command[1] == "actionunban":
act = command[2]
- value = command[3]
+ value = " ".join(command[3:])
self.__server.setActionUnban(name, act, value)
return self.__server.getActionUnban(name, act)
raise Exception("Invalid command (no set action or not yet implemented)")
Something went wrong with that request. Please try again.