Also I would need the PDU sent back by the server that includes the control. The fact is that the RFC draft is not necessarily well implemented by Forgerock, as the value you expect to get is "0" while the draft mentions it's an OCTET STRING containing the number of seconds before expiration, which would be something like 0x04 0x01 0x00 (and even that is wrong, because the RFC draft is frankly broken, and it should be something like 0x02 0x01 0x00).

ATM, I will assume it contains a value with just 0x30 ("0").


On 25/06/2019 16:49, Jan Zelmer wrote:
Hi,

I work for a bank in germany, and we are using ForgeRock Directory Service (aka 
OpenDJ). We use it for storing authentication, authorisation and personal 
information.
We have several Java applications in our pipeline and decided to use your API 
because it is actively maintained and allows far more control than the sun JNDI 
libs.

We now got the problem, that people should be able to reset their passwords, 
without knowing their old ones. (We authenticate and authorise via other means)
So, at first we use an application bind with password-reset capabilites to 
reset and generate a temporary password, with that we bind the user and 
immediately change the password to the user desired one.
There is one problem: your api will crash during the bind request with a Null 
Pointer Exception.

I found that the api is not able to decode the control: 2.16.840.1.113730.3.4.4 
(taken from here 
https://docs.ldap.com/specs/draft-vchu-ldap-pwd-policy-00.txt); can not find 
the according factory and stop processing the message.
The control is just about the expired password.

After digging your code, I implemented missing factory and control. (and 
manually registered that factory). Now my code works :)

For the first time sending on this mail list, I don't want to attach a zip. So 
heres the code in plain text. (I can't access git, because of proxy, ssl 
interception and stuff)
Feel free to tell me your definition of Done and any comments, so I can satisfy 
those.

Kind Regards,
Jan Zelmer
Magdeburg,
Germany

Interface:
import org.apache.directory.api.ldap.model.message.Control;

public interface PasswordExpiredResponse extends Control {

     /** This control OID */
     String OID = "2.16.840.1.113730.3.4.4";

}

Implementation:
import org.apache.directory.api.ldap.model.message.controls.AbstractControl;

public class PasswordExpiredResponseImpl extends AbstractControl implements 
PasswordExpiredResponse {


     public PasswordExpiredResponseImpl() {
         super(OID);
     }


     /**
      * Return a String representing this PasswordExpiredControl.
      */
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append( "    Password Expired Response Control\n" );
         sb.append( "        oid : " ).append( getOid() ).append( '\n' );
         sb.append( "        critical : " ).append( isCritical() ).append( '\n' 
);
         return sb.toString();
     }

}

Factory:
import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.ldap.codec.api.AbstractControlFactory;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.util.Strings;

public class PasswordExpiredResponseFactory extends 
AbstractControlFactory<PasswordExpiredResponse> {

     /**
      * Creates a new instance of PasswordExpiredResponseFactory.
      *
      * @param codec The LDAP codec.
      */
     public PasswordExpiredResponseFactory( LdapApiService codec )
     {
         super( codec, PasswordExpiredResponse.OID );
     }

     /**
      * {@inheritDoc}
      */
     @Override
     public Control newControl() {
         return new PasswordExpiredResponseImpl();
     }

     /**
      * {@inheritDoc}
      */
     @Override
     public void decodeValue( Control control, byte[] controlBytes ) throws 
DecoderException {
         try {
              if (!Strings.utf8ToString( controlBytes ).equals("0")){
                  throw new DecoderException("An error occurred during decoding the 
response message: found a non zero value" +
                          "for the password expired control value. According to the 
ldap reference guide, only values of zero are valid.");
             }
         }
         catch ( RuntimeException re ) {
             throw new DecoderException( re.getMessage() );
         }
     }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to