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; }
/** * 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"); }
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 }
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; }
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; }
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; }
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); }
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; }
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; }
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); } } } } }
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; }
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, ¤t_ok, ¤t_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); }