mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-25 09:28:27 +00:00
Move CharArrays to core lib (#32851)
This change cleans up some methods in the CharArrays class from x-pack, which includes the unification of char[] to utf8 and utf8 to char[] conversions that intentionally do not use strings. There was previously an implementation in x-pack and in the reloading of secure settings. The method from the reloading of secure settings was adopted as it handled more scenarios related to the backing byte and char buffers that were used to perform the conversions. The cleaned up class is moved into libs/core to allow it to be used by requests that will be migrated to the high level rest client. Relates #32332
This commit is contained in:
parent
364ccc36d6
commit
1a45b27d8b
150
libs/core/src/main/java/org/elasticsearch/common/CharArrays.java
Normal file
150
libs/core/src/main/java/org/elasticsearch/common/CharArrays.java
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Helper class similar to Arrays to handle conversions for Char arrays
|
||||
*/
|
||||
public final class CharArrays {
|
||||
|
||||
private CharArrays() {}
|
||||
|
||||
/**
|
||||
* Decodes the provided byte[] to a UTF-8 char[]. This is done while avoiding
|
||||
* conversions to String. The provided byte[] is not modified by this method, so
|
||||
* the caller needs to take care of clearing the value if it is sensitive.
|
||||
*/
|
||||
public static char[] utf8BytesToChars(byte[] utf8Bytes) {
|
||||
final ByteBuffer byteBuffer = ByteBuffer.wrap(utf8Bytes);
|
||||
final CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
|
||||
final char[] chars;
|
||||
if (charBuffer.hasArray()) {
|
||||
// there is no guarantee that the char buffers backing array is the right size
|
||||
// so we need to make a copy
|
||||
chars = Arrays.copyOfRange(charBuffer.array(), charBuffer.position(), charBuffer.limit());
|
||||
Arrays.fill(charBuffer.array(), (char) 0); // clear sensitive data
|
||||
} else {
|
||||
final int length = charBuffer.limit() - charBuffer.position();
|
||||
chars = new char[length];
|
||||
charBuffer.get(chars);
|
||||
// if the buffer is not read only we can reset and fill with 0's
|
||||
if (charBuffer.isReadOnly() == false) {
|
||||
charBuffer.clear(); // reset
|
||||
for (int i = 0; i < charBuffer.limit(); i++) {
|
||||
charBuffer.put((char) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the provided char[] to a UTF-8 byte[]. This is done while avoiding
|
||||
* conversions to String. The provided char[] is not modified by this method, so
|
||||
* the caller needs to take care of clearing the value if it is sensitive.
|
||||
*/
|
||||
public static byte[] toUtf8Bytes(char[] chars) {
|
||||
final CharBuffer charBuffer = CharBuffer.wrap(chars);
|
||||
final ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
|
||||
final byte[] bytes;
|
||||
if (byteBuffer.hasArray()) {
|
||||
// there is no guarantee that the byte buffers backing array is the right size
|
||||
// so we need to make a copy
|
||||
bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
|
||||
Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
|
||||
} else {
|
||||
final int length = byteBuffer.limit() - byteBuffer.position();
|
||||
bytes = new byte[length];
|
||||
byteBuffer.get(bytes);
|
||||
// if the buffer is not read only we can reset and fill with 0's
|
||||
if (byteBuffer.isReadOnly() == false) {
|
||||
byteBuffer.clear(); // reset
|
||||
for (int i = 0; i < byteBuffer.limit(); i++) {
|
||||
byteBuffer.put((byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a char[] contains a sequence of characters that match the prefix. This is like
|
||||
* {@link String#startsWith(String)} but does not require conversion of the char[] to a string.
|
||||
*/
|
||||
public static boolean charsBeginsWith(String prefix, char[] chars) {
|
||||
if (chars == null || prefix == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prefix.length() > chars.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < prefix.length(); i++) {
|
||||
if (chars[i] != prefix.charAt(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant time equality check of char arrays to avoid potential timing attacks.
|
||||
*/
|
||||
public static boolean constantTimeEquals(char[] a, char[] b) {
|
||||
Objects.requireNonNull(a, "char arrays must not be null for constantTimeEquals");
|
||||
Objects.requireNonNull(b, "char arrays must not be null for constantTimeEquals");
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int equals = 0;
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
equals |= a[i] ^ b[i];
|
||||
}
|
||||
|
||||
return equals == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant time equality check of strings to avoid potential timing attacks.
|
||||
*/
|
||||
public static boolean constantTimeEquals(String a, String b) {
|
||||
Objects.requireNonNull(a, "strings must not be null for constantTimeEquals");
|
||||
Objects.requireNonNull(b, "strings must not be null for constantTimeEquals");
|
||||
if (a.length() != b.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int equals = 0;
|
||||
for (int i = 0; i < a.length(); i++) {
|
||||
equals |= a.charAt(i) ^ b.charAt(i);
|
||||
}
|
||||
|
||||
return equals == 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class CharArraysTests extends ESTestCase {
|
||||
|
||||
public void testCharsToBytes() {
|
||||
final String originalValue = randomUnicodeOfCodepointLengthBetween(0, 32);
|
||||
final byte[] expectedBytes = originalValue.getBytes(StandardCharsets.UTF_8);
|
||||
final char[] valueChars = originalValue.toCharArray();
|
||||
|
||||
final byte[] convertedBytes = CharArrays.toUtf8Bytes(valueChars);
|
||||
assertArrayEquals(expectedBytes, convertedBytes);
|
||||
}
|
||||
|
||||
public void testBytesToUtf8Chars() {
|
||||
final String originalValue = randomUnicodeOfCodepointLengthBetween(0, 32);
|
||||
final byte[] bytes = originalValue.getBytes(StandardCharsets.UTF_8);
|
||||
final char[] expectedChars = originalValue.toCharArray();
|
||||
|
||||
final char[] convertedChars = CharArrays.utf8BytesToChars(bytes);
|
||||
assertArrayEquals(expectedChars, convertedChars);
|
||||
}
|
||||
|
||||
public void testCharsBeginsWith() {
|
||||
assertFalse(CharArrays.charsBeginsWith(randomAlphaOfLength(4), null));
|
||||
assertFalse(CharArrays.charsBeginsWith(null, null));
|
||||
assertFalse(CharArrays.charsBeginsWith(null, randomAlphaOfLength(4).toCharArray()));
|
||||
assertFalse(CharArrays.charsBeginsWith(randomAlphaOfLength(2), randomAlphaOfLengthBetween(3, 8).toCharArray()));
|
||||
|
||||
final String prefix = randomAlphaOfLengthBetween(2, 4);
|
||||
assertTrue(CharArrays.charsBeginsWith(prefix, prefix.toCharArray()));
|
||||
final char[] prefixedValue = prefix.concat(randomAlphaOfLengthBetween(1, 12)).toCharArray();
|
||||
assertTrue(CharArrays.charsBeginsWith(prefix, prefixedValue));
|
||||
|
||||
final String modifiedPrefix = randomBoolean() ? prefix.substring(1) : prefix.substring(0, prefix.length() - 1);
|
||||
final char[] nonMatchingValue = modifiedPrefix.concat(randomAlphaOfLengthBetween(0, 12)).toCharArray();
|
||||
assertFalse(CharArrays.charsBeginsWith(prefix, nonMatchingValue));
|
||||
assertTrue(CharArrays.charsBeginsWith(modifiedPrefix, nonMatchingValue));
|
||||
}
|
||||
|
||||
public void testConstantTimeEquals() {
|
||||
final String value = randomAlphaOfLengthBetween(0, 32);
|
||||
assertTrue(CharArrays.constantTimeEquals(value, value));
|
||||
assertTrue(CharArrays.constantTimeEquals(value.toCharArray(), value.toCharArray()));
|
||||
|
||||
final String other = randomAlphaOfLengthBetween(1, 32);
|
||||
assertFalse(CharArrays.constantTimeEquals(value, other));
|
||||
assertFalse(CharArrays.constantTimeEquals(value.toCharArray(), other.toCharArray()));
|
||||
}
|
||||
}
|
@ -22,14 +22,12 @@ package org.elasticsearch.action.admin.cluster.node.reload;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.nodes.BaseNodesRequest;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||
@ -83,7 +81,7 @@ public class NodesReloadSecureSettingsRequest extends BaseNodesRequest<NodesRelo
|
||||
super.readFrom(in);
|
||||
final byte[] passwordBytes = in.readByteArray();
|
||||
try {
|
||||
this.secureSettingsPassword = new SecureString(utf8BytesToChars(passwordBytes));
|
||||
this.secureSettingsPassword = new SecureString(CharArrays.utf8BytesToChars(passwordBytes));
|
||||
} finally {
|
||||
Arrays.fill(passwordBytes, (byte) 0);
|
||||
}
|
||||
@ -92,69 +90,11 @@ public class NodesReloadSecureSettingsRequest extends BaseNodesRequest<NodesRelo
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
final byte[] passwordBytes = charsToUtf8Bytes(this.secureSettingsPassword.getChars());
|
||||
final byte[] passwordBytes = CharArrays.toUtf8Bytes(this.secureSettingsPassword.getChars());
|
||||
try {
|
||||
out.writeByteArray(passwordBytes);
|
||||
} finally {
|
||||
Arrays.fill(passwordBytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the provided char[] to a UTF-8 byte[]. This is done while avoiding
|
||||
* conversions to String. The provided char[] is not modified by this method, so
|
||||
* the caller needs to take care of clearing the value if it is sensitive.
|
||||
*/
|
||||
private static byte[] charsToUtf8Bytes(char[] chars) {
|
||||
final CharBuffer charBuffer = CharBuffer.wrap(chars);
|
||||
final ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
|
||||
final byte[] bytes;
|
||||
if (byteBuffer.hasArray()) {
|
||||
// there is no guarantee that the byte buffers backing array is the right size
|
||||
// so we need to make a copy
|
||||
bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
|
||||
Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
|
||||
} else {
|
||||
final int length = byteBuffer.limit() - byteBuffer.position();
|
||||
bytes = new byte[length];
|
||||
byteBuffer.get(bytes);
|
||||
// if the buffer is not read only we can reset and fill with 0's
|
||||
if (byteBuffer.isReadOnly() == false) {
|
||||
byteBuffer.clear(); // reset
|
||||
for (int i = 0; i < byteBuffer.limit(); i++) {
|
||||
byteBuffer.put((byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the provided byte[] to a UTF-8 char[]. This is done while avoiding
|
||||
* conversions to String. The provided byte[] is not modified by this method, so
|
||||
* the caller needs to take care of clearing the value if it is sensitive.
|
||||
*/
|
||||
public static char[] utf8BytesToChars(byte[] utf8Bytes) {
|
||||
final ByteBuffer byteBuffer = ByteBuffer.wrap(utf8Bytes);
|
||||
final CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
|
||||
final char[] chars;
|
||||
if (charBuffer.hasArray()) {
|
||||
// there is no guarantee that the char buffers backing array is the right size
|
||||
// so we need to make a copy
|
||||
chars = Arrays.copyOfRange(charBuffer.array(), charBuffer.position(), charBuffer.limit());
|
||||
Arrays.fill(charBuffer.array(), (char) 0); // clear sensitive data
|
||||
} else {
|
||||
final int length = charBuffer.limit() - charBuffer.position();
|
||||
chars = new char[length];
|
||||
charBuffer.get(chars);
|
||||
// if the buffer is not read only we can reset and fill with 0's
|
||||
if (charBuffer.isReadOnly() == false) {
|
||||
charBuffer.clear(); // reset
|
||||
for (int i = 0; i < charBuffer.limit(); i++) {
|
||||
charBuffer.put((char) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
@ -12,7 +12,7 @@ import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -8,12 +8,12 @@ package org.elasticsearch.xpack.core.security.action.user;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
@ -14,6 +14,7 @@ package org.elasticsearch.xpack.core.security.authc.support;
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
@ -54,7 +55,7 @@ import java.security.SecureRandom;
|
||||
* String stronger_salt = BCrypt.gensalt(12)<br>
|
||||
* </code>
|
||||
* <p>
|
||||
* The amount of work increases exponentially (2**log_rounds), so
|
||||
* The amount of work increases exponentially (2**log_rounds), so
|
||||
* each increment is twice as much work. The default log_rounds is
|
||||
* 10, and the valid range is 4 to 30.
|
||||
*
|
||||
@ -689,7 +690,11 @@ public class BCrypt {
|
||||
|
||||
// the next lines are the SecureString replacement for the above commented-out section
|
||||
if (minor >= 'a') {
|
||||
try (SecureString secureString = new SecureString(CharArrays.concat(password.getChars(), "\000".toCharArray()))) {
|
||||
final char[] suffix = "\000".toCharArray();
|
||||
final char[] result = new char[password.length() + suffix.length];
|
||||
System.arraycopy(password.getChars(), 0, result, 0, password.length());
|
||||
System.arraycopy(suffix, 0, result, password.length(), suffix.length);
|
||||
try (SecureString secureString = new SecureString(result)) {
|
||||
passwordb = CharArrays.toUtf8Bytes(secureString.getChars());
|
||||
}
|
||||
} else {
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.core.security.authc.support;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Helper class similar to Arrays to handle conversions for Char arrays
|
||||
*/
|
||||
public class CharArrays {
|
||||
|
||||
public static char[] utf8BytesToChars(byte[] utf8Bytes) {
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(utf8Bytes);
|
||||
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
|
||||
char[] chars = Arrays.copyOfRange(charBuffer.array(), charBuffer.position(), charBuffer.limit());
|
||||
byteBuffer.clear();
|
||||
charBuffer.clear();
|
||||
return chars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like String.indexOf for for an array of chars
|
||||
*/
|
||||
static int indexOf(char[] array, char ch) {
|
||||
for (int i = 0; (i < array.length); i++) {
|
||||
if (array[i] == ch) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the provided char[] to a UTF-8 byte[]. The provided char[] is not modified by this
|
||||
* method, so the caller needs to take care of clearing the value if it is sensitive.
|
||||
*/
|
||||
public static byte[] toUtf8Bytes(char[] chars) {
|
||||
CharBuffer charBuffer = CharBuffer.wrap(chars);
|
||||
ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
|
||||
byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
|
||||
Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static boolean charsBeginsWith(String prefix, char[] chars) {
|
||||
if (chars == null || prefix == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prefix.length() > chars.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < prefix.length(); i++) {
|
||||
if (chars[i] != prefix.charAt(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean constantTimeEquals(char[] a, char[] b) {
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int equals = 0;
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
equals |= a[i] ^ b[i];
|
||||
}
|
||||
|
||||
return equals == 0;
|
||||
}
|
||||
|
||||
public static boolean constantTimeEquals(String a, String b) {
|
||||
if (a.length() != b.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int equals = 0;
|
||||
for (int i = 0; i < a.length(); i++) {
|
||||
equals |= a.charAt(i) ^ b.charAt(i);
|
||||
}
|
||||
|
||||
return equals == 0;
|
||||
}
|
||||
|
||||
public static char[] concat(char[] a, char[] b) {
|
||||
final char[] result = new char[a.length + b.length];
|
||||
System.arraycopy(a, 0, result, 0, a.length);
|
||||
System.arraycopy(b, 0, result, a.length, b.length);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
package org.elasticsearch.xpack.core.security.authc.support;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.common.hash.MessageDigests;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.core.security.authc.support;
|
||||
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
@ -107,7 +108,7 @@ public class UsernamePasswordToken implements AuthenticationToken {
|
||||
throw authenticationError("invalid basic authentication header encoding", e);
|
||||
}
|
||||
|
||||
int i = CharArrays.indexOf(userpasswd, ':');
|
||||
int i = indexOfColon(userpasswd);
|
||||
if (i < 0) {
|
||||
throw authenticationError("invalid basic authentication header value");
|
||||
}
|
||||
@ -121,4 +122,15 @@ public class UsernamePasswordToken implements AuthenticationToken {
|
||||
context.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue(token.username, token.password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Like String.indexOf for for an array of chars
|
||||
*/
|
||||
private static int indexOfColon(char[] array) {
|
||||
for (int i = 0; (i < array.length); i++) {
|
||||
if (array[i] == ':') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
package org.elasticsearch.xpack.core.ssl;
|
||||
|
||||
import org.elasticsearch.common.hash.MessageDigests;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -13,7 +13,7 @@ import org.elasticsearch.common.settings.Setting.Property;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.core.watcher.WatcherField;
|
||||
import org.elasticsearch.xpack.core.security.SecurityField;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
|
@ -32,7 +32,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.ActiveDirectorySessionFactorySettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.PoolingSessionFactorySettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.ssl.SSLService;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapMetaDataResolver;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
|
||||
|
@ -19,7 +19,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.LdapSessionFactorySettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.SearchGroupsResolverSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.ssl.SSLService;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapMetaDataResolver;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
|
||||
|
@ -24,7 +24,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.LdapUserSearchSessionFactorySettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.SearchGroupsResolverSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.ssl.SSLService;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession.GroupsResolver;
|
||||
|
@ -25,7 +25,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.ldap.PoolingSessionFactorySettings;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.ssl.SSLService;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapMetaDataResolver;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
|
||||
|
@ -13,7 +13,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -12,7 +12,7 @@ import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.protocol.xpack.security.User;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user