Browse Source

Forbid more user names

- Control characters are now forbidden
- Controls and colons are now also forbidden when renaming
rpm
J. King 3 years ago
parent
commit
2946d950f2
  1. 9
      CHANGELOG
  2. 13
      lib/User.php
  3. 27
      tests/cases/User/TestUser.php

9
CHANGELOG

@ -1,13 +1,14 @@
Version 0.9.0 (????-??-??) Version 0.9.0 (????-??-??)
========================== ==========================
New features:
- Support for the Miniflux protocol (see manual for details)
Bug fixes: Bug fixes:
- Use icons specified in Atom feeds when available - Use icons specified in Atom feeds when available
- Do not return null as subscription unread count - Do not return null as subscription unread count
- Explicitly forbid U+003A COLON and control characters in usernames, for
Changes: compatibility with RFC 7617
- Explicitly forbid U+003A COLON in usernames, for compatibility with HTTP
Basic authentication
Version 0.8.5 (2020-10-27) Version 0.8.5 (2020-10-27)
========================== ==========================

13
lib/User.php

@ -84,10 +84,11 @@ class User {
} }
public function add(string $user, ?string $password = null): string { public function add(string $user, ?string $password = null): string {
// ensure the user name does not contain any U+003A COLON characters, as // ensure the user name does not contain any U+003A COLON or control characters, as
// this is incompatible with HTTP Basic authentication // this is incompatible with HTTP Basic authentication
if (strpos($user, ":") !== false) { if (preg_match("/[\x{00}-\x{1F}\x{7F}:]/", $user, $m)) {
throw new User\ExceptionInput("invalidUsername", "U+003A COLON"); $c = ord($m[0]);
throw new User\ExceptionInput("invalidUsername", "U+".str_pad((string) $c, 4, "0", \STR_PAD_LEFT)." ".\IntlChar::charName($c, \IntlChar::EXTENDED_CHAR_NAME));
} }
try { try {
$out = $this->u->userAdd($user, $password) ?? $this->u->userAdd($user, $this->generatePassword()); $out = $this->u->userAdd($user, $password) ?? $this->u->userAdd($user, $this->generatePassword());
@ -105,6 +106,12 @@ class User {
} }
public function rename(string $user, string $newName): bool { public function rename(string $user, string $newName): bool {
// ensure the new user name does not contain any U+003A COLON or
// control characters, as this is incompatible with HTTP Basic authentication
if (preg_match("/[\x{00}-\x{1F}\x{7F}:]/", $newName, $m)) {
$c = ord($m[0]);
throw new User\ExceptionInput("invalidUsername", "U+".str_pad((string) $c, 4, "0", \STR_PAD_LEFT)." ".\IntlChar::charName($c, \IntlChar::EXTENDED_CHAR_NAME));
}
if ($this->u->userRename($user, $newName)) { if ($this->u->userRename($user, $newName)) {
$tr = Arsse::$db->begin(); $tr = Arsse::$db->begin();
if (!Arsse::$db->userExists($user)) { if (!Arsse::$db->userExists($user)) {

27
tests/cases/User/TestUser.php

@ -160,13 +160,22 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
} }
} }
public function testAddAnInvalidUser(): void { /** @dataProvider provideInvalidUserNames */
$user = "john:doe@example.com"; public function testAddAnInvalidUser(string $user): void {
$pass = "secret";
$u = new User($this->drv); $u = new User($this->drv);
\Phake::when($this->drv)->userAdd->thenThrow(new ExceptionInput("invalidUsername"));
$this->assertException("invalidUsername", "User", "ExceptionInput"); $this->assertException("invalidUsername", "User", "ExceptionInput");
$u->add($user, $pass); $u->add($user, "secret");
}
public function provideInvalidUserNames(): iterable {
// output names with control characters
foreach (array_merge(range(0x00, 0x1F), [0x7F]) as $ord) {
yield [chr($ord)];
yield ["john".chr($ord)."doe@example.com"];
}
// also handle colons
yield [":"];
yield ["john:doe@example.com"];
} }
public function testAddAUserWithARandomPassword(): void { public function testAddAUserWithARandomPassword(): void {
@ -231,11 +240,17 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
\Phake::when($this->drv)->userRename->thenReturn(false); \Phake::when($this->drv)->userRename->thenReturn(false);
$u = new User($this->drv); $u = new User($this->drv);
$old = "john.doe@example.com"; $old = "john.doe@example.com";
$new = "jane.doe@example.com";
$this->assertFalse($u->rename($old, $old)); $this->assertFalse($u->rename($old, $old));
\Phake::verify($this->drv)->userRename($old, $old); \Phake::verify($this->drv)->userRename($old, $old);
} }
/** @dataProvider provideInvalidUserNames */
public function testRenameAUserToAnInvalidName(string $new): void {
$u = new User($this->drv);
$this->assertException("invalidUsername", "User", "ExceptionInput");
$u->rename("john.doe@example.com", $new);
}
public function testRemoveAUser(): void { public function testRemoveAUser(): void {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$u = new User($this->drv); $u = new User($this->drv);

Loading…
Cancel
Save