Skip to content

Commit

Permalink
===BEGIN-RELEASE-NOTE===
Browse files Browse the repository at this point in the history
Addressed an issue where SCIM filter processing may not handle date literals properly when converting to an LDAP filter. This may have produced incorrect search results with date-based filtering. 
===END-RELEASE-NOTE=== 

Reviewer: Bo Li
Reviewer: Lee Saenz
Reviewer: Jacob Childress

JiraIssue:DS-12344 

SalesforceCaseNumber:00002612 

Product:ds 
Product:proxy 
Product:broker
  • Loading branch information
Richard Cardona committed Feb 11, 2015
1 parent 22bdb88 commit 9f1cf2d
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 27 deletions.
4 changes: 3 additions & 1 deletion resource/Release-Notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ https://www.unboundid.com/resources/scim

* Resolved Issues

-
- Fixed an issue where SCIM filter processing may not handle date literals
properly when converting to an LDAP filter. This may have produced
incorrect search results with date-based filtering.

---------- SCIM 1.8.1 ----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public SCIMAttributeValue toSCIMValue(final AttributeDescriptor descriptor,
return SCIMAttributeValue.createBinaryValue(byteString.getValue());

case DATETIME:
throw new IllegalArgumentException(
"The default transformation can not be used on " +
descriptor.getDataType() + " data");
case STRING:
case BOOLEAN:
case DECIMAL:
Expand All @@ -67,6 +70,9 @@ public ASN1OctetString toLDAPValue(final AttributeDescriptor descriptor,
return new ASN1OctetString(value.getBinaryValue());

case DATETIME:
throw new IllegalArgumentException(
"The default transformation can not be used on " +
descriptor.getDataType() + " data");
case STRING:
case BOOLEAN:
case DECIMAL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public ASN1OctetString toLDAPValue(final AttributeDescriptor descriptor,
switch (descriptor.getDataType())
{
case DATETIME:
final Date date = value.getDateValue();
final Date date = new SimpleValue(value.getStringValue())
.getDateValue();
return new ASN1OctetString(StaticUtils.encodeGeneralizedTime(date));

case STRING:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,40 @@ public void testFilterMappings()
assertEquals(filter.getAttributeName(), "cn");
assertEquals(filter.getAssertionValue(), "test");

filter = mapper.toLDAPFilter(
SCIMFilter.parse("name.familyName ge " +
"\"2015-02-06T09:37:57.969-07:00\""), null);
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_AND);
filter = filter.getComponents()[0];
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_GREATER_OR_EQUAL);
assertEquals(filter.getAttributeName(), "sn");
assertEquals(filter.getAssertionValue(), "2015-02-06T09:37:57.969-07:00");

filter = mapper.toLDAPFilter(
SCIMFilter.parse("name.familyName ge \"2015-02-06\""), null);
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_AND);
filter = filter.getComponents()[0];
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_GREATER_OR_EQUAL);
assertEquals(filter.getAttributeName(), "sn");
assertEquals(filter.getAssertionValue(), "2015-02-06");

filter = mapper.toLDAPFilter(
SCIMFilter.parse("meta.lastModified lt " +
"\"2015-02-06T09:37:57.969-07:00\""), null);
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_AND);
andFilter = filter.getComponents()[0];
assertEquals(andFilter.getFilterType(), Filter.FILTER_TYPE_AND);
filter = andFilter.getComponents()[0];
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_LESS_OR_EQUAL);
assertEquals(filter.getAttributeName(), "modifyTimestamp");
assertEquals(filter.getAssertionValue(), "20150206163757.969Z");
notFilter = andFilter.getComponents()[1];
assertEquals(notFilter.getFilterType(), Filter.FILTER_TYPE_NOT);
filter = notFilter.getNOTComponent();
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_EQUALITY);
assertEquals(filter.getAttributeName(), "modifyTimestamp");
assertEquals(filter.getAssertionValue(), "20150206163757.969Z");

filter = mapper.toLDAPFilter(
SCIMFilter.parse("name.familyName ge \"test\""), null);
assertEquals(filter.getFilterType(), Filter.FILTER_TYPE_AND);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
Expand All @@ -84,6 +84,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.DatatypeConverter;

import static com.unboundid.scim.sdk.SCIMConstants.SCHEMA_URI_CORE;
import static com.unboundid.scim.sdk.SCIMConstants.
Expand Down Expand Up @@ -2219,10 +2220,6 @@ public void testFiltering() throws Exception
testDS.add(generateDomainEntry("example", "dc=com"));
testDS.add(generateOrgUnitEntry("people", "dc=example,dc=com"));

final SimpleDateFormat formatter =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

long halfwayTime = 0;

// Create some users.
Expand Down Expand Up @@ -2319,7 +2316,9 @@ else if(i % 3 == 0)

//Test 'gt' (greater than)
Date halfwayDate = new Date(halfwayTime);
String formattedTime = formatter.format(halfwayDate);
Calendar calendar = Calendar.getInstance();
calendar.setTime(halfwayDate);
String formattedTime = DatatypeConverter.printDateTime(calendar);
results = userEndpoint.query("userName sw \"filterUser\" and " +
"meta.created gt \"" + formattedTime + "\"");
assertEquals(results.getTotalResults(), 5);
Expand Down
28 changes: 12 additions & 16 deletions scim-sdk/src/main/java/com/unboundid/scim/sdk/FilterParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,11 @@ else if (operator.equalsIgnoreCase("le"))
throw new IllegalArgumentException(msg);
}

final Object filterValue;
final String filterValueString;
if (!filterType.equals(SCIMFilterType.PRESENCE))
{
filterValue = readValue();
if (filterValue == null)
filterValueString = readValue();
if (filterValueString == null)
{
final String msg = String.format(
"End of input at position %d while expecting a value for " +
Expand All @@ -369,14 +369,12 @@ else if (operator.equalsIgnoreCase("le"))
}
else
{
filterValue = null;
filterValueString = null;
}

return new SCIMFilter(
filterType, filterAttribute,
filterValue != null ? filterValue.toString() : null,
(filterValue != null) && (filterValue instanceof String),
null);
filterType, filterAttribute, filterValueString,
(filterValueString != null), null);
}


Expand Down Expand Up @@ -573,17 +571,16 @@ private void rewind()


/**
* Read a value at the current position. A value can be a number, or a
* boolean value (the words true or false), or a string value in double
* Read a value at the current position. A value can be a number, a datetime
* or a boolean value (the words true or false), or a string value in double
* quotes, using the same syntax as for JSON values. Whitespace before and
* after the value is consumed. The start of the value is saved in
* {@code markPos}.
*
* @return A Boolean, Double, Integer, Long or String representing the value
* at the current position, or {@code null} if the end of the input
* has already been reached.
* @return A String representing the value at the current position, or
* {@code null} if the end of the input has already been reached.
*/
public Object readValue()
public String readValue()
{
skipWhitespace();
markPos = currentPos;
Expand Down Expand Up @@ -788,15 +785,14 @@ public Object readValue()
final String s = filterString.substring(markPos, currentPos);
skipWhitespace();
final Object value = JSONObject.stringToValue(s);

if (value.equals(JSONObject.NULL) || value instanceof String)
{
final String msg = String.format(
"Invalid filter value beginning at position %d", markPos);
throw new IllegalArgumentException(msg);
}

return value;
return s;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,7 @@ public Long getLongValue()
*/
public Date getDateValue()
{
final Calendar calendar = DatatypeConverter.parseDateTime((String)value);
calendar.setTimeZone(utcTimeZone);
return calendar.getTime();
return DatatypeConverter.parseDateTime((String)value).getTime();
}


Expand Down

0 comments on commit 9f1cf2d

Please sign in to comment.