Hi Thierry,

On Sat, Feb 25, 2017 at 01:01:54PM +0100, thierry.fourn...@arpalert.org wrote:
> The patch implementing this idea is in attachment. It returns the
> client-hello cioher list as binary, hexadecimal string, xxh64 and with
> the decoded ciphers.

Is this supposed to be the last version ? I'm asking because it's still
bogus regarding the length calculation :

> +static inline
> +void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
> +                                const void *buf, size_t len,
> +                                struct ssl_capture *capture)
> +{
> +     unsigned char *msg;
> +     unsigned char *end;
> +     unsigned int rec_len;
> +
> +     /* This function is called for "from client" and "to server"
> +      * connections. The combination of write_p == 0 and content_type == 22
> +      * is only avalaible during "from client" connection.
> +      */
> +
> +     /* "write_p" is set to 0 is the bytes are received messages,
> +      * otherwise it is set to 1.
> +      */
> +     if (write_p != 0)
> +             return;
> +
> +     /* content_type contains the type of message received or sent
> +      * according with the SSL/TLS protocol spec. This message is
> +      * encoded with one byte. The value 256 (two bytes) is used
> +      * for designing the SSL/TLS record layer. According with the
> +      * rfc6101, the expected message (other than 256) are:
> +      *  - change_cipher_spec(20)
> +      *  - alert(21)
> +      *  - handshake(22)
> +      *  - application_data(23)
> +      *  - (255)
> +      * We are interessed by the handshake and specially the client
> +      * hello.
> +      */
> +     if (content_type != 22)
> +             return;
> +
> +     /* The message length is at least 4 bytes, containing the
> +      * message type and the message length.
> +      */
> +     if (len < 4)
> +             return;
> +
> +     /* First byte of the handshake message id the type of
> +      * message. The konwn types are:
> +      *  - hello_request(0)
> +      *  - client_hello(1)
> +      *  - server_hello(2)
> +      *  - certificate(11)
> +      *  - server_key_exchange (12)
> +      *  - certificate_request(13)
> +      *  - server_hello_done(14)
> +      * We are interested by the client hello.
> +      */
> +     msg = (unsigned char *)buf;
> +     if (msg[0] != 1)
> +             return;
> +
> +     /* Next three bytes are the length of the message. The total length
> +      * must be this decoded length + 4. If the length given as argument
> +      * is not the same, we abort the protocol dissector.
> +      */
> +     rec_len = (msg[1] << 3) + (msg[2] << 2) + msg[3];

Here. The correct statement is :

        rec_len = msg[1] * 65536 + msg[2] * 256 + msg[3];

(or << 16, << 8)


> +     if (len < rec_len + 4)
> +             return;
> +     msg += 4;
> +     end = msg + rec_len;
> +     if (end <= msg)
> +             return;

This one looks wrong as it prevents rec_len from being NULL, the
correct overflow test is if (end < msg).

> +     /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
> +      * for minor, the random, composed by 4 bytes for the unix time and
> +      * 28 bytes for unix payload, and them 1 byte for the session id. So
> +      * we jump 1 + 1 + 4 + 28 + 1 bytes.
> +      */
> +     msg += 1 + 1 + 4 + 28 + 1;
> +     if (msg >= end)
> +             return;

It seems like this one should be "if (msg > end)" given that it accounts for
a length. However given that it's covered by the next one, maybe it can
simply be dropped.

> +     /* Next two bytes are the ciphersuite length. */
> +     if (msg + 2 > end)
> +             return;
> +     rec_len = (msg[0] << 2) + msg[1];

Wrong shift again.

> +     msg += 2;
> +     if (msg + rec_len > end || msg + rec_len < msg)
> +             return;
> +
> +     /* Compute the xxh64 of the ciphersuite. */
> +     capture->xxh64 = XXH64(msg, rec_len, 0);
> +
> +     /* Capture the ciphersuite. */
> +     capture->ciphersuite_len = rec_len;
> +     if (capture->ciphersuite_len > global_ssl.capture_cipherlist)
> +             capture->ciphersuite_len = global_ssl.capture_cipherlist;
> +     memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
> +}
> +
 
The rest looks OK though. Just let me know.

Thanks,
Willy

Reply via email to