Return-Path: Delivered-To: apmail-directory-dev-archive@www.apache.org Received: (qmail 62107 invoked from network); 23 Nov 2005 06:34:51 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 23 Nov 2005 06:34:51 -0000 Received: (qmail 87839 invoked by uid 500); 23 Nov 2005 06:34:50 -0000 Delivered-To: apmail-directory-dev-archive@directory.apache.org Received: (qmail 87797 invoked by uid 500); 23 Nov 2005 06:34:49 -0000 Mailing-List: contact dev-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Apache Directory Developers List" Delivered-To: mailing list dev@directory.apache.org Received: (qmail 87786 invoked by uid 99); 23 Nov 2005 06:34:49 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 22 Nov 2005 22:34:49 -0800 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=DNS_FROM_RFC_ABUSE X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [206.190.38.61] (HELO web50307.mail.yahoo.com) (206.190.38.61) by apache.org (qpsmtpd/0.29) with SMTP; Tue, 22 Nov 2005 22:36:21 -0800 Received: (qmail 91422 invoked by uid 60001); 23 Nov 2005 06:34:27 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com; h=Message-ID:Received:Date:From:Subject:To:MIME-Version:Content-Type:Content-Transfer-Encoding; b=reSRBo2sK6vZFX4cje2kjdewM2sXZfjRDiUll/Q/EjeqdWcTyOVAjXciVF3nHnidyAM+G63lEK25oAhcmTGtA5RedONpRm7iLodQ72b8akOiWKF72bFnXi8o/STAJTURqPXEgAd5s1refy2LTNqHmKFQV3a86dmUICBvlKHG6+k= ; Message-ID: <20051123063427.91420.qmail@web50307.mail.yahoo.com> Received: from [155.35.248.112] by web50307.mail.yahoo.com via HTTP; Tue, 22 Nov 2005 22:34:27 PST Date: Tue, 22 Nov 2005 22:34:27 -0800 (PST) From: Van Nhu Subject: The Twix Codec for LDAP Controls To: dev@directory.apache.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="0-1363371442-1132727667=:91402" Content-Transfer-Encoding: 8bit X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N --0-1363371442-1132727667=:91402 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Content-Id: Content-Disposition: inline Hi all, According to the RFC 2251, the "controlType" attribute of an LDAP Control "...MUST be a UTF-8 encoded dotted-decimal representation of an OBJECT IDENTIFIER which uniquely identifies the control". Essentially, this means that the "controlType" attribute is an OCTET STRING and should be treated as such. However, the Twix ASN1 codec is treating this attribute as an OBJECT IDENTIFIER. This results in incorrect decoding/decoding of LDAP Controls. I suggest that we change the type of the "controlType" attribute of the org.apache.asn1new.ldap.pojo.Control class from OID to LdapString to fix the problem. A patch, which includes a test for exposing the problem and validating the fix, is attached for your reference. With Regards, Van __________________________________ Yahoo! FareChase: Search multiple travel sites in one click. http://farechase.yahoo.com --0-1363371442-1132727667=:91402 Content-Type: text/plain; name="LDAPControlCodec.patch" Content-Description: 4069829843-LDAPControlCodec.patch Content-Disposition: inline; filename="LDAPControlCodec.patch" Index: apache2-provider/src/test/org/apache/asn1new/ldap/codec/SearchRequestTest.java =================================================================== --- apache2-provider/src/test/org/apache/asn1new/ldap/codec/SearchRequestTest.java (revision 348378) +++ apache2-provider/src/test/org/apache/asn1new/ldap/codec/SearchRequestTest.java (working copy) @@ -29,6 +29,7 @@ import org.apache.asn1new.ldap.pojo.AttributeValueAssertion; import org.apache.asn1new.ldap.pojo.LdapMessage; import org.apache.asn1new.ldap.pojo.SearchRequest; +import org.apache.asn1new.ldap.pojo.Control; import org.apache.asn1new.ldap.pojo.filters.AndFilter; import org.apache.asn1new.ldap.pojo.filters.AttributeValueAssertionFilter; import org.apache.asn1new.ldap.pojo.filters.NotFilter; @@ -46,7 +47,105 @@ * @author Apache Directory Project */ public class SearchRequestTest extends TestCase { + /** + * Test the decoding of a SearchRequest with controls. + */ + public void testDecodeSearchRequestWithControls() + { + byte[] asn1BER = new byte[] + { + 0x30, 0x7f, + 0x02, 0x01, 0x04, // messageID + 0x63, 0x33, + 0x04, 0x13, + 0x64, 0x63, 0x3d, 0x6d, 0x79, 0x2d, 0x64, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, // baseObject: dc=my-domain,dc=com + 0x0a, 0x01, 0x02, // scope: subtree + 0x0a, 0x01, 0x03, // derefAliases: derefAlways + 0x02, 0x01, 0x00, // sizeLimit: 0 + 0x02, 0x01, 0x00, // timeLimit: 0 + 0x01, 0x01, 0x00, // typesOnly: false + (byte)0x87, 0x0b, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, // filter: (objectClass=*) + 0x30, 0x00, + (byte)0xa0, 0x45, // controls + 0x30, 0x28, + 0x04, 0x16, + 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, + 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, + 0x31, 0x39, // control oid: 1.2.840.113556.1.4.319 + 0x01, 0x01, (byte)0xff, // criticality: false + 0x04, 0x0b, + 0x30, 0x09, 0x02, 0x01, 0x02, 0x04, 0x04, 0x47, 0x00, 0x00, 0x00, // value: pageSize=2 + 0x30, 0x19, + 0x04, 0x17, + 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, + 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, + 0x34, 0x2e, 0x32 // control oid: 2.16.840.1.113730.3.4.2 + }; + + Asn1Decoder ldapDecoder = new LdapDecoder(); + + ByteBuffer stream = ByteBuffer.allocate( asn1BER.length ); + stream.put( asn1BER ); + String decodedPdu = StringUtils.dumpBytes( stream.array() ); + stream.flip(); + + IAsn1Container ldapMessageContainer = new LdapMessageContainer(); + + try + { + ldapDecoder.decode( stream, ldapMessageContainer ); + } + catch ( DecoderException de ) + { + de.printStackTrace(); + Assert.fail( de.getMessage() ); + } + + LdapMessage message = ( ( LdapMessageContainer ) ldapMessageContainer ).getLdapMessage(); + Assert.assertEquals( 4, message.getMessageId() ); + Assert.assertEquals( 2, message.getControls().size() ); + + // this is a constant in Java 5 API + String pagedResultsControlOID = "1.2.840.113556.1.4.319"; + Control pagedResultsControl = message.getControls( 0 ); + Assert.assertEquals( pagedResultsControlOID, pagedResultsControl.getControlType() ); + Assert.assertTrue( pagedResultsControl.getCriticality() ); + + // this is a constant in Java 5 API + String manageReferralControlOID = "2.16.840.1.113730.3.4.2"; + Control manageReferralControl = message.getControls( 1 ); + Assert.assertEquals( manageReferralControlOID, manageReferralControl.getControlType() ); + + SearchRequest sr = message.getSearchRequest(); + Assert.assertEquals( "dc=my-domain,dc=com", sr.getBaseObject() ); + Assert.assertEquals( LdapConstants.SCOPE_WHOLE_SUBTREE, sr.getScope() ); + Assert.assertEquals( LdapConstants.DEREF_ALWAYS, sr.getDerefAliases() ); + Assert.assertEquals( 0, sr.getSizeLimit() ); + Assert.assertEquals( 0, sr.getTimeLimit() ); + Assert.assertEquals( false, sr.isTypesOnly() ); + + Assert.assertTrue( sr.getFilter() instanceof PresentFilter ); + Assert.assertEquals ( "objectClass", + ( (PresentFilter) sr.getFilter() ).getAttributeDescription().getString()); + + // Check the encoding + try + { + ByteBuffer bb = message.encode( null ); + String encodedPdu = StringUtils.dumpBytes( bb.array() ); + Assert.assertEquals(encodedPdu, decodedPdu ); + } + catch ( EncoderException ee ) + { + ee.printStackTrace(); + Assert.fail( ee.getMessage() ); + } + } + + /** * Test the decoding of a SearchRequest with no controls. * The search filter is : * (&(|(objectclass=top)(ou=contacts))(!(objectclass=ttt))) Index: apache2-provider/src/main/java/org/apache/asn1new/ldap/pojo/Control.java =================================================================== --- apache2-provider/src/main/java/org/apache/asn1new/ldap/pojo/Control.java (revision 348378) +++ apache2-provider/src/main/java/org/apache/asn1new/ldap/pojo/Control.java (working copy) @@ -20,11 +20,11 @@ import java.nio.ByteBuffer; import org.apache.asn1new.Asn1Object; +import org.apache.asn1new.ldap.codec.primitives.LdapString; import org.apache.asn1.codec.EncoderException; import org.apache.asn1new.ber.tlv.Length; import org.apache.asn1new.ber.tlv.UniversalTag; import org.apache.asn1new.ber.tlv.Value; -import org.apache.asn1new.primitives.OID; import org.apache.asn1.codec.util.StringUtils; @@ -37,8 +37,12 @@ { //~ Instance fields ---------------------------------------------------------------------------- - /** The control type */ - private OID controlType; + /** + * The control type as an UTF-8 encoded dotted-decimal + * representation of an OBJECT IDENTIFIER which uniquely + * identifies the control + */ + private LdapString controlType; /** The criticality (default value is false) */ private boolean criticality = false; @@ -68,7 +72,7 @@ * * @param controlType An OID to store */ - public void setControlType( OID controlType ) + public void setControlType( LdapString controlType ) { this.controlType = controlType; } @@ -143,7 +147,7 @@ public int computeLength() { // The controlType - int controlTypeLengh = controlType.getOIDLength(); + int controlTypeLengh = controlType.getNbBytes(); controlLength = 1 + Length.getNbBytes( controlTypeLengh ) + controlTypeLengh; // The criticality, only if true @@ -190,7 +194,7 @@ } // The control type - Value.encode( buffer, controlType ); + Value.encode( buffer, controlType.getBytes() ); // The control criticality, if true if ( criticality == true ) Index: apache2-provider/src/main/java/org/apache/asn1new/ldap/codec/grammar/LdapControlGrammar.java =================================================================== --- apache2-provider/src/main/java/org/apache/asn1new/ldap/codec/grammar/LdapControlGrammar.java (revision 348378) +++ apache2-provider/src/main/java/org/apache/asn1new/ldap/codec/grammar/LdapControlGrammar.java (working copy) @@ -28,9 +28,10 @@ import org.apache.asn1new.util.BooleanDecoder; import org.apache.asn1new.util.BooleanDecoderException; import org.apache.asn1.codec.util.StringUtils; -import org.apache.asn1new.primitives.OID; import org.apache.asn1new.ldap.codec.LdapConstants; import org.apache.asn1new.ldap.codec.LdapMessageContainer; +import org.apache.asn1new.ldap.codec.primitives.LdapString; +import org.apache.asn1new.ldap.codec.primitives.LdapStringEncodingException; import org.apache.asn1new.ldap.pojo.Control; import org.apache.asn1new.ldap.pojo.LdapMessage; import org.slf4j.Logger; @@ -189,7 +190,15 @@ } else { - control.setControlType( new OID( tlv.getValue().getData() ) ); + try + { + control.setControlType( new LdapString(tlv.getValue().getData() ) ); + } + catch (LdapStringEncodingException e) + { + log.error( "Error encoding control type", e ); + throw new DecoderException( "Error encoding control type: " + e ); + } } if ( log.isDebugEnabled() ) --0-1363371442-1132727667=:91402--