diff --git a/dev-tools/checkstyle_suppressions.xml b/dev-tools/checkstyle_suppressions.xml
index 3e774029d18..4748436a849 100644
--- a/dev-tools/checkstyle_suppressions.xml
+++ b/dev-tools/checkstyle_suppressions.xml
@@ -13,6 +13,7 @@
+
diff --git a/plugin/security/build.gradle b/plugin/security/build.gradle
index 4dfe7b27d13..12533a389b5 100644
--- a/plugin/security/build.gradle
+++ b/plugin/security/build.gradle
@@ -84,6 +84,11 @@ dependencyLicenses {
mapping from: /http.*/, to: 'httpclient'
}
+licenseHeaders {
+ // This class was sourced from apache directory studio for some microsoft-specific logic
+ excludes << 'org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtil.java'
+}
+
forbiddenPatterns {
exclude '**/*.key'
exclude '**/*.p12'
diff --git a/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolver.java b/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolver.java
index f43e1768267..8e009154cad 100644
--- a/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolver.java
+++ b/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolver.java
@@ -30,7 +30,7 @@ import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.OBJE
import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.search;
import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.searchForEntry;
import static org.elasticsearch.xpack.core.security.authc.ldap.support.SessionFactorySettings.IGNORE_REFERRAL_ERRORS_SETTING;
-
+import static org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySIDUtil.convertToString;
class ActiveDirectoryGroupsResolver implements GroupsResolver {
@@ -84,7 +84,7 @@ class ActiveDirectoryGroupsResolver implements GroupsResolver {
} else {
final byte[][] tokenGroupSIDBytes = entry.getAttributeValueByteArrays(TOKEN_GROUPS);
List orFilters = Arrays.stream(tokenGroupSIDBytes)
- .map((sidBytes) -> Filter.createEqualityFilter("objectSid", binarySidToStringSid(sidBytes)))
+ .map((sidBytes) -> Filter.createEqualityFilter("objectSid", convertToString(sidBytes)))
.collect(Collectors.toList());
listener.onResponse(Filter.createORFilter(orFilters));
}
@@ -92,46 +92,4 @@ class ActiveDirectoryGroupsResolver implements GroupsResolver {
TOKEN_GROUPS);
}
- /**
- * To better understand what the sid is and how its string representation looks like, see
- * http://blogs.msdn.com/b/alextch/archive/2007/06/18/sample-java-application-that-retrieves-group-membership-of-an-active-directory
- * -user-account.aspx
- *
- * @param SID byte encoded security ID
- */
- private static String binarySidToStringSid(byte[] SID) {
- String strSID;
-
- //convert the SID into string format
-
- long version;
- long authority;
- long count;
- long rid;
-
- strSID = "S";
- version = SID[0];
- strSID = strSID + "-" + Long.toString(version);
- authority = SID[4];
-
- for (int i = 0; i < 4; i++) {
- authority <<= 8;
- authority += SID[4 + i] & 0xFF;
- }
-
- strSID = strSID + "-" + Long.toString(authority);
- count = SID[2];
- count <<= 8;
- count += SID[1] & 0xFF;
- for (int j = 0; j < count; j++) {
- rid = SID[11 + (j * 4)] & 0xFF;
- for (int k = 1; k < 4; k++) {
- rid <<= 8;
- rid += SID[11 - k + (j * 4)] & 0xFF;
- }
- strSID = strSID + "-" + Long.toString(rid);
- }
- return strSID;
- }
-
}
diff --git a/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtil.java b/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtil.java
new file mode 100644
index 00000000000..8cb6e128d17
--- /dev/null
+++ b/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtil.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/*
+ * This code sourced from:http://svn.apache.org/repos/asf/directory/studio/tags/2.0.0.v20170904-M13/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectSidValueEditor.java
+ */
+
+package org.elasticsearch.xpack.security.authc.ldap;
+
+import org.apache.commons.codec.binary.Hex;
+
+class ActiveDirectorySIDUtil {
+
+ static String convertToString( byte[] bytes )
+ {
+ /*
+ * The binary data structure, from http://msdn.microsoft.com/en-us/library/cc230371(PROT.10).aspx:
+ * byte[0] - Revision (1 byte): An 8-bit unsigned integer that specifies the revision level of
+ * the SID structure. This value MUST be set to 0x01.
+ * byte[1] - SubAuthorityCount (1 byte): An 8-bit unsigned integer that specifies the number of
+ * elements in the SubAuthority array. The maximum number of elements allowed is 15.
+ * byte[2-7] - IdentifierAuthority (6 bytes): A SID_IDENTIFIER_AUTHORITY structure that contains
+ * information, which indicates the authority under which the SID was created. It describes the
+ * entity that created the SID and manages the account.
+ * Six element arrays of 8-bit unsigned integers that specify the top-level authority
+ * big-endian!
+ * and then - SubAuthority (variable): A variable length array of unsigned 32-bit integers that
+ * uniquely identifies a principal relative to the IdentifierAuthority. Its length is determined
+ * by SubAuthorityCount. little-endian!
+ */
+
+ if ( ( bytes == null ) || ( bytes.length < 8 ) )
+ {
+ throw new IllegalArgumentException("Invalid SID");
+ }
+
+ char[] hex = Hex.encodeHex( bytes );
+ StringBuffer sb = new StringBuffer();
+
+ // start with 'S'
+ sb.append( 'S' );
+
+ // revision
+ int revision = Integer.parseInt( new String( hex, 0, 2 ), 16 );
+ sb.append( '-' );
+ sb.append( revision );
+
+ // get count
+ int count = Integer.parseInt( new String( hex, 2, 2 ), 16 );
+
+ // check length
+ if ( bytes.length != ( 8 + count * 4 ) )
+ {
+ throw new IllegalArgumentException("Invalid SID");
+ }
+
+ // get authority, big-endian
+ long authority = Long.parseLong( new String( hex, 4, 12 ), 16 );
+ sb.append( '-' );
+ sb.append( authority );
+
+ // sub-authorities, little-endian
+ for ( int i = 0; i < count; i++ )
+ {
+ StringBuffer rid = new StringBuffer();
+
+ for ( int k = 3; k >= 0; k-- )
+ {
+ rid.append( hex[16 + ( i * 8 ) + ( k * 2 )] );
+ rid.append( hex[16 + ( i * 8 ) + ( k * 2 ) + 1] );
+ }
+
+ long subAuthority = Long.parseLong( rid.toString(), 16 );
+ sb.append( '-' );
+ sb.append( subAuthority );
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtilTests.java b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtilTests.java
new file mode 100644
index 00000000000..a3bda896bd3
--- /dev/null
+++ b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySIDUtilTests.java
@@ -0,0 +1,21 @@
+/*
+ * 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.security.authc.ldap;
+
+import org.apache.commons.codec.binary.Hex;
+import org.elasticsearch.test.ESTestCase;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class ActiveDirectorySIDUtilTests extends ESTestCase {
+
+ private static final String USER_SID_HEX ="01050000000000051500000050bd51b583ef8ebc4c75521ae9030000";
+ private static final String USER_STRING_SID = "S-1-5-21-3042032976-3163484035-441611596-1001";
+
+ public void testSidConversion() throws Exception {
+ assertThat(USER_STRING_SID, equalTo(ActiveDirectorySIDUtil.convertToString(Hex.decodeHex(USER_SID_HEX.toCharArray()))));
+ }
+}