[ 
https://issues.apache.org/jira/browse/DIRKRB-620?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15881008#comment-15881008
 ] 

Emmanuel Lecharny commented on DIRKRB-620:
------------------------------------------

Actually, we *know* the size we should read :

{code:title=org.apache.directory.kerberos.client.KerberosChannel|borderStyle=solid}
...
        else
        {
            out.write( reqData );
            out.flush();

            // Read the data length
            int len = in.readInt();
...
{code}

so we should be able to read only as many bytes as needed. We should have 
something like :

{code:title=org.apache.directory.kerberos.client.KerberosChannel|borderStyle=solid}
        else
        {
            out.write( reqData );
            out.flush();
            
            int len = in.readInt();
            
            repData = ByteBuffer.allocate( len + 4 );
            repData.putInt( len );
            
            byte[] tmp = new byte[ len ];
            int read;
            
            while ( ( read = in.read( tmp ) ) > 0) 
            {
                repData.put( tmp, 0, read );
            }
        }
{code}

I drop the try...catch, so that the IoException will be thrown back to the 
caller, and allocated just the right size for the buffer.



> KerberosChannel does not read whole response
> --------------------------------------------
>
>                 Key: DIRKRB-620
>                 URL: https://issues.apache.org/jira/browse/DIRKRB-620
>             Project: Directory Kerberos
>          Issue Type: Bug
>          Components: changepw
>            Reporter: Maciej Miklas
>
> We have in production some customers who cannot change their password. In log 
> we observe following exception:
> {noformat}
> 20.02.2017 10:59:11,987 DEBUG [http-bio-127.22.1.62-80-exec-383] 
> org.apache.directory.api.asn1.ber.Asn1Decoder - 
> <<<==========================================
> 20.02.2017 10:59:11,987 ERROR [http-bio-127.22.1.62-80-exec-383] 
> org.apache.directory.kerberos.client.KdcConnection - Authentication failed : 
> timeout occured
> 20.02.2017 10:59:11,987 WARN [http-bio-127.22.1.62-80-exec-383] 
> org.apache.directory.kerberos.client.KdcConnection - failed to change the 
> password
> org.apache.directory.shared.kerberos.exceptions.KerberosException: TimeOut 
> occured
> at 
> org.apache.directory.kerberos.client.KdcConnection._getTgt(KdcConnection.java:294)
> at 
> org.apache.directory.kerberos.client.KdcConnection.getTgt(KdcConnection.java:181)
> at 
> org.apache.directory.kerberos.client.KdcConnection.changePassword(KdcConnection.java:535)
> {noformat}
> Real reason for this error is incorrect socket implementation:
> {code:title=org.apache.directory.kerberos.client.KerberosChannel|borderStyle=solid}
>             byte[] tmp = new byte[ 1024 * 8 ];
>             while ( in.available() > 0 )
>             {
>                 int read = in.read( tmp );
>                 repData.put( tmp, 0, read );
>             }
> {code}
> You should not relay on _available()_ - it returns only assumption. In our 
> case for some users it returns 0 before whole message has been consumed.
> In order to fix it, you should first read header of the message in order to 
> figure out its size. Now use _in.read(...)_ until you consume expected amount 
> of bytes. Eventually you will run into timeout, which is fine and happens if 
> server does not keep its promise from header and cuts the message.
> I've changed code into this:
> {code:title=org.apache.directory.kerberos.client.KerberosChannel|borderStyle=solid}
>           byte[] tmp = new byte[1024 * 8];
>           int read;
>           try {
>               while ((read = in.read(tmp)) > 0) {
>                   repData.put(tmp, 0, read);
>               }
>           }
>           catch (SocketTimeoutException e) {
>               // OK
>           }
> {code}
> and customers now can change their password. Obviously this implementation is 
> *incorrect*, because it runs into timeout with every call. Bu it proves that 
> using _available()_ does not work.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to