Uploaded image for project: 'Directory Kerberos'
  1. Directory Kerberos
  2. DIRKRB-620

KerberosChannel does not read whole response

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • None
    • 2.0.0-RC1
    • changepw
    • None

    Description

      We have in production some customers who cannot change their password. In log we observe following exception:

      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)
      

      Real reason for this error is incorrect socket implementation:

      org.apache.directory.kerberos.client.KerberosChannel
                  byte[] tmp = new byte[ 1024 * 8 ];
                  while ( in.available() > 0 )
                  {
                      int read = in.read( tmp );
                      repData.put( tmp, 0, read );
                  }
      

      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:

      org.apache.directory.kerberos.client.KerberosChannel
      	    byte[] tmp = new byte[1024 * 8];
      	    int read;
      	    try {
      		while ((read = in.read(tmp)) > 0) {
      		    repData.put(tmp, 0, read);
      		}
      	    }
      	    catch (SocketTimeoutException e) {
      		// OK
      	    }
      

      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.

      Attachments

        Activity

          People

            Unassigned Unassigned
            mac.miklas Maciej Miklas
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: