Exemple #1
0
int openssl_error(neo4j_logger_t *logger, uint_fast8_t level,
        const char *file, unsigned int line)
{
    unsigned long code = ERR_get_error();
    if (code == 0)
    {
        neo4j_log_error(logger, "OpenSSL error not available (%s:%d)",
                file, line);
        return NEO4J_UNEXPECTED_ERROR;
    }

    if (ERR_get_error() != 0)
    {
        neo4j_log_error(logger, "OpenSSL error stack too deep (%s:%d)",
                file, line);
        return NEO4J_UNEXPECTED_ERROR;
    }

    char ebuf[256];
    ERR_error_string_n(code, ebuf, sizeof(ebuf));
    neo4j_log(logger, level, "OpenSSL error: %lu:%s:%s:%s", code,
            ERR_lib_error_string(code),
            ERR_func_error_string(code),
            ERR_reason_error_string(code));

    return NEO4J_UNEXPECTED_ERROR;
}
Exemple #2
0
int sha512_digest(unsigned char *buf, unsigned int *np, const void *s, size_t n,
        neo4j_logger_t *logger)
{
    const EVP_MD *md = EVP_get_digestbyname("SHA512");
    assert(md != NULL);
    if (md == NULL)
    {
        neo4j_log_error(logger, "OpenSSL failed to load digest SHA512");
        errno = NEO4J_UNEXPECTED_ERROR;
        return -1;
    }

    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
    assert(mdctx != NULL);
    if (mdctx == NULL)
    {
        neo4j_log_error(logger, "OpenSSL `EVP_MD_CTX_create` failed");
        errno = NEO4J_UNEXPECTED_ERROR;
        return -1;
    }
    if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
    {
        neo4j_log_error(logger, "OpenSSL `EVP_DigestInit_ex` failed");
        errno = NEO4J_UNEXPECTED_ERROR;
        goto failure;
    }
    if (EVP_DigestUpdate(mdctx, s, n) != 1)
    {
        neo4j_log_error(logger, "OpenSSL `EVP_DigestUpdate` failed");
        errno = NEO4J_UNEXPECTED_ERROR;
        goto failure;
    }
    if (EVP_DigestFinal_ex(mdctx, buf, np) != 1)
    {
        neo4j_log_error(logger, "OpenSSL `EVP_DigestFinal` failed");
        errno = NEO4J_UNEXPECTED_ERROR;
        goto failure;
    }
    EVP_MD_CTX_destroy(mdctx);
    return 0;

    int errsv;
failure:
    errsv = errno;
    EVP_MD_CTX_destroy(mdctx);
    errno = errsv;
    return -1;
}
Exemple #3
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;
}
int append_result(run_result_stream_t *results,
        const neo4j_value_t *argv, uint16_t argc)
{
    assert(results != NULL);
    neo4j_session_t *session = results->session;

    if (argc != 1)
    {
        neo4j_log_error(results->logger,
                "invalid number of fields in RECORD message received in %p",
                (void *)session);
        errno = EPROTO;
        return -1;
    }

    assert(argv != NULL);

    neo4j_type_t arg_type = neo4j_type(argv[0]);
    if (arg_type != NEO4J_LIST)
    {
        neo4j_log_error(results->logger,
                "invalid field in RECORD message received in %p"
                " (got %s, expected List)", (void *)session,
                neo4j_typestr(arg_type));
        errno = EPROTO;
        return -1;
    }

    if (!results->streaming)
    {
        // discard memory for the record
        neo4j_mpool_drain(&(results->record_mpool));
        return 0;
    }

    assert(session != NULL);
    neo4j_config_t *config = neo4j_session_config(session);

    result_record_t *record = neo4j_mpool_calloc(&(results->record_mpool),
            1, sizeof(result_record_t));
    if (record == NULL)
    {
        return -1;
    }

    record->refcount = 1;

    // save memory for the record with the record
    record->mpool = results->record_mpool;
    results->record_mpool = neo4j_std_mpool(config);

    record->list = argv[0];
    record->next = NULL;

    neo4j_result_t *result = &(record->_result);
    result->field = run_result_field;
    result->retain = run_result_retain;
    result->release = run_result_release;

    if (results->records == NULL)
    {
        assert(results->records_tail == NULL);
        results->records = record;
        results->records_tail = record;
    }
    else
    {
        results->records_tail->next = record;
        results->records_tail = record;
    }

    if (results->awaiting_records > 0)
    {
        --(results->awaiting_records);
    }

    return 0;
}
int stream_end(run_result_stream_t *results, neo4j_message_type_t type,
        const char *src_message_type, const neo4j_value_t *argv, uint16_t argc)
{
    neo4j_logger_t *logger = results->logger;
    neo4j_session_t *session = results->session;

    if (session == NULL)
    {
        return 0;
    }

    neo4j_config_t *config = neo4j_session_config(session);

    if (type == NEO4J_IGNORED_MESSAGE)
    {
        if (results->failure == 0)
        {
            neo4j_log_error(logger,
                    "unexpected IGNORED message received in %p"
                    " (in response to %s, yet no failure occurred)",
                    (void *)session, src_message_type);
            set_failure(results, errno = EPROTO);
            return -1;
        }
        return 0;
    }

    assert(results->failure == 0);

    if (type == NEO4J_FAILURE_MESSAGE)
    {
        return set_eval_failure(results, src_message_type, argv, argc);
    }
    if (type != NEO4J_SUCCESS_MESSAGE)
    {
        neo4j_log_error(logger,
                "unexpected %s message received in %p"
                " (in response to %s)", neo4j_message_type_str(type),
                (void *)session, src_message_type);
        set_failure(results, errno = EPROTO);
        return -1;
    }

    char description[128];
    snprintf(description, sizeof(description), "SUCCESS in %p (response to %s)",
            (void *)session, src_message_type);

    const neo4j_value_t *metadata = neo4j_validate_metadata(argv, argc,
            description, logger);
    if (metadata == NULL)
    {
        set_failure(results, errno);
        return -1;
    }

    if (neo4j_log_is_enabled(logger, NEO4J_LOG_TRACE))
    {
        neo4j_metadata_log(logger, NEO4J_LOG_TRACE, description, *metadata);
    }

    results->statement_type =
        neo4j_meta_statement_type(*metadata, description, logger);
    if (results->statement_type < 0)
    {
        set_failure(results, errno);
        return -1;
    }

    results->statement_plan = neo4j_meta_plan(*metadata, description,
            config, logger);
    if (results->statement_plan == NULL && errno != NEO4J_NO_PLAN_AVAILABLE)
    {
        set_failure(results, errno);
        return -1;
    }

    if (neo4j_meta_update_counts(&(results->update_counts), *metadata,
                description, logger))
    {
        set_failure(results, errno);
        return -1;
    }

    return 0;
}
int run_callback(void *cdata, neo4j_message_type_t type,
        const neo4j_value_t *argv, uint16_t argc)
{
    assert(cdata != NULL);
    assert(argc == 0 || argv != NULL);
    run_result_stream_t *results = (run_result_stream_t *)cdata;
    neo4j_logger_t *logger = results->logger;
    neo4j_session_t *session = results->session;

    results->starting = false;
    --(results->refcount);

    if (session == NULL)
    {
        return 0;
    }

    if (type == NEO4J_FAILURE_MESSAGE)
    {
        return set_eval_failure(results, "RUN", argv, argc);
    }
    if (type == NEO4J_IGNORED_MESSAGE)
    {
        if (results->failure == 0)
        {
            set_failure(results, NEO4J_STATEMENT_PREVIOUS_FAILURE);
        }
        return 0;
    }

    char description[128];
    snprintf(description, sizeof(description), "%s in %p (response to RUN)",
            neo4j_message_type_str(type), (void *)session);

    if (type != NEO4J_SUCCESS_MESSAGE)
    {
        neo4j_log_error(logger, "unexpected %s", description);
        set_failure(results, errno = EPROTO);
        return -1;
    }

    const neo4j_value_t *metadata = neo4j_validate_metadata(argv, argc,
            description, logger);
    if (metadata == NULL)
    {
        set_failure(results, errno);
        return -1;
    }

    if (neo4j_log_is_enabled(session->logger, NEO4J_LOG_TRACE))
    {
        neo4j_metadata_log(logger, NEO4J_LOG_TRACE, description, *metadata);
    }

    if (neo4j_meta_fieldnames(&(results->fields), &(results->nfields),
                *metadata, &(results->mpool), description, logger))
    {
        set_failure(results, errno);
        return -1;
    }
    return 0;
}