Add various validation tests (#221)

* Add various validation tests

* skip UTF8ONLY tests on servers that don't support it

* Fixes for Ergo

* Fixes for Nefarious and ircu2

* xfail for irc2 and workaround for ngIRCd

* Bump ngIRCd to the ERR_NOTEXTTOSEND fix
This commit is contained in:
2023-09-18 20:31:50 +02:00
committed by GitHub
parent 04d0c8000f
commit 3692f2d79d
6 changed files with 121 additions and 5 deletions

View File

@ -233,7 +233,7 @@ jobs:
uses: actions/checkout@v3
with:
path: ngircd
ref: rel-26.1
ref: 0714466af88d71d6c395629cd7fb624b099507d4
repository: ngircd/ngircd
- name: Build ngircd
run: |

View File

@ -44,8 +44,8 @@ class KeyTestCase(cases.BaseServerTestCase):
@pytest.mark.parametrize(
"key",
["passphrase with spaces", "long" * 100, ""],
ids=["spaces", "long", "empty"],
["passphrase with spaces", "long" * 100, "", " "],
ids=["spaces", "long", "empty", "only-space"],
)
@cases.mark_specifications("RFC2812", "Modern")
def testKeyValidation(self, key):
@ -84,6 +84,8 @@ class KeyTestCase(cases.BaseServerTestCase):
"ngIRCd does not validate channel keys: "
"https://github.com/ngircd/ngircd/issues/290"
)
if key == " " and self.controller.software_name == "irc2":
pytest.xfail("irc2 rewrites non-empty keys that contain only spaces")
self.connectClient("bar")
self.joinChannel(1, "#chan")

View File

@ -5,6 +5,8 @@ Tests section 4.1 of RFC 1459.
TODO: cross-reference Modern and RFC 2812 too
"""
import time
from irctest import cases
from irctest.client_mock import ConnectionClosed
from irctest.numerics import ERR_NEEDMOREPARAMS, ERR_PASSWDMISMATCH
@ -133,7 +135,7 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.assertNotEqual(
m.command,
"001",
"Received 001 after registering with the nick of a " "registered user.",
"Received 001 after registering with the nick of a registered user.",
)
def testEarlyNickCollision(self):
@ -206,3 +208,58 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
command=ERR_NEEDMOREPARAMS,
params=[StrRe(r"(\*|foo)"), "USER", ANYSTR],
)
def testNonutf8Realname(self):
self.addClient()
self.sendLine(1, "NICK foo")
line = b"USER username * * :i\xe8rc\xe9\r\n"
print("1 -> S (repr): " + repr(line))
self.clients[1].conn.sendall(line)
for _ in range(10):
time.sleep(1)
d = self.clients[1].conn.recv(10000)
self.assertTrue(d, "Server closed connection")
print("S -> 1 (repr): " + repr(d))
if b" 001 " in d:
break
if b"ERROR " in d or b" FAIL " in d:
# Rejected; nothing more to test.
return
for line in d.split(b"\r\n"):
if line.startswith(b"PING "):
line = line.replace(b"PING", b"PONG") + b"\r\n"
print("1 -> S (repr): " + repr(line))
self.clients[1].conn.sendall(line)
else:
self.assertTrue(False, "stuck waiting")
self.sendLine(1, "WHOIS foo")
time.sleep(3) # for ngIRCd
d = self.clients[1].conn.recv(10000)
print("S -> 1 (repr): " + repr(d))
self.assertIn(b"username", d)
def testNonutf8Username(self):
self.addClient()
self.sendLine(1, "NICK foo")
self.sendLine(1, "USER 😊😊😊😊😊😊😊😊😊😊 * * :realname")
for _ in range(10):
time.sleep(1)
d = self.clients[1].conn.recv(10000)
self.assertTrue(d, "Server closed connection")
print("S -> 1 (repr): " + repr(d))
if b" 001 " in d:
break
if b" 468" in d or b"ERROR " in d:
# Rejected; nothing more to test.
return
for line in d.split(b"\r\n"):
if line.startswith(b"PING "):
line = line.replace(b"PING", b"PONG") + b"\r\n"
print("1 -> S (repr): " + repr(line))
self.clients[1].conn.sendall(line)
else:
self.assertTrue(False, "stuck waiting")
self.sendLine(1, "WHOIS foo")
d = self.clients[1].conn.recv(10000)
print("S -> 1 (repr): " + repr(d))
self.assertIn(b"realname", d)

View File

@ -53,6 +53,28 @@ class PrivmsgTestCase(cases.BaseServerTestCase):
# ERR_NOSUCHNICK: 401 <sender> <recipient> :No such nick
self.assertMessageMatch(msg, command="401", params=["foo", "bar", ANYSTR])
@cases.mark_specifications("RFC1459", "RFC2812", "Modern")
@cases.xfailIfSoftware(
["irc2"],
"replies with ERR_NEEDMOREPARAMS instead of ERR_NOTEXTTOSEND",
)
def testEmptyPrivmsg(self):
self.connectClient("foo")
self.sendLine(1, "JOIN #chan")
self.getMessages(1) # synchronize
self.connectClient("bar")
self.sendLine(2, "JOIN #chan")
self.getMessages(2) # synchronize
self.getMessages(1) # synchronize
self.sendLine(1, "PRIVMSG #chan :")
self.assertMessageMatch(
self.getMessage(1),
command="412", # ERR_NOTEXTTOSEND
params=["foo", ANYSTR],
)
self.assertEqual(self.getMessages(2), [])
class NoticeTestCase(cases.BaseServerTestCase):
@cases.mark_specifications("RFC1459", "RFC2812")

View File

@ -46,3 +46,38 @@ class Utf8TestCase(cases.BaseServerTestCase):
if m.command in ("FAIL", "WARN"):
self.assertMessageMatch(m, params=["PRIVMSG", "INVALID_UTF8", ANYSTR])
def testNonutf8Realname(self):
self.connectClient("foo")
if "UTF8ONLY" not in self.server_support:
raise runner.IsupportTokenNotSupported("UTF8ONLY")
self.addClient()
self.sendLine(2, "NICK foo")
self.clients[2].conn.sendall(b"USER username * * :i\xe8rc\xe9\r\n")
d = self.clients[2].conn.recv(1024)
if b" FAIL " in d or b" 468 " in d: # ERR_INVALIDUSERNAME
return # nothing more to test
self.assertIn(b" 001 ", d)
self.sendLine(2, "WHOIS foo")
self.getMessages(2)
def testNonutf8Username(self):
self.connectClient("foo")
if "UTF8ONLY" not in self.server_support:
raise runner.IsupportTokenNotSupported("UTF8ONLY")
self.addClient()
self.sendLine(2, "NICK foo")
self.sendLine(2, "USER 😊😊😊😊😊😊😊😊😊😊 * * :realname")
m = self.getRegistrationMessage(2)
if m.command in ("FAIL", "468"): # ERR_INVALIDUSERNAME
return # nothing more to test
self.assertMessageMatch(
m,
command="001",
)
self.sendLine(2, "WHOIS foo")
self.getMessages(2)

View File

@ -235,7 +235,7 @@ software:
name: ngircd
repository: ngircd/ngircd
refs:
stable: rel-26.1
stable: 0714466af88d71d6c395629cd7fb624b099507d4 # two years ahead of rel-26.1
release: null
devel: master
devel_release: null