diff --git a/rsocket-core/src/main/java/io/rsocket/metadata/AuthMetadataCodec.java b/rsocket-core/src/main/java/io/rsocket/metadata/AuthMetadataCodec.java index d908abb3c..c16c4dc52 100644 --- a/rsocket-core/src/main/java/io/rsocket/metadata/AuthMetadataCodec.java +++ b/rsocket-core/src/main/java/io/rsocket/metadata/AuthMetadataCodec.java @@ -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]; @@ -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. @@ -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); @@ -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); @@ -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; @@ -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; @@ -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) { @@ -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( diff --git a/rsocket-core/src/test/java/io/rsocket/metadata/security/AuthMetadataFlyweightTest.java b/rsocket-core/src/test/java/io/rsocket/metadata/security/AuthMetadataFlyweightTest.java index 13d910e15..93d0f8b12 100644 --- a/rsocket-core/src/test/java/io/rsocket/metadata/security/AuthMetadataFlyweightTest.java +++ b/rsocket-core/src/test/java/io/rsocket/metadata/security/AuthMetadataFlyweightTest.java @@ -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"; @@ -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); @@ -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 @@ -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); } @@ -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); } @@ -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); }