[
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)