Exemplo n.º 1
0
static int
parse_extensions(const char *data, size_t data_len, char **hostname) {
    size_t pos = 0;
    size_t len;

    /* Parse each 4 bytes for the extension header */
    while (pos + 4 < data_len) {
        /* Extension Length */
        len = ((unsigned char)data[pos + 2] << 8) +
            (unsigned char)data[pos + 3];

        /* Check if it's a server name extension */
        if (data[pos] == 0x00 && data[pos + 1] == 0x00) {
            /* There can be only one extension of each type, so we break
               our state and move p to beinnging of the extension here */
            if (pos + 4 + len > data_len)
                return -5;
            return parse_server_name_extension(data + pos + 4, len, hostname);
        }
        pos += 4 + len; /* Advance to the next extension header */
    }
    /* Check we ended where we expected to */
    if (pos != data_len)
        return -5;

    return -2;
}
Exemplo n.º 2
0
/* Parse a TLS packet for the Server Name Indication extension in the client hello
 * handshake, returning the first servername found (pointer to static array) */
const char *
parse_tls_header(const char* data, int data_len) {
    char tls_content_type;
    char tls_version_major;
    char tls_version_minor;
    int tls_length;
    const char* p = data;
    int len;

    /* Check that our TCP payload is at least large enough for a TLS header */
    if (data_len < TLS_HEADER_LEN)
        return NULL;

    tls_content_type = p[0];
    if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) {
        syslog(LOG_DEBUG, "Did not receive TLS handshake");
        return NULL;
    }

    tls_version_major = p[1];
    tls_version_minor = p[2];
    if (tls_version_major < 3) {
        syslog(LOG_DEBUG, "Receved pre SSL 3.0 handshake");
        return NULL;
    }

    if (tls_version_major == 3 && tls_version_minor < 1) {
        syslog(LOG_DEBUG, "Receved SSL 3.0 handshake");
        return NULL;
    }

    tls_length = ((unsigned char)p[3] << 8) + (unsigned char)p[4];
    if (data_len < tls_length + TLS_HEADER_LEN) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }



    /* Advance to first TLS payload */
    p += TLS_HEADER_LEN;

    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }

    if (*p != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
        syslog(LOG_DEBUG, "Not a client hello");
        return NULL;
    }

    /* Skip past:
       1	Handshake Type
       3	Length
       2	Version (again)
       32	Random
       to	Session ID Length
     */
    p += 38;
    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }

    len = (unsigned char)*p; /* Session ID Length */
    p += 1 + len; /* Skip session ID block */
    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }

    len = (unsigned char)*p << 8; /* Cipher Suites length high byte */
    p ++;
    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }
    len += (unsigned char)*p; /* Cipher Suites length low byte */

    p += 1 + len;

    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }
    len = (unsigned char)*p; /* Compression Methods length */

    p += 1 + len;


    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "No extensions present in TLS handshake header: %d", __LINE__);
        return NULL;
    }


    len = (unsigned char)*p << 8; /* Extensions length high byte */
    p++;
    if (p - data >= data_len) {
        syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
        return NULL;
    }
    len += (unsigned char)*p; /* Extensions length low byte */
    p++;

    while (1) {
        if (p - data + 4 >= data_len) { /* 4 bytes for the extension header */
            syslog(LOG_DEBUG, "No more TLS handshake extensions: %d", __LINE__);
            return NULL;
        }

        /* Parse our extension header */
        len = ((unsigned char)p[2] << 8) + (unsigned char)p[3]; /* Extension length */
        if (p[0] == 0x00 && p[1] == 0x00) { /* Check if it's a server name extension */
            /* There can be only one extension of each type, so we break
               our state and move p to beinnging of the extension here */
            p += 4;
            if (p - data + len > data_len) {
                syslog(LOG_DEBUG, "Did not receive complete TLS handshake header: %d", __LINE__);
                return NULL;
            }
            return parse_server_name_extension(p, len);
        }
        p += 4 + len; /* Advance to the next extension header */
    }
    return NULL;
}