Esempio n. 1
0
int verify(SSL *ssl, const char *hostname, int port,
        const neo4j_config_t *config, uint_fast32_t flags,
        neo4j_logger_t *logger)
{
    X509 *cert = SSL_get_peer_certificate(ssl);
    if (cert == NULL)
    {
        errno = NEO4J_TLS_VERIFICATION_FAILED;
        return -1;
    }

    int result = -1;

    char fingerprint[SHA512_DIGEST_LENGTH * 2];
    if (cert_fingerprint(cert, fingerprint, sizeof(fingerprint), logger))
    {
        goto cleanup;
    }

    neo4j_log_debug(logger, "server cert fingerprint: %s", fingerprint);

    long verification = SSL_get_verify_result(ssl);
    switch (verification)
    {
    case X509_V_OK:
        // TODO: verify that the certificate matches hostname/port
        neo4j_log_debug(logger, "certificate verified using CA");
        result = 0;
        goto cleanup;
    // TODO: check other verification codes for unacceptable certificates
    default:
        break;
    }

    if (!(config->trust_known))
    {
        errno = NEO4J_TLS_VERIFICATION_FAILED;
        goto cleanup;
    }

    result = neo4j_check_known_hosts(hostname, port, fingerprint, config, flags);
    if (result > 0)
    {
        errno = NEO4J_TLS_VERIFICATION_FAILED;
        result = -1;
    }

cleanup:
    X509_free(cert);
    return result;
}
Esempio n. 2
0
int neo4j_connect_tcp_socket(const char *hostname, const char *servname,
        const neo4j_config_t *config, neo4j_logger_t *logger)
{
    REQUIRE(hostname != NULL, -1);

    struct addrinfo hints;
    struct addrinfo *candidate_addresses = NULL;
    int err = 0;

    init_getaddrinfo_hints(&hints);
    err = getaddrinfo(hostname, servname, &hints, &candidate_addresses);
    if (err)
    {
        errno = NEO4J_UNKNOWN_HOST;
        return -1;
    }

    int fd = -1;
    struct addrinfo *addr;
    for (addr = candidate_addresses; addr != NULL; addr = addr->ai_next)
    {
        fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (fd < 0)
        {
            if (!unsupported_sock_error(errno))
                continue;
            neo4j_log_error_errno(logger, "socket");
            freeaddrinfo(candidate_addresses);
            return -1;
        }

        set_socket_options(fd, config, logger);

        char hostnum[NI_MAXHOST];
        char servnum[NI_MAXSERV];
        err = getnameinfo(addr->ai_addr, addr->ai_addrlen,
                hostnum, sizeof(hostnum), servnum, sizeof(servnum),
                NI_NUMERICHOST | NI_NUMERICSERV);
        if (err)
        {
            neo4j_log_error(logger, "getnameinfo: %s", gai_strerror(err));
            freeaddrinfo(candidate_addresses);
            errno = NEO4J_UNEXPECTED_ERROR;
            return -1;
        }

        neo4j_log_debug(logger, "attempting connection to %s [%s]",
                hostnum, servnum);

        err = connect_with_timeout(fd, addr->ai_addr, addr->ai_addrlen,
                    config->connect_timeout, logger);
        if (err == 0)
        {
            break;
        }
        else if (err < 0)
        {
            return -1;
        }

        char ebuf[256];
        neo4j_log_info(logger, "connection to %s [%s] failed: %s",
                hostnum, servnum, neo4j_strerror(errno, ebuf, sizeof(ebuf)));

        close(fd);
        fd = -1;
    }

    freeaddrinfo(candidate_addresses);
    return fd;
}