diff --git a/libs/core/src/main/java/org/elasticsearch/common/CharArrays.java b/libs/core/src/main/java/org/elasticsearch/common/CharArrays.java
new file mode 100644
index 0000000000000..907874ca5735b
--- /dev/null
+++ b/libs/core/src/main/java/org/elasticsearch/common/CharArrays.java
@@ -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;
+ }
+}
diff --git a/libs/core/src/test/java/org/elasticsearch/common/CharArraysTests.java b/libs/core/src/test/java/org/elasticsearch/common/CharArraysTests.java
new file mode 100644
index 0000000000000..64b1ecd1f8a2d
--- /dev/null
+++ b/libs/core/src/test/java/org/elasticsearch/common/CharArraysTests.java
@@ -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()));
+ }
+}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/reload/NodesReloadSecureSettingsRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/reload/NodesReloadSecureSettingsRequest.java
index 50df7b1bb26e0..5320470d366e1 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/node/reload/NodesReloadSecureSettingsRequest.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/node/reload/NodesReloadSecureSettingsRequest.java
@@ -22,14 +22,12 @@
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 void readFrom(StreamInput in) throws IOException {
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 void readFrom(StreamInput in) throws IOException {
@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;
- }
}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/token/CreateTokenRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/token/CreateTokenRequest.java
index 5956e1a661345..fdb46711c0c59 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/token/CreateTokenRequest.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/token/CreateTokenRequest.java
@@ -15,7 +15,7 @@
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;
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/ChangePasswordRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/ChangePasswordRequest.java
index f84b133d984b6..b78b81c060080 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/ChangePasswordRequest.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/ChangePasswordRequest.java
@@ -12,7 +12,7 @@
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;
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
index f37072b9cf0fc..e704259396a34 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
@@ -8,12 +8,12 @@
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;
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/BCrypt.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/BCrypt.java
index ceb93dc4c853c..a93476bbdc8da 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/BCrypt.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/BCrypt.java
@@ -14,6 +14,7 @@
// 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 @@
* String stronger_salt = BCrypt.gensalt(12)
*
*
- * 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 static String hashpw(SecureString password, String salt) { // 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 { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/CharArrays.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/CharArrays.java deleted file mode 100644 index 26df90c31a2de..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/CharArrays.java +++ /dev/null @@ -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; - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/Hasher.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/Hasher.java index d12547bd90645..492622b2c519c 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/Hasher.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/Hasher.java @@ -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; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/UsernamePasswordToken.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/UsernamePasswordToken.java index d8e58c29d237b..1349303600884 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/UsernamePasswordToken.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/support/UsernamePasswordToken.java @@ -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 @@ private static UsernamePasswordToken extractToken(String headerValue) { 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 static void putTokenHeader(ThreadContext context, UsernamePasswordToken t 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; + } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java index d959c017e0a35..a3814a76a3e6e 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java @@ -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; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/crypto/CryptoService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/crypto/CryptoService.java index b1f3a32769ec9..a25e79ffdf66f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/crypto/CryptoService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/crypto/CryptoService.java @@ -13,7 +13,7 @@ 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; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactory.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactory.java index d175e1b229312..8107d7488188b 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactory.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactory.java @@ -32,7 +32,7 @@ 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; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactory.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactory.java index 36d14aa67c0de..70b2f0015cf7a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactory.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactory.java @@ -19,7 +19,7 @@ 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; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactory.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactory.java index 2ec87888d8c13..a3541ec2759b3 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactory.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactory.java @@ -24,7 +24,7 @@ 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; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/PoolingSessionFactory.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/PoolingSessionFactory.java index 367bd525036e2..986fa1900e7c8 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/PoolingSessionFactory.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/PoolingSessionFactory.java @@ -25,7 +25,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.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; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java index 212ee7ea499ec..6d75cf093714a 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java @@ -13,7 +13,7 @@ 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; diff --git a/x-pack/qa/security-example-spi-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java b/x-pack/qa/security-example-spi-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java index af3fb160e133f..c6502c05d252f 100644 --- a/x-pack/qa/security-example-spi-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java +++ b/x-pack/qa/security-example-spi-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java @@ -12,7 +12,7 @@ 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;