Пример #1
0
bool
UDPSocket::connect(const am::UDPReadDesc &desc)
{
	m_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (m_socket < 0)
	{
		AM_LOG_ERROR("Unable to create socket");
		return false;
	}

	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	addr.sin_port = htons(desc.port);

	if (bind(m_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		AM_LOG_ERROR("Failed to bind socket to port: %d, %s", addr.sin_port, StringUtils::errorCodeToString(errno).c_str());

		closeSocket();
		return false;
	}

	AM_LOG_SUCCESS("Connected to UDPSocket: %d", addr.sin_port);
	return true;
}
Пример #2
0
/**
 * This is the simplest of tests to check we can log things without crashing.
 *
 * In fact, because of the way logging works (differently) in test mode than it does in "agent mode"
 * all we're really doing here is to test that logging in test mode isn't broken.  This may or may not
 * bear any relation to whether logging works for the rest of the time.
 */
void test_logging_in_unit_test_mode(void** state) {
    
    static const char* text1 = "Now is the winter of our discontent,";
    static const char* text2 = "Made glorious summer by this son of York";
        
    AM_LOG_INFO(0, "instance id is zero and no args");
    AM_LOG_INFO(0, "instance id is zero and incorrect args", text1);
    AM_LOG_INFO(0, "instance id is zero and more incorrect args", text1, text2);

    /* we're testing this will not crash */
    AM_LOG_INFO(0, NULL, text1, text2);

    /* this will not appear, since the instance is greater than zero, but it should not crash either */
    AM_LOG_ERROR(10, "%s %s", text1, text2);

    AM_LOG_INFO(0, "%s %s", text1, text2);
    AM_LOG_WARNING(0, "%s %s", text1, text2);
    AM_LOG_ERROR(0, "%s %s", text1, text2);
    AM_LOG_DEBUG(0, "%s %s", text1, text2);
    AM_LOG_AUDIT(0, "%s %s", text1, text2);

    AM_LOG_ALWAYS(0, "%s %s", text1, text2);
    AM_LOG_ALWAYS(0, "Now %s the %s of our %s, %s summ%s of York",
                  "is",
                  "winter",
                  "discontent",
                  "Made glorious",
                  "er by this son");

    /* attempt to overflow the buffer, although this will be ultimately unsuccessful because the
     * logging works differently in unit test mode than it does in "real life" mode.
     */
    AM_LOG_ALWAYS(0, "\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
                     "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ");
}
Пример #3
0
UDPSocket::UDPSocket()
{
#ifdef AM_PLATFORM_WINDOWS
	WSADATA wsaData;
	int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (error != 0)
	{
		AM_LOG_ERROR("WSAStartup failed with error: %d\n", error);
		return;
	}
	
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		AM_LOG_ERROR("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
	}
#endif
}
Пример #4
0
bool
UDPSocket::closeSocket()
{
#ifdef AM_PLATFORM_WINDOWS
	int ret = closesocket(m_socket);
#elif defined AM_PLATFORM_APPLE
	int ret = close(m_socket);
#endif
	if (ret < 0)
		AM_LOG_ERROR("Failed to shutdown socket: %s", StringUtils::errorCodeToString(errno).c_str());
	else
		AM_LOG_SUCCESS("Closed socket");

	return ret == 0;
}
Пример #5
0
int
UDPSocket::write(const char *buffer, size_t size)
{
	if (m_socket >= 0)
	{
		int len = sendto(m_socket, buffer, static_cast<int>(size), 0, m_addrInfo->ai_addr, static_cast<int>(m_addrInfo->ai_addrlen));
		if (len == -1)
		{
			AM_LOG_ERROR("Failed to write to socket: %s", StringUtils::errorCodeToString(errno).c_str());
		}
		return len;
	}
	else
		return 0;
}
Пример #6
0
bool
UDPSocket::connect(const am::UDPWriteDesc &desc)
{
	addrinfo hints {0};
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_protocol = 0;
	hints.ai_canonname = NULL;
	hints.ai_addr = NULL;
	hints.ai_next = NULL;
	
	addrinfo* result;
	int s = getaddrinfo(desc.address.c_str(), std::to_string(desc.port).c_str(), &hints, &result);
	if (s != 0) {
		AM_LOG_ERROR("getaddrinfo: %s", gai_strerror(s));
		return false;
	}

	bool connected = false;
	addrinfo* rp;
	for (rp = result; rp != NULL; )
	{
		m_socket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if (m_socket >= 0)
		{
			m_addrInfo = rp;
			connected = true;
			addrinfo* next = rp->ai_next;
			rp->ai_next = nullptr;
			freeaddrinfo(next);
			break;
		}
		else
		{
			addrinfo* next = rp->ai_next;
			rp->ai_next = nullptr;
			freeaddrinfo(rp);
			rp = next;
		}
	}

	return connected;
}
Пример #7
0
static void am_url_validator_tick(void *arg) {
    static const char *thisfunc = "am_url_validator_tick():";
    int i;
    struct url_validator_worker_data *list;

    list = (struct url_validator_worker_data *) calloc(1,
            sizeof (struct url_validator_worker_data) * AM_MAX_INSTANCES);
    if (list == NULL || get_valid_url_all(list) != AM_SUCCESS) {
        am_free(list);
        return;
    }

    for (i = 0; i < AM_MAX_INSTANCES; i++) {
        /* schedule a new url_validator_worker only when instance is registered and validator is not running already */
        if (list[i].instance_id > 0 && !list[i].running) {
            struct url_validator_worker_data *worker_data =
                    (struct url_validator_worker_data *) malloc(sizeof (struct url_validator_worker_data));
            if (worker_data != NULL) {
                worker_data->instance_id = list[i].instance_id;
                worker_data->url_index = list[i].url_index;
                worker_data->last = list[i].last;
                worker_data->config_path = strdup(list[i].config_path);
                if (am_worker_dispatch(url_validator_worker, worker_data) != AM_SUCCESS) {
                    AM_LOG_WARNING(list[i].instance_id, "%s failed to dispatch url validator worker", thisfunc);
                    AM_FREE(worker_data->config_path, worker_data);
                }
            } else {
                AM_LOG_ERROR(list[i].instance_id, "%s memory allocation error", thisfunc);
            }
        } else if (list[i].instance_id > 0 && list[i].running) {
            AM_LOG_WARNING(list[i].instance_id, "%s url validator worker already running", thisfunc);
        }
        am_free(list[i].config_path);
    }
    free(list);
}
Пример #8
0
am_config_t *am_get_config_file(unsigned long instance_id, const char *filename) {
    static const char *thisfunc = "am_get_config_file():";
    am_config_t *conf = NULL;
    FILE *file = NULL;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    conf = calloc(1, sizeof (am_config_t));
    if (conf == NULL) {
        AM_LOG_ERROR(instance_id, "%s memory allocation error", thisfunc);
        return NULL;
    }
    conf->instance_id = instance_id;

    file = fopen(filename, "r");
    if (file == NULL) {
        AM_LOG_ERROR(instance_id,
                "%s can't open file %s (error: %d)", thisfunc,
                filename, errno);
        free(conf);
        return NULL;
    }

    while ((read = get_line(&line, &len, file)) != -1) {
        trim(line, '\n');
        trim(line, '\r');
        trim(line, ' ');
        if (line == NULL || line[0] == '\0' || line[0] == '#') continue;

        /* bootstrap options */

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOCAL, CONF_NUMBER, NULL, &conf->local, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_POSTDATA_PRESERVE_DIR, CONF_STRING, NULL, &conf->pdp_dir, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NAMING_URL, CONF_STRING_LIST, &conf->naming_url_sz, &conf->naming_url, AM_SPACE_CHAR);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_REALM, CONF_STRING, NULL, &conf->realm, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_USER, CONF_STRING, NULL, &conf->user, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PASSWORD, CONF_STRING, NULL, &conf->pass, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_KEY, CONF_STRING, NULL, &conf->key, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_DEBUG_OPT, CONF_NUMBER, NULL, &conf->debug, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_DEBUG_FILE, CONF_STRING, NULL, &conf->debug_file, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_DEBUG_LEVEL, CONF_DEBUG_LEVEL, NULL, &conf->debug_level, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_FILE, CONF_STRING, NULL, &conf->audit_file, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_OPT, CONF_NUMBER, NULL, &conf->audit, NULL);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CERT_KEY_FILE, CONF_STRING, NULL, &conf->cert_key_file, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CERT_KEY_PASSWORD, CONF_STRING, NULL, &conf->cert_key_pass, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CERT_FILE, CONF_STRING, NULL, &conf->cert_file, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CA_FILE, CONF_STRING, NULL, &conf->cert_ca_file, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CIPHERS, CONF_STRING, NULL, &conf->ciphers, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_TRUST_CERT, CONF_NUMBER, NULL, &conf->cert_trust, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_TLS_OPT, CONF_STRING, NULL, &conf->tls_opts, NULL);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NET_TIMEOUT, CONF_NUMBER, NULL, &conf->net_timeout, NULL);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_URL_VALIDATE_LEVEL, CONF_NUMBER, NULL, &conf->valid_level, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_URL_VALIDATE_PING_INTERVAL, CONF_NUMBER, NULL, &conf->valid_ping, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_URL_VALIDATE_PING_MISS, CONF_NUMBER, NULL, &conf->valid_ping_miss, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_URL_VALIDATE_PING_OK, CONF_NUMBER, NULL, &conf->valid_ping_ok, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_URL_VALIDATE_DEFAULT_SET, CONF_NUMBER_LIST, &conf->valid_default_url_sz, &conf->valid_default_url, AM_COMMA_CHAR);

        /*
         * com.forgerock.agents.config.hostmap format:
         *  server1.domain.name|192.168.1.1,server2.domain.name|192.168.1.2
         */
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_HOST_MAP, CONF_STRING_LIST, &conf->hostmap_sz, &conf->hostmap, AM_COMMA_CHAR);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_RETRY_MAX, CONF_NUMBER, NULL, &conf->retry_max, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_RETRY_WAIT, CONF_NUMBER, NULL, &conf->retry_wait, NULL);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOTIF_ENABLE, CONF_NUMBER, NULL, &conf->notif_enable, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOTIF_URL, CONF_STRING, NULL, &conf->notif_url, NULL);

        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LB_ENABLE, CONF_NUMBER, NULL, &conf->lb_enable, NULL);
        parse_config_value(instance_id, line, AM_AGENTS_CONFIG_KEEPALIVE_DISABLE, CONF_NUMBER, NULL, &conf->keepalive_disable, NULL);

        if (conf->local) { /* do read other options in case configuration is local */

            /* other options */

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AGENT_URI, CONF_STRING, NULL, &conf->agenturi, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_NAME, CONF_STRING, NULL, &conf->cookie_name, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGIN_URL_MAP, CONF_STRING_MAP, &conf->login_url_sz, &conf->login_url, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_SECURE, CONF_NUMBER, NULL, &conf->cookie_secure, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CMP_CASE_IGNORE, CONF_NUMBER, NULL, &conf->url_eval_case_ignore, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_POLICY_CACHE_VALID, CONF_NUMBER, NULL, &conf->policy_cache_valid, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_TOKEN_CACHE_VALID, CONF_NUMBER, NULL, &conf->token_cache_valid, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_UID_PARAM, CONF_STRING, NULL, &conf->userid_param, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_UID_PARAM_TYPE, CONF_STRING, NULL, &conf->userid_param_type, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_PROFILE_MODE, CONF_ATTR_MODE, NULL, &conf->profile_attr_fetch, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_PROFILE_MAP, CONF_STRING_MAP, &conf->profile_attr_map_sz, &conf->profile_attr_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_SESSION_MODE, CONF_ATTR_MODE, NULL, &conf->session_attr_fetch, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_SESSION_MAP, CONF_STRING_MAP, &conf->session_attr_map_sz, &conf->session_attr_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_RESPONSE_MODE, CONF_ATTR_MODE, NULL, &conf->response_attr_fetch, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_RESPONSE_MAP, CONF_STRING_MAP, &conf->response_attr_map_sz, &conf->response_attr_map, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_SSO_ONLY, CONF_NUMBER, NULL, &conf->sso_only, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ACCESS_DENIED_URL, CONF_STRING, NULL, &conf->access_denied_url, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_FQDN_CHECK_ENABLE, CONF_NUMBER, NULL, &conf->fqdn_check_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_FQDN_DEFAULT, CONF_STRING, NULL, &conf->fqdn_default, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_FQDN_MAP, CONF_STRING_MAP, &conf->fqdn_map_sz, &conf->fqdn_map, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_RESET_ENABLE, CONF_NUMBER, NULL, &conf->cookie_reset_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_RESET_MAP, CONF_STRING_MAP, &conf->cookie_reset_map_sz, &conf->cookie_reset_map, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOT_ENFORCED_URL, CONF_STRING_MAP, &conf->not_enforced_map_sz, &conf->not_enforced_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOT_ENFORCED_INVERT, CONF_NUMBER, NULL, &conf->not_enforced_invert, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOT_ENFORCED_ATTR, CONF_NUMBER, NULL, &conf->not_enforced_fetch_attr, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOT_ENFORCED_IP, CONF_STRING_MAP, &conf->not_enforced_ip_map_sz, &conf->not_enforced_ip_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_EXT_NOT_ENFORCED_URL, CONF_STRING_MAP, &conf->not_enforced_ext_map_sz, &conf->not_enforced_ext_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_NOT_ENFORCED_REGEX_ENABLE, CONF_NUMBER, NULL, &conf->not_enforced_regex_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_EXT_NOT_ENFORCED_REGEX_ENABLE, CONF_NUMBER, NULL, &conf->not_enforced_ext_regex_enable, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_ENABLE, CONF_NUMBER, NULL, &conf->pdp_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_VALID, CONF_NUMBER, NULL, &conf->pdp_cache_valid, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_COOKIE, CONF_STRING, NULL, &conf->pdp_lb_cookie, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_STICKYMODE, CONF_STRING, NULL, &conf->pdp_sess_mode, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_STICKYVALUE, CONF_STRING, NULL, &conf->pdp_sess_value, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_URI_PREFIX, CONF_STRING, NULL, &conf->pdp_uri_prefix, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CLIENT_IP_VALIDATE, CONF_NUMBER, NULL, &conf->client_ip_validate, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_COOKIE_PREFIX, CONF_STRING, NULL, &conf->cookie_prefix, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ATTR_COOKIE_MAX_AGE, CONF_NUMBER, NULL, &conf->cookie_maxage, NULL);


            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CDSSO_ENABLE, CONF_NUMBER, NULL, &conf->cdsso_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CDSSO_LOGIN, CONF_STRING_MAP, &conf->cdsso_login_map_sz, &conf->cdsso_login_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CDSSO_DOMAIN, CONF_STRING_MAP, &conf->cdsso_cookie_domain_map_sz, &conf->cdsso_cookie_domain_map, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_URL, CONF_STRING_MAP, &conf->openam_logout_map_sz, &conf->openam_logout_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_APP_LOGOUT_URL, CONF_STRING_MAP, &conf->logout_map_sz, &conf->logout_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_REDIRECT_URL, CONF_STRING, NULL, &conf->logout_redirect_url, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_COOKIE_RESET, CONF_STRING_MAP, &conf->logout_cookie_reset_map_sz, &conf->logout_cookie_reset_map, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_REGEX_ENABLE, CONF_NUMBER, NULL, &conf->logout_regex_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_URL_REGEX, CONF_STRING, NULL, &conf->logout_url_regex, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_LOGOUT_REDIRECT_DISABLE, CONF_NUMBER, NULL, &conf->logout_redirect_disable, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_POLICY_SCOPE, CONF_NUMBER, NULL, &conf->policy_scope_subtree, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_RESOLVE_CLIENT_HOST, CONF_NUMBER, NULL, &conf->resolve_client_host, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_POLICY_ENCODE_SPECIAL_CHAR, CONF_NUMBER, NULL, &conf->policy_eval_encode_chars, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_ENCODE_SPECIAL_CHAR, CONF_NUMBER, NULL, &conf->cookie_encode_chars, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_OVERRIDE_PROTO, CONF_NUMBER, NULL, &conf->override_protocol, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_OVERRIDE_HOST, CONF_NUMBER, NULL, &conf->override_host, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_OVERRIDE_PORT, CONF_NUMBER, NULL, &conf->override_port, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_OVERRIDE_NOTIFICATION_URL, CONF_NUMBER, NULL, &conf->override_notif_url, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_VALID, CONF_NUMBER, NULL, &conf->config_valid, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PASSWORD_REPLAY_KEY, CONF_STRING, NULL, &conf->password_replay_key, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_POLICY_CLOCK_SKEW, CONF_NUMBER, NULL, &conf->policy_clock_skew, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_GOTO_PARAM_NAME, CONF_STRING, NULL, &conf->url_redirect_param, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CACHE_CONTROL_ENABLE, CONF_NUMBER, NULL, &conf->cache_control_enable, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_USE_REDIRECT_ADVICE, CONF_NUMBER, NULL, &conf->use_redirect_for_advice, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CLIENT_IP_HEADER, CONF_STRING, NULL, &conf->client_ip_header, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CLIENT_HOSTNAME_HEADER, CONF_STRING, NULL, &conf->client_hostname_header, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_INVALID_URL, CONF_STRING, NULL, &conf->url_check_regex, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_CONDITIONAL_LOGIN_URL, CONF_STRING_MAP, &conf->cond_login_url_sz, &conf->cond_login_url, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_COOKIE_HTTP_ONLY, CONF_NUMBER, NULL, &conf->cookie_http_only, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_MULTI_VALUE_SEPARATOR, CONF_STRING, NULL, &conf->multi_attr_separator, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_IIS_LOGON_USER, CONF_NUMBER, NULL, &conf->logon_user_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_IIS_PASSWORD_HEADER, CONF_NUMBER, NULL, &conf->password_header_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_PDP_JS_REPOST, CONF_NUMBER, NULL, &conf->pdp_js_repost, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_JSON_URL, CONF_STRING_MAP, &conf->json_url_map_sz, &conf->json_url_map, NULL);

            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_LEVEL, CONF_AUDIT_LEVEL, NULL, &conf->audit_level, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_REMOTE_INTERVAL, CONF_NUMBER, NULL, &conf->audit_remote_interval, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_REMOTE_FILE, CONF_STRING, NULL, &conf->audit_file_remote, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_AUDIT_DISPOSITION, CONF_STRING, NULL, &conf->audit_file_disposition, NULL);
        
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ANONYMOUS_USER_ENABLE, CONF_NUMBER, NULL, &conf->anon_remote_user_enable, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_ANONYMOUS_USER_ID, CONF_STRING, NULL, &conf->unauthenticated_user, NULL);
        
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_IGNORE_PATHINFO, CONF_NUMBER, NULL, &conf->path_info_ignore, NULL);
            parse_config_value(instance_id, line, AM_AGENTS_CONFIG_IGNORE_PATHINFO_NOT_ENFORCED, CONF_NUMBER, NULL, &conf->path_info_ignore_not_enforced, NULL);
        }
    }

    conf->ts = time(NULL);

    fclose(file);
    am_free(line);

    decrypt_agent_passwords(conf);
    update_agent_configuration_ttl(conf);
    update_agent_configuration_audit(conf);
    update_agent_configuration_normalise_map_urls(conf);
    update_agent_configuration_reorder_map_values(conf);
    
    return conf;
}
Пример #9
0
static void *net_async_connect(void *arg) {
    am_net_t *n = (am_net_t *) arg;
    static const char *thisfunc = "net_async_connect():";
    struct in6_addr serveraddr;
    struct addrinfo *rp, hints;
    int err = 0, on = 1;
    char port[7];
    am_timer_t tmr;

    memset(&hints, 0, sizeof (struct addrinfo));
    hints.ai_flags = AI_NUMERICSERV;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    err = INETPTON(AF_INET, n->uv.host, &serveraddr);
    if (err == 1) {
        hints.ai_family = AF_INET;
        hints.ai_flags |= AI_NUMERICHOST;
    } else {
        err = INETPTON(AF_INET6, n->uv.host, &serveraddr);
        if (err == 1) {
            hints.ai_family = AF_INET6;
            hints.ai_flags |= AI_NUMERICHOST;
        }
    }

    snprintf(port, sizeof (port), "%d", n->uv.port);

    am_timer_start(&tmr);
    if ((err = getaddrinfo(n->uv.host, port, &hints, &n->ra)) != 0) {
        n->error = AM_EHOSTUNREACH;
        am_timer_stop(&tmr);
        am_timer_report(n->instance_id, &tmr, "getaddrinfo");
        set_event(n->ce);
        return NULL;
    }

    am_timer_stop(&tmr);
    am_timer_report(n->instance_id, &tmr, "getaddrinfo");

    n->error = 0;

    for (rp = n->ra; rp != NULL; rp = rp->ai_next) {

        if (rp->ai_family != AF_INET && rp->ai_family != AF_INET6 &&
                rp->ai_socktype != SOCK_STREAM && rp->ai_protocol != IPPROTO_TCP) continue;

        if ((n->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == INVALID_SOCKET) {
            AM_LOG_ERROR(n->instance_id,
                    "%s: cannot create socket while connecting to %s:%d",
                    thisfunc, n->uv.host, n->uv.port);
            net_log_error(n->instance_id, net_error());
            continue;
        }

        if (setsockopt(n->sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof (on)) < 0) {
            net_log_error(n->instance_id, net_error());
        }
        if (setsockopt(n->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof (on)) < 0) {
            net_log_error(n->instance_id, net_error());
        }
#ifdef SO_NOSIGPIPE
        if (setsockopt(n->sock, SOL_SOCKET, SO_NOSIGPIPE, (void *) &on, sizeof (on)) < 0) {
            net_log_error(n->instance_id, net_error());
        }
#endif
        if (set_nonblocking(n, 1) != 0) {
            n->error = AM_EPERM;
            continue;
        }

        err = connect(n->sock, rp->ai_addr, (SOCKLEN_T) rp->ai_addrlen);
        if (err == 0) {
            AM_LOG_DEBUG(n->instance_id, "%s: connected to %s:%d (%s)",
                    thisfunc, n->uv.host, n->uv.port,
                    rp->ai_family == AF_INET ? "IPv4" : "IPv6");
            n->error = 0;
            if (n->uv.ssl) {
                net_connect_ssl(n);
                if (n->ssl.error != AM_SUCCESS) {
                    AM_LOG_ERROR(n->instance_id,
                            "%s: SSL/TLS connection to %s:%d (%s) failed (%s)",
                            thisfunc, n->uv.host, n->uv.port,
                            rp->ai_family == AF_INET ? "IPv4" : "IPv6",
                            am_strerror(n->ssl.error));
                    net_close_socket(n->sock);
                    n->sock = INVALID_SOCKET;
                    n->error = n->ssl.error;
                    break;
                }
            }
            net_async_poll(n);
            break;
        }

        if (err == INVALID_SOCKET && net_in_progress(net_error())) {
#ifdef _WIN32
            WSAPOLLFD fds[1];
#else
            struct pollfd fds[1];
#endif
            memset(fds, 0, sizeof (fds));
            fds[0].fd = n->sock;
            fds[0].events = connect_ev;
            fds[0].revents = 0;

            err = sockpoll(fds, 1, n->timeout > 0 ? n->timeout * 1000 : -1);
            if (err > 0 && fds[0].revents & connected_ev) {
                int pe = 0;
                SOCKLEN_T pe_sz = sizeof (pe);
                err = getsockopt(n->sock, SOL_SOCKET, SO_ERROR, (char *) &pe, &pe_sz);
                if (err == 0 && pe == 0) {
                    AM_LOG_DEBUG(n->instance_id, "%s: connected to %s:%d (%s)",
                            thisfunc, n->uv.host, n->uv.port,
                            rp->ai_family == AF_INET ? "IPv4" : "IPv6");

                    n->error = 0;
                    if (n->uv.ssl) {
                        net_connect_ssl(n);
                        if (n->ssl.error != AM_SUCCESS) {
                            AM_LOG_ERROR(n->instance_id,
                                    "%s: SSL/TLS connection to %s:%d (%s) failed (%s)",
                                    thisfunc, n->uv.host, n->uv.port,
                                    rp->ai_family == AF_INET ? "IPv4" : "IPv6",
                                    am_strerror(n->ssl.error));
                            net_close_socket(n->sock);
                            n->sock = INVALID_SOCKET;
                            n->error = n->ssl.error;
                            break;
                        }
                    }
                    net_async_poll(n);
                    break;
                }
                net_log_error(n->instance_id, pe);
                n->error = AM_ECONNREFUSED;
            } else if (err == 0) {
                AM_LOG_WARNING(n->instance_id,
                        "%s: timeout connecting to %s:%d (%s)",
                        thisfunc, n->uv.host, n->uv.port,
                        rp->ai_family == AF_INET ? "IPv4" : "IPv6");
                n->error = AM_ETIMEDOUT;
            } else {
                int pe = 0;
                SOCKLEN_T pe_sz = sizeof (pe);
                err = getsockopt(n->sock, SOL_SOCKET, SO_ERROR, (char *) &pe, &pe_sz);
                n->error = AM_ETIMEDOUT;
                break;
            }
        }

        net_close_socket(n->sock);
        n->sock = INVALID_SOCKET;
    }

    if (n->error != 0) {
        set_event(n->ce);
    }
    return NULL;
}
Пример #10
0
static void net_async_poll(am_net_t *n) {
    static const char *thisfunc = "net_async_poll():";
    int ev = 0;
    char first_run = 1;
#ifdef _WIN32
    WSAPOLLFD fds[1];
#else
    struct pollfd fds[1];
#endif

    n->tm = am_create_timer_event(AM_TIMER_EVENT_ONCE, AM_NET_POOL_TIMEOUT, n,
            net_async_poll_timeout);
    if (n->tm == NULL) {
        AM_LOG_ERROR(n->instance_id,
                "%s failed to create response timeout control", thisfunc);
        n->error = AM_ENOMEM;
        return;
    }
    if (n->tm->error != 0) {
        AM_LOG_ERROR(n->instance_id,
                "%s error %d creating response timeout control", thisfunc, n->tm->error);
        n->error = AM_ERROR;
        return;
    }

    am_start_timer_event(n->tm);

    memset(fds, 0, sizeof (fds));
    while (ev != -1) {

        fds[0].fd = n->sock;
        fds[0].events = read_ev;
        fds[0].revents = 0;

        if (first_run) {
            set_event(n->ce);
            if (n->on_connected) n->on_connected(n->data, 0);
            first_run = 0;
        }

        if (wait_for_exit_event(n->de) != 0) {
            break;
        }

        ev = sockpoll(fds, 1, 100);
        if (ev < 0) {
            net_log_error(n->instance_id, net_error());
            break;
        }
        if (ev == 1 && fds[0].revents & (POLLNVAL | POLLERR)) {
            if (n->on_close) n->on_close(n->data, 0);
            break;
        }
        if (ev == 1 && fds[0].revents & read_avail_ev) {
            /* read an output from a remote side */
            int er = 0, error = 0;
            char tmp[1024];
            int got = 0;
            SOCKLEN_T errlen = sizeof (error);
            er = getsockopt(n->sock, SOL_SOCKET, SO_ERROR, (void *) &error, &errlen);
            memset(&tmp[0], 0, sizeof (tmp));
            if (error != 0) break;

            got = recv(n->sock, tmp, sizeof (tmp), 0);
            if (n->ssl.on) {
                error = net_read_ssl(n, tmp, got);
                if (error != AM_SUCCESS) {
                    if (error != AM_EAGAIN) {
                        if (n->on_close) n->on_close(n->data, 0);
                        break;
                    }
                }
            } else {
                if (got < 0) {
                    if (!net_in_progress(errno)) {
                        if (n->on_close) n->on_close(n->data, 0);
                        break;
                    }
                } else if (got == 0) {
                    if (n->on_close) n->on_close(n->data, 0);
                    break;
                } else {
                    http_parser_execute(n->hp, n->hs, tmp, got);
                }
            }
        }
    }
}
Пример #11
0
am_config_t *am_parse_config_xml(unsigned long instance_id, const char *xml, size_t xml_sz, char log_enable) {
    static const char *thisfunc = "am_parse_config_xml():";
    am_config_t *r = NULL;
    char *begin, *stream = NULL;
    size_t data_sz;
    pcre *x = NULL;
    const char *error = NULL;
    int erroroffset;

    am_xml_parser_ctx_t xctx = {.setting_value = 0,
        .conf = NULL, .rgx = NULL, .parser = NULL, .log_enable = log_enable,
        .data_sz = 0, .data = NULL, .status = AM_SUCCESS};

    if (xml == NULL || xml_sz == 0) {
        AM_LOG_ERROR(instance_id, "%s memory allocation error", thisfunc);
        return NULL;
    }

    /* match [key]=value returned within <value>[key]=value_of_a_key</value> element */
    x = pcre_compile("(?<=\\[)(.+?)(?=\\])\\]\\s*\\=\\s*(.+)", 0, &error, &erroroffset, NULL);
    if (x == NULL) {
        AM_LOG_ERROR(instance_id, "%s pcre error %s", thisfunc, error == NULL ? "" : error);
    }

    r = calloc(1, sizeof (am_config_t));
    if (r == NULL) {
        AM_LOG_ERROR(instance_id, "%s memory allocation error", thisfunc);
        pcre_free(x);
        return NULL;
    }
    r->instance_id = instance_id;

    begin = strstr(xml, "![CDATA[");
    if (begin != NULL) {
        char *end = strstr(begin + 8, "]]>");
        if (end != NULL) {
            stream = begin + 8;
            data_sz = end - (begin + 8);
        }
    } else {
        /* no CDATA */
        stream = (char *) xml;
        data_sz = xml_sz;
    }

    if (stream != NULL && data_sz > 0) {
        XML_Parser parser = XML_ParserCreate("UTF-8");
        xctx.parser = &parser;
        xctx.conf = r;
        xctx.rgx = x;
        XML_SetUserData(parser, &xctx);
        XML_SetElementHandler(parser, start_element, end_element);
        XML_SetCharacterDataHandler(parser, character_data);
        XML_SetEntityDeclHandler(parser, entity_declaration);
        if (XML_Parse(parser, stream, (int) data_sz, XML_TRUE) == XML_STATUS_ERROR) {
            const char *message = XML_ErrorString(XML_GetErrorCode(parser));
            XML_Size line = XML_GetCurrentLineNumber(parser);
            XML_Size col = XML_GetCurrentColumnNumber(parser);
            AM_LOG_ERROR(instance_id, "%s xml parser error (%lu:%lu) %s", thisfunc,
                    (unsigned long) line, (unsigned long) col, message);
            am_config_free(&r);
            r = NULL;
        } else {
            r->ts = time(NULL);
        }
        XML_ParserFree(parser);
    }

    if (xctx.status != AM_SUCCESS) {
        AM_LOG_ERROR(instance_id, "%s %s", thisfunc, am_strerror(xctx.status));
    }

    pcre_free(x);

    decrypt_agent_passwords(r);
    update_agent_configuration_ttl(r);
    return r;
}
Пример #12
0
void url_validator_worker(void *arg) {
    static const char *thisfunc = "url_validator_worker():";
    struct url_validator_worker_data *w = (struct url_validator_worker_data *) arg;
    am_net_options_t *net_options;
    int i, validate_status;
    am_config_t *conf = NULL;
    time_t current_ts;
    struct url_valid_table *e, *t;
    int current_index, current_ok, current_fail, default_ok, next_ok;
    char **url_list;
    int url_list_sz = 0;
    int ping_diff;

    set_valid_url_instance_running(w->instance_id, AM_TRUE);

    conf = am_get_config_file(w->instance_id, w->config_path);
    if (conf == NULL) {
        AM_LOG_WARNING(w->instance_id, "%s failed to get agent configuration (%s)",
                thisfunc, LOGEMPTY(w->config_path));
        set_valid_url_instance_running(w->instance_id, AM_FALSE);
        AM_FREE(w->config_path, w);
        return;
    }

    ping_diff = MAX(MIN_URL_VALIDATOR_TICK, conf->valid_ping);
    current_ts = time(NULL);
    /* this index corresponds to the naming.url multi-value index */
    current_index = w->url_index;

    if (conf->valid_level > 1 || conf->naming_url_sz < 2 || conf->naming_url_sz != conf->valid_default_url_sz ||
            (current_ts - w->last) < ping_diff) {
        /* a) validation is disabled; b) there is nothing to validate;
         * c) naming.url list and default.url list sizes do not match or
         * d) its not time yet to do any validation
         */
        am_config_free(&conf);
        set_valid_url_instance_running(w->instance_id, AM_FALSE);
        AM_FREE(w->config_path, w);
        return;
    }

    if (current_index < 0 || current_index >= conf->naming_url_sz) {
        AM_LOG_WARNING(w->instance_id,
                "%s invalid current index value, defaulting to %s", thisfunc, conf->naming_url[0]);
        set_valid_url_index(w->instance_id, 0);
        am_config_free(&conf);
        set_valid_url_instance_running(w->instance_id, AM_FALSE);
        AM_FREE(w->config_path, w);
        return;
    }

#define URL_LIST_FREE(l, s) do { \
        int k; \
        if (l == NULL) break; \
        for (k = 0; k < s; k++) { \
            am_free(l[k]); \
        }\
        free(l); \
    } while (0)

    net_options = calloc(1, sizeof (am_net_options_t));
    if (net_options == NULL) {
        AM_LOG_ERROR(w->instance_id, "%s memory allocation error", thisfunc);
        am_config_free(&conf);
        set_valid_url_instance_running(w->instance_id, AM_FALSE);
        AM_FREE(w->config_path, w);
        return;
    }

    url_list = (char **) calloc(1, conf->naming_url_sz * sizeof (char *));
    if (url_list == NULL) {
        AM_LOG_ERROR(w->instance_id, "%s memory allocation error", thisfunc);
        am_config_free(&conf);
        set_valid_url_instance_running(w->instance_id, AM_FALSE);
        AM_FREE(net_options, w->config_path, w);
        return;
    }
    url_list_sz = conf->naming_url_sz;

    for (i = 0; i < url_list_sz; i++) {
        /* default.url.set contains fail-over order;
         * will keep internal value list index-ordered 
         **/
        int j = conf->valid_default_url[i];
        url_list[i] = strdup(conf->naming_url[j]);
        if (url_list[i] == NULL) {
            URL_LIST_FREE(url_list, url_list_sz);
            am_config_free(&conf);
            set_valid_url_instance_running(w->instance_id, AM_FALSE);
            AM_FREE(net_options, w->config_path, w);
            return;
        }
    }

    am_net_options_create(conf, net_options, NULL);
    net_options->keepalive = AM_FALSE;
    net_options->local = net_options->cert_trust = AM_TRUE;
    net_options->net_timeout = 2; /* fixed for url validator; in sec */

    /* do the actual url validation */

    for (i = 0; i < url_list_sz; i++) {
        const char *url = url_list[i];
        int ok = 0, fail = 0, httpcode = 0;

        get_validation_table_entry(w->instance_id, i, &ok, &fail, NULL);

        AM_LOG_DEBUG(w->instance_id, "%s validating %s", thisfunc, url);

        if (conf->valid_level == 1) {
            /* simple HEAD request */
            validate_status = am_url_validate(w->instance_id, url, net_options, &httpcode);
        } else {
            /* full scale agent login-logout request */
            char *agent_token = NULL;
            validate_status = am_agent_login(w->instance_id, url, conf->user, conf->pass, conf->realm,
                    net_options, &agent_token, NULL, NULL, NULL);
            if (agent_token != NULL) {
                am_agent_logout(0, url, agent_token, net_options);
                free(agent_token);
                httpcode = 200;
            }
        }

        if (validate_status == AM_SUCCESS && httpcode != 0) {
            if (ok++ > conf->valid_ping_ok) {
                ok = conf->valid_ping_ok;
            }
            fail = 0;
        } else {
            if (fail++ > conf->valid_ping_miss) {
                fail = conf->valid_ping_miss;
            }
            ok = 0;
        }

        set_validation_table_entry(w->instance_id, i, ok, fail);
    }

    /* map stored index value to our ordered list index */
    for (i = 0; i < conf->valid_default_url_sz; i++) {
        if (current_index == conf->valid_default_url[i]) {
            current_index = i;
            break;
        }
    }

    default_ok = current_ok = current_fail = 0;
    /* fetch validation table entry for the current_index 
     * (which now corresponds to the default.url.set value/index) */
    get_validation_table_entry(w->instance_id, current_index, &current_ok, &current_fail, &default_ok);

    /* do the fail-over logic */
    do {
        if (current_ok > 0) {
            if (current_index > 0 && default_ok >= conf->valid_ping_ok) {
                set_valid_url_index(w->instance_id, conf->valid_default_url[0]);
                AM_LOG_INFO(w->instance_id, "%s fail-back to %s", thisfunc, url_list[0]);
            } else {
                set_valid_url_index(w->instance_id, conf->valid_default_url[current_index]);
                AM_LOG_INFO(w->instance_id, "%s continue with %s", thisfunc, url_list[current_index]);
            }
            break;
        }

        /* current index is not valid; check ping.miss.count */
        if (current_ok == 0 && current_fail <= conf->valid_ping_miss) {
            set_valid_url_index(w->instance_id, conf->valid_default_url[current_index]);
            AM_LOG_INFO(w->instance_id, "%s still staying with %s", thisfunc, url_list[current_index]);
            break;
        }

        /* find next valid index value to fail-over to */
        next_ok = 0;
        AM_MUTEX_LOCK(&table_mutex);

        AM_LIST_FOR_EACH(table, e, t) {
            if (e->instance_id == w->instance_id && e->index == 0) {
                default_ok = e->ok;
            }
            if (e->instance_id == w->instance_id && e->ok > 0) {
                next_ok = e->ok;
                i = e->index;
                break;
            }
        }

        AM_MUTEX_UNLOCK(&table_mutex);

        if (next_ok == 0) {
            AM_LOG_WARNING(w->instance_id,
                    "%s none of the values are valid, defaulting to %s", thisfunc, url_list[0]);
            set_valid_url_index(w->instance_id, conf->valid_default_url[0]);
            break;
        }

        if (current_index > 0 && default_ok >= conf->valid_ping_ok) {
            AM_LOG_INFO(w->instance_id, "%s fail-back to %s", thisfunc, url_list[0]);
            set_valid_url_index(w->instance_id, conf->valid_default_url[0]);
            break;
        }

        AM_LOG_INFO(w->instance_id, "%s fail-over to %s", thisfunc, url_list[i]);
        set_valid_url_index(w->instance_id, conf->valid_default_url[i]);

    } while (0);

    am_net_options_delete(net_options);
    free(net_options);
    am_config_free(&conf);
    set_valid_url_instance_running(w->instance_id, AM_FALSE);
    AM_FREE(w->config_path, w);
    URL_LIST_FREE(url_list, url_list_sz);
}