Skip to content

Commit

Permalink
updates username length to align with the spec (uint8 vs uint16) (#938)
Browse files Browse the repository at this point in the history
Co-authored-by: Jascha Riedel <Jascha.Riedel@sunplugged.at>
  • Loading branch information
freelancer1845 and Jascha Riedel authored Oct 1, 2020
1 parent fdf7fb0 commit 7af1848
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AuthMetadataCodec {
static final int STREAM_METADATA_KNOWN_MASK = 0x80; // 1000 0000
static final byte STREAM_METADATA_LENGTH_MASK = 0x7F; // 0111 1111

static final int USERNAME_BYTES_LENGTH = 1;
static final int USERNAME_BYTES_LENGTH = 2;
static final int AUTH_TYPE_ID_LENGTH = 1;

static final char[] EMPTY_CHARS_ARRAY = new char[0];
Expand Down Expand Up @@ -81,7 +81,7 @@ public static ByteBuf encodeMetadata(
/**
* Encode a Authentication CompositeMetadata payload using Simple Authentication format
*
* @throws IllegalArgumentException if the username length is greater than 255
* @throws IllegalArgumentException if the username length is greater than 65535
* @param allocator the {@link ByteBufAllocator} to use to create intermediate buffers as needed.
* @param username the char sequence which represents user name.
* @param password the char sequence which represents user password.
Expand All @@ -90,9 +90,9 @@ public static ByteBuf encodeSimpleMetadata(
ByteBufAllocator allocator, char[] username, char[] password) {

int usernameLength = CharByteBufUtil.utf8Bytes(username);
if (usernameLength > 255) {
if (usernameLength > 65535) {
throw new IllegalArgumentException(
"Username should be shorter than or equal to 255 bytes length in UTF-8 encoding");
"Username should be shorter than or equal to 65535 bytes length in UTF-8 encoding");
}

int passwordLength = CharByteBufUtil.utf8Bytes(password);
Expand All @@ -101,7 +101,7 @@ public static ByteBuf encodeSimpleMetadata(
allocator
.buffer(capacity, capacity)
.writeByte(WellKnownAuthType.SIMPLE.getIdentifier() | STREAM_METADATA_KNOWN_MASK)
.writeByte(usernameLength);
.writeShort(usernameLength);

CharByteBufUtil.writeUtf8(buffer, username);
CharByteBufUtil.writeUtf8(buffer, password);
Expand Down Expand Up @@ -235,15 +235,15 @@ public static ByteBuf readPayload(ByteBuf metadata) {
}

/**
* Read up to 257 {@code bytes} from the given {@link ByteBuf} where the first byte is username
* length and the subsequent number of bytes equal to decoded length
* Read up to 65537 {@code bytes} from the given {@link ByteBuf} where the first two bytes
* represent username length and the subsequent number of bytes equal to read length
*
* @param simpleAuthMetadata the given metadata to read username from. Please note, the {@code
* simpleAuthMetadata#readIndex} should be set to the username length byte
* simpleAuthMetadata#readIndex} should be set to the username length position
* @return sliced {@link ByteBuf} or {@link Unpooled#EMPTY_BUFFER} if username length is zero
*/
public static ByteBuf readUsername(ByteBuf simpleAuthMetadata) {
short usernameLength = readUsernameLength(simpleAuthMetadata);
int usernameLength = readUsernameLength(simpleAuthMetadata);

if (usernameLength == 0) {
return Unpooled.EMPTY_BUFFER;
Expand All @@ -268,15 +268,15 @@ public static ByteBuf readPassword(ByteBuf simpleAuthMetadata) {
return simpleAuthMetadata.readSlice(simpleAuthMetadata.readableBytes());
}
/**
* Read up to 257 {@code bytes} from the given {@link ByteBuf} where the first byte is username
* length and the subsequent number of bytes equal to decoded length
* Read up to 65537 {@code bytes} from the given {@link ByteBuf} where the first two bytes
* represent username length and the subsequent number of bytes equal to read length
*
* @param simpleAuthMetadata the given metadata to read username from. Please note, the {@code
* simpleAuthMetadata#readIndex} should be set to the username length byte
* @return {@code char[]} which represents UTF-8 username
*/
public static char[] readUsernameAsCharArray(ByteBuf simpleAuthMetadata) {
short usernameLength = readUsernameLength(simpleAuthMetadata);
int usernameLength = readUsernameLength(simpleAuthMetadata);

if (usernameLength == 0) {
return EMPTY_CHARS_ARRAY;
Expand All @@ -302,11 +302,10 @@ public static char[] readPasswordAsCharArray(ByteBuf simpleAuthMetadata) {
}

/**
* Read all the remaining {@code bytes} from the given {@link ByteBuf} where the first byte is
* username length and the subsequent number of bytes equal to decoded length
* Read all the remaining {@code bytes} from the given {@link ByteBuf}
*
* @param bearerAuthMetadata the given metadata to read username from. Please note, the {@code
* simpleAuthMetadata#readIndex} should be set to the beginning of the password bytes
* bearerAuthMetadata#readIndex} should be set to the beginning of the password bytes
* @return {@code char[]} which represents UTF-8 password
*/
public static char[] readBearerTokenAsCharArray(ByteBuf bearerAuthMetadata) {
Expand All @@ -317,13 +316,13 @@ public static char[] readBearerTokenAsCharArray(ByteBuf bearerAuthMetadata) {
return CharByteBufUtil.readUtf8(bearerAuthMetadata, bearerAuthMetadata.readableBytes());
}

private static short readUsernameLength(ByteBuf simpleAuthMetadata) {
if (simpleAuthMetadata.readableBytes() < 1) {
private static int readUsernameLength(ByteBuf simpleAuthMetadata) {
if (simpleAuthMetadata.readableBytes() < 2) {
throw new IllegalStateException(
"Unable to decode custom username. Not enough readable bytes");
}

short usernameLength = simpleAuthMetadata.readUnsignedByte();
int usernameLength = simpleAuthMetadata.readUnsignedShort();

if (simpleAuthMetadata.readableBytes() < usernameLength) {
throw new IllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class AuthMetadataFlyweightTest {

public static final int AUTH_TYPE_ID_LENGTH = 1;
public static final int USER_NAME_BYTES_LENGTH = 1;
public static final int USER_NAME_BYTES_LENGTH = 2;
public static final String TEST_BEARER_TOKEN =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJpYXQxIjoxNTE2MjM5MDIyLCJpYXQyIjoxNTE2MjM5MDIyLCJpYXQzIjoxNTE2MjM5MDIyLCJpYXQ0IjoxNTE2MjM5MDIyfQ.ljYuH-GNyyhhLcx-rHMchRkGbNsR2_4aSxo8XjrYrSM";

Expand Down Expand Up @@ -82,7 +82,7 @@ private static void checkSimpleAuthMetadataEncoding(

Assertions.assertThat(byteBuf.readUnsignedByte() & ~0x80)
.isEqualTo(WellKnownAuthType.SIMPLE.getIdentifier());
Assertions.assertThat(byteBuf.readUnsignedByte()).isEqualTo((short) usernameLength);
Assertions.assertThat(byteBuf.readUnsignedShort()).isEqualTo((short) usernameLength);

Assertions.assertThat(byteBuf.readCharSequence(usernameLength, CharsetUtil.UTF_8))
.isEqualTo(username);
Expand Down Expand Up @@ -116,16 +116,22 @@ private static void checkSimpleAuthMetadataEncodingUsingDecoders(

@Test
void shouldThrowExceptionIfUsernameLengthExitsAllowedBounds() {
String username =
StringBuilder usernameBuilder = new StringBuilder();
String usernamePart =
"𠜎𠜱𠝹𠱓𠱸𠲖𠳏𠳕𠴕𠵼𠵿𠸎𠸏𠹷𠺝𠺢𠻗𠻹𠻺𠼭𠼮𠽌𠾴𠾼𠿪𡁜𡁯𡁵𡁶𡁻𡃁𡃉𡇙𢃇𢞵𢫕𢭃𢯊𢱑𢱕𢳂𢴈𢵌𢵧𢺳𣲷𤓓𤶸𤷪𥄫𦉘𦟌𦧲𦧺𧨾𨅝𨈇𨋢𨳊𨳍𨳒𩶘𠜎𠜱𠝹";
for (int i = 0; i < 65535 / usernamePart.length(); i++) {
usernameBuilder.append(usernamePart);
}
String password = "tset1234";

Assertions.assertThatThrownBy(
() ->
AuthMetadataFlyweight.encodeSimpleMetadata(
ByteBufAllocator.DEFAULT, username.toCharArray(), password.toCharArray()))
ByteBufAllocator.DEFAULT,
usernameBuilder.toString().toCharArray(),
password.toCharArray()))
.hasMessage(
"Username should be shorter than or equal to 255 bytes length in UTF-8 encoding");
"Username should be shorter than or equal to 65535 bytes length in UTF-8 encoding");
}

@Test
Expand Down Expand Up @@ -243,7 +249,7 @@ void shouldEncodeUsingWellKnownAuthType() {
AuthMetadataFlyweight.encodeMetadata(
ByteBufAllocator.DEFAULT,
WellKnownAuthType.SIMPLE,
ByteBufAllocator.DEFAULT.buffer(3, 3).writeByte(1).writeByte('u').writeByte('p'));
ByteBufAllocator.DEFAULT.buffer().writeShort(1).writeByte('u').writeByte('p'));

checkSimpleAuthMetadataEncoding("u", "p", 1, 1, byteBuf);
}
Expand All @@ -254,7 +260,7 @@ void shouldEncodeUsingWellKnownAuthType1() {
AuthMetadataFlyweight.encodeMetadata(
ByteBufAllocator.DEFAULT,
WellKnownAuthType.SIMPLE,
ByteBufAllocator.DEFAULT.buffer().writeByte(1).writeByte('u').writeByte('p'));
ByteBufAllocator.DEFAULT.buffer().writeShort(1).writeByte('u').writeByte('p'));

checkSimpleAuthMetadataEncoding("u", "p", 1, 1, byteBuf);
}
Expand Down Expand Up @@ -298,7 +304,7 @@ void shouldCompressMetadata() {
AuthMetadataFlyweight.encodeMetadataWithCompression(
ByteBufAllocator.DEFAULT,
"simple",
ByteBufAllocator.DEFAULT.buffer().writeByte(1).writeByte('u').writeByte('p'));
ByteBufAllocator.DEFAULT.buffer().writeShort(1).writeByte('u').writeByte('p'));

checkSimpleAuthMetadataEncoding("u", "p", 1, 1, byteBuf);
}
Expand Down

0 comments on commit 7af1848

Please sign in to comment.