* Remove copy-pasted code

An examination of the x-pack source code revealed copy-pasted code
in ActiveDirectoryGroupsResolver in the binarySidToStringSid
method.  I have replaced this with an apache2 implementation from
the apache directory studio project.  Furthermore, I have added
a test that leverages a real binary/string SID pair retrieved
from an active directory domain controller.  The apache2-based
implementation is exempt for the license checker.

Original commit: elastic/x-pack-elasticsearch@81a7471261
This commit is contained in:
tomcallahan 2018-04-19 09:12:15 -04:00 committed by GitHub
parent 650b80a982
commit 8d6f36c507
5 changed files with 112 additions and 44 deletions

View File

@ -13,6 +13,7 @@
<suppress files="plugin[/\\]core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]persistent[/\\]CompletionPersistentTaskAction.java" checks="LineLength" /> <suppress files="plugin[/\\]core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]persistent[/\\]CompletionPersistentTaskAction.java" checks="LineLength" />
<suppress files="plugin[/\\]security[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]Security.java" checks="LineLength" /> <suppress files="plugin[/\\]security[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]Security.java" checks="LineLength" />
<suppress files="plugin[/\\]security[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]authc[/\\]Realms.java" checks="LineLength" /> <suppress files="plugin[/\\]security[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]authc[/\\]Realms.java" checks="LineLength" />
<suppress files="plugin[/\\]security[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]authc[/\\]ldap[/\\]ActiveDirectorySIDUtil.java" checks="LineLength" />
<suppress files="plugin[/\\]ml[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]ml[/\\]integration[/\\]TooManyJobsIT.java" checks="LineLength" /> <suppress files="plugin[/\\]ml[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]ml[/\\]integration[/\\]TooManyJobsIT.java" checks="LineLength" />
<suppress files="plugin[/\\]core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]persistent[/\\]TestPersistentTasksPlugin.java" checks="LineLength" /> <suppress files="plugin[/\\]core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]persistent[/\\]TestPersistentTasksPlugin.java" checks="LineLength" />
<suppress files="plugin[/\\]security[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]action[/\\]user[/\\]TransportGetUsersActionTests.java" checks="LineLength" /> <suppress files="plugin[/\\]security[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]xpack[/\\]security[/\\]action[/\\]user[/\\]TransportGetUsersActionTests.java" checks="LineLength" />

View File

@ -84,6 +84,11 @@ dependencyLicenses {
mapping from: /http.*/, to: 'httpclient' 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 { forbiddenPatterns {
exclude '**/*.key' exclude '**/*.key'
exclude '**/*.p12' exclude '**/*.p12'

View File

@ -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.search;
import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.searchForEntry; 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.core.security.authc.ldap.support.SessionFactorySettings.IGNORE_REFERRAL_ERRORS_SETTING;
import static org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySIDUtil.convertToString;
class ActiveDirectoryGroupsResolver implements GroupsResolver { class ActiveDirectoryGroupsResolver implements GroupsResolver {
@ -84,7 +84,7 @@ class ActiveDirectoryGroupsResolver implements GroupsResolver {
} else { } else {
final byte[][] tokenGroupSIDBytes = entry.getAttributeValueByteArrays(TOKEN_GROUPS); final byte[][] tokenGroupSIDBytes = entry.getAttributeValueByteArrays(TOKEN_GROUPS);
List<Filter> orFilters = Arrays.stream(tokenGroupSIDBytes) List<Filter> orFilters = Arrays.stream(tokenGroupSIDBytes)
.map((sidBytes) -> Filter.createEqualityFilter("objectSid", binarySidToStringSid(sidBytes))) .map((sidBytes) -> Filter.createEqualityFilter("objectSid", convertToString(sidBytes)))
.collect(Collectors.toList()); .collect(Collectors.toList());
listener.onResponse(Filter.createORFilter(orFilters)); listener.onResponse(Filter.createORFilter(orFilters));
} }
@ -92,46 +92,4 @@ class ActiveDirectoryGroupsResolver implements GroupsResolver {
TOKEN_GROUPS); 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;
}
} }

View File

@ -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();
}
}

View File

@ -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()))));
}
}