Le 03/10/16 à 13:09, Mark Dobrinic a écrit :
> Hi api @directory.apache.org,
>
> When using Apache Directory API to send out a ModifyPassword request to
> a non-Apache LDAP server, I stumbled upon an issue when processing the
> response of the request.
>
> The specification ( https://tools.ietf.org/html/rfc3062#section-2.2 ;
> RFC 3062 section 2.2), states
>
> " Password Modify response is an ExtendedResponse where the responseName
> field is absent and the response field is optional."
>
> But PasswordModifyFactory#decorate() instead assumes there will always
> be a response field.
True !
>
>
> I was able to override PasswordModifyFactory and implement a fix by
> changing the decorate() method in the subclass, but I think it's
> actually a bug in the library, so I'd like to propose to change it in
> Apache Directory API instead.
>
> The change in PasswordModifyFactory.java is minimal:
>
> Line 133, from
> byte[] value = response.getResponseValue();
>
> ByteBuffer buffer = ByteBuffer.wrap( value );
> to
> byte[] value = response.getResponseValue();
>
> if (value == null)
> {
> value = new byte[0];
> }
>
> ByteBuffer buffer = ByteBuffer.wrap(value);
I come with a patch whch is slightly more complex. Here is the
replacement for the decorate() method :
/**
* {@inheritDoc}
*/
public PasswordModifyResponseDecorator decorate( ExtendedResponse
decoratedResponse )
{
if ( decoratedResponse instanceof PasswordModifyResponseDecorator )
{
return ( PasswordModifyResponseDecorator ) decoratedResponse;
}
if ( decoratedResponse instanceof PasswordModifyResponse )
{
return new PasswordModifyResponseDecorator( codec, (
PasswordModifyResponse ) decoratedResponse );
}
// It's an opaque extended operation
@SuppressWarnings("unchecked")
ExtendedResponseDecorator<ExtendedResponse> response = (
ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
// Decode the response, as it's an opaque operation
Asn1Decoder decoder = new Asn1Decoder();
byte[] value = response.getResponseValue();
PasswordModifyResponseContainer container = new
PasswordModifyResponseContainer();
PasswordModifyResponse pwdModifyResponse = null;
if ( value != null )
{
ByteBuffer buffer = ByteBuffer.wrap( value );
try
{
decoder.decode( buffer, container );
pwdModifyResponse = container.getPwdModifyResponse();
// Now, update the created response with what we got
from the extendedResponse
pwdModifyResponse.getLdapResult().setResultCode(
response.getLdapResult().getResultCode() );
pwdModifyResponse.getLdapResult().setDiagnosticMessage(
response.getLdapResult().getDiagnosticMessage() );
pwdModifyResponse.getLdapResult().setMatchedDn(
response.getLdapResult().getMatchedDn() );
pwdModifyResponse.getLdapResult().setReferral(
response.getLdapResult().getReferral() );
}
catch ( DecoderException de )
{
StringWriter sw = new StringWriter();
de.printStackTrace( new PrintWriter( sw ) );
String stackTrace = sw.toString();
// Error while decoding the value.
pwdModifyResponse = new PasswordModifyResponseImpl(
decoratedResponse.getMessageId(),
ResultCodeEnum.OPERATIONS_ERROR,
stackTrace );
}
}
else
{
pwdModifyResponse = new PasswordModifyResponseImpl();
// Now, update the created response with what we got from
the extendedResponse
pwdModifyResponse.getLdapResult().setResultCode(
response.getLdapResult().getResultCode() );
pwdModifyResponse.getLdapResult().setDiagnosticMessage(
response.getLdapResult().getDiagnosticMessage() );
pwdModifyResponse.getLdapResult().setMatchedDn(
response.getLdapResult().getMatchedDn() );
pwdModifyResponse.getLdapResult().setReferral(
response.getLdapResult().getReferral() );
}
PasswordModifyResponseDecorator decorated = new
PasswordModifyResponseDecorator( codec, pwdModifyResponse );
Control ppolicyControl = response.getControl( PasswordPolicy.OID );
if ( ppolicyControl != null )
{
decorated.addControl( ppolicyControl );
}
return decorated;
}
Can you test it on your side (I'm afraid I don't have a test case for
this atm)
Can you also create a JIRA for the bug you have found, so that we have
it listed when we will cut a release ?
Many thanks !