示例#1
0
/**
 * Ensure that at warning log level we do NOT log something via AM_LOG_DEBUG.
 */
void test_log_debug_not_at_warning_level(void** state) {
    int result;
    const char* message = "Message written at DEBUG level.";

    logging_setup(AM_LOG_LEVEL_WARNING);
    AM_LOG_DEBUG(getpid(), message);
    sleep(5);
    result = validate_contains(log_file_name, message);
    logging_teardown();
    assert_int_equal(result, 0);
}
示例#2
0
/**
 * Ensure that an impractically high log level we DO actually log text via AM_LOG_DEBUG.
 */
void test_log_debug_at_debug_level(void** state) {
    int result;
    const char* message = "Message written at DEBUG level.";

    srand(time(NULL));
    logging_setup(AM_LOG_LEVEL_AUDIT_DENY);
    AM_LOG_DEBUG(getpid(), message);
    sleep(5);
    result = validate_contains(log_file_name, message);
    logging_teardown();
    assert_int_equal(result, 1);
}
示例#3
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");
}
static void parse_config_value(unsigned long instance_id, const char *line, const char *prm, int type,
        int *itm_sz, void *itm, const char *sep) {

    if (itm == NULL || compare_property(line, prm) != AM_SUCCESS) {
        return;
    }

    switch (type) {
        case CONF_STRING:
        {
            char **value = (char **) itm;
            *value = (char *) parse_value(line, prm, type, NULL);
            if (strstr(prm, "password") != NULL) {
                AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to '%s'",
                        prm, *value == NULL ? "NULL" : "********");
                break;
            }
            AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to '%s'",
                    prm, *value == NULL ? "NULL" : *value);
        }
            break;
        case CONF_NUMBER:
        case CONF_DEBUG_LEVEL:
        case CONF_ATTR_MODE:
        case CONF_AUDIT_LEVEL:
        {
            int *value = (int *) itm;
            int *value_tmp = (int *) parse_value(line, prm, type, NULL);
            if (value_tmp != NULL) {
                *value = *value_tmp;
                free(value_tmp);
            }
            AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to '%d'", prm, *value);
        }
            break;
        case CONF_STRING_LIST:
        {
            char ***value = (char ***) itm;
            struct val_string_list *value_tmp = (struct val_string_list *) parse_value(line, prm, type, sep);
            if (value_tmp != NULL) {
                *value = value_tmp->list;
                *itm_sz = value_tmp->size;
                free(value_tmp);
            }
            AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to %d value(s)", prm, *itm_sz);
        }
            break;
        case CONF_NUMBER_LIST:
        {
            int **value = (int **) itm;
            struct val_number_list *value_tmp = (struct val_number_list *) parse_value(line, prm, type, sep);
            if (value_tmp != NULL) {
                *value = value_tmp->list;
                *itm_sz = value_tmp->size;
                free(value_tmp);
            }
            AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to %d value(s)", prm, *itm_sz);
        }
            break;
        case CONF_STRING_MAP:
        {
            int old_sz = *itm_sz;
            am_config_map_t **value = (am_config_map_t **) itm;
            char *value_tmp = (char *) parse_value(line, prm, CONF_STRING, NULL);
            if (value_tmp == NULL) {
                break;
            }
            *value = (am_config_map_t *) realloc(*value, sizeof (am_config_map_t) *(++(*itm_sz)));
            if (*value == NULL) {
                if (--(*itm_sz) < 0) {
                    *itm_sz = 0;
                }
                free(value_tmp);
                break;
            }
            (&(*value)[old_sz])->name = value_tmp;
            (&(*value)[old_sz])->value = value_tmp + strlen(value_tmp) + 1;
            AM_LOG_DEBUG(instance_id, "am_get_config_file() %s is set to %d value(s)", prm, *itm_sz);
        }
            break;
        default:
            AM_LOG_WARNING(instance_id, "am_get_config_file() unknown type value %d setting %s", type, prm);
            break;
    }
}
示例#5
0
文件: net_ops.c 项目: j3guile/OpenAM
int am_agent_policy_request(unsigned long instance_id, const char *openam,
        const char *token, const char *user_token, const char *req_url,
        const char *notif_url, const char *scope, const char *cip, const char *pattr,
        const char *server_id, struct am_ssl_options *info,
        struct am_namevalue **session_list,
        struct am_policy_result **policy_list) {

    static const char *thisfunc = "am_agent_policy_request():";
    char *post = NULL, *post_data = NULL;
    am_net_t n;
    size_t post_sz;
    int status = AM_ERROR;
    int session_status = AM_SUCCESS;
    struct request_data req_data;

    if (!ISVALID(token) || !ISVALID(user_token) || !ISVALID(notif_url) || !ISVALID(scope) ||
            !ISVALID(req_url) || !ISVALID(openam) || !ISVALID(cip)) {
        return AM_EINVAL;
    }

    memset(&req_data, 0, sizeof(struct request_data));
    memset(&n, 0, sizeof(am_net_t));
    n.instance_id = instance_id;
    n.timeout = AM_NET_CONNECT_TIMEOUT;
    n.url = openam;
    if (info != NULL) {
        memcpy(&n.ssl.info, info, sizeof(struct am_ssl_options));
    }

    if (ISVALID(server_id)) {
        am_asprintf(&n.req_headers, "Cookie: amlbcookie=%s\r\n", server_id);
    }

    req_data.event = create_event();
    if (req_data.event == NULL) {
        return AM_ENOMEM;
    }

    n.data = &req_data;
    n.on_connected = on_connected_cb;
    n.on_close = on_close_cb;
    n.on_data = on_agent_request_data_cb;
    n.on_complete = on_complete_cb;

    if (am_net_connect(&n) == 0) {
        char *token_in = NULL;
        size_t token_sz = am_asprintf(&token_in, "token:%s", token);
        char *token_b64 = base64_encode(token_in, &token_sz);

        size_t post_data_sz = am_asprintf(&post_data,
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                "<RequestSet vers=\"1.0\" svcid=\"Session\" reqid=\"0\">"
                "<Request><![CDATA["
                "<SessionRequest vers=\"1.0\" reqid=\"1\" requester=\"%s\">"
                "<GetSession reset=\"true\">" /* reset the idle timeout */
                "<SessionID>%s</SessionID>"
                "</GetSession>"
                "</SessionRequest>]]>"
                "</Request>"
                "<Request><![CDATA["
                "<SessionRequest vers=\"1.0\" reqid=\"2\" requester=\"%s\">"
                "<AddSessionListener>"
                "<URL>%s</URL>"
                "<SessionID>%s</SessionID>"
                "</AddSessionListener>"
                "</SessionRequest>]]>"
                "</Request>"
                "</RequestSet>",
                NOTNULL(token_b64), user_token, NOTNULL(token_b64), notif_url, user_token);

        AM_FREE(token_in, token_b64);

        if (post_data != NULL) {
            post_sz = am_asprintf(&post, "POST %s/sessionservice HTTP/1.1\r\n"
                    "Host: %s:%d\r\n"
                    "User-Agent: "MODINFO"\r\n"
                    "Accept: text/xml\r\n"
                    "Connection: Keep-Alive\r\n"
                    "Content-Type: text/xml; charset=UTF-8\r\n"
                    "%s"
                    "Content-Length: %d\r\n\r\n"
                    "%s", n.uv.path, n.uv.host, n.uv.port,
                    NOTNULL(n.req_headers), post_data_sz, post_data);
            if (post != NULL) {
                AM_LOG_DEBUG(instance_id, "%s sending request:\n%s", thisfunc, post);
                status = am_net_write(&n, post, post_sz);
                free(post);
                post = NULL;
            }
            free(post_data);
            post_data = NULL;
        }

        if (status == AM_SUCCESS) {
            wait_for_event(req_data.event, 0);
        }

        AM_LOG_DEBUG(instance_id, "%s response status code: %d", thisfunc, n.http_status);

        if (status == AM_SUCCESS && n.http_status == 200 && ISVALID(req_data.data)) {
            size_t req_url_sz = strlen(req_url);
            char *req_url_escaped = malloc(req_url_sz * 6 + 1); /* worst case */
            if (req_url_escaped != NULL) {
                memcpy(req_url_escaped, req_url, req_url_sz);
                xml_entity_escape(req_url_escaped, req_url_sz);
            }

            AM_LOG_DEBUG(instance_id, "%s response:\n%s", thisfunc, req_data.data);

            if (strstr(req_data.data, "<Exception>") != NULL && strstr(req_data.data, "Invalid session ID") != NULL) {
                session_status = AM_INVALID_SESSION;
            }
            if (strstr(req_data.data, "<Exception>") != NULL && strstr(req_data.data, "Application token passed in") != NULL) {
                session_status = AM_INVALID_AGENT_SESSION;
            }
            if (session_status == AM_SUCCESS && session_list != NULL) {
                *session_list = am_parse_session_xml(instance_id, req_data.data, req_data.data_size);
            }

            req_data.data_size = 0;
            free(req_data.data);
            req_data.data = NULL;

            /* TODO:
             * <AttributeValuePair><Attribute name=\"requestDnsName\"/><Value>%s</Value></AttributeValuePair>
             */
            post_data_sz = am_asprintf(&post_data,
                    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                    "<RequestSet vers=\"1.0\" svcid=\"Policy\" reqid=\"3\">"
                    "<Request><![CDATA[<PolicyService version=\"1.0\">"
                    "<PolicyRequest requestId=\"4\" appSSOToken=\"%s\">"
                    "<GetResourceResults userSSOToken=\"%s\" serviceName=\"iPlanetAMWebAgentService\" resourceName=\"%s\" resourceScope=\"%s\">"
                    "<EnvParameters><AttributeValuePair><Attribute name=\"requestIp\"/><Value>%s</Value></AttributeValuePair></EnvParameters>"
                    "<GetResponseDecisions>"
                    "%s"
                    "</GetResponseDecisions>"
                    "</GetResourceResults>"
                    "</PolicyRequest>"
                    "</PolicyService>]]>"
                    "</Request>"
                    "</RequestSet>",
                    token, user_token, NOTNULL(req_url_escaped), scope,
                    cip, NOTNULL(pattr));

            am_free(req_url_escaped);

            post_sz = am_asprintf(&post, "POST %s/policyservice HTTP/1.1\r\n"
                    "Host: %s:%d\r\n"
                    "User-Agent: "MODINFO"\r\n"
                    "Accept: text/xml\r\n"
                    "Content-Type: text/xml; charset=UTF-8\r\n"
                    "Content-Length: %d\r\n"
                    "%s"
                    "Connection: close\r\n\r\n"
                    "%s", n.uv.path, n.uv.host, n.uv.port,
                    post_data_sz, NOTNULL(n.req_headers), post_data);

            if (post != NULL) {
                AM_LOG_DEBUG(instance_id, "%s sending request:\n%s", thisfunc, post);
                status = am_net_write(&n, post, post_sz);
                free(post);
            }
        } else {
            status = n.error != AM_SUCCESS ? n.error : AM_ERROR;
        }
    }

    if (status == AM_SUCCESS) {
        wait_for_event(req_data.event, 0);
    } else {
        AM_LOG_DEBUG(instance_id, "%s disconnecting", thisfunc);
        am_net_diconnect(&n);
    }

    AM_LOG_DEBUG(instance_id, "%s response status code: %d", thisfunc, n.http_status);

    if (status == AM_SUCCESS && n.http_status == 200 && ISVALID(req_data.data)) {
        AM_LOG_DEBUG(instance_id, "%s response:\n%s", thisfunc, req_data.data);

        if (strstr(req_data.data, "<Exception>") != NULL) {
            if (strstr(req_data.data, "SSO token is invalid") != NULL) {
                session_status = AM_INVALID_SESSION;
            } else if (strstr(req_data.data, "Application sso token is invalid") != NULL) {
                session_status = AM_INVALID_AGENT_SESSION;
            }
        }

        if (session_status == AM_SUCCESS && policy_list != NULL) {
            *policy_list = am_parse_policy_xml(instance_id, req_data.data, req_data.data_size,
                    am_scope_to_num(scope));
        }
    }

    am_net_close(&n);
    close_event(req_data.event);

    am_free(req_data.data);
    return session_status != AM_SUCCESS ? session_status : status;
}
示例#6
0
文件: net_ops.c 项目: j3guile/OpenAM
static int send_authcontext_request(am_net_t *conn, const char *realm, char **token) {
    static const char *thisfunc = "send_authcontext_request():";
    size_t post_sz, post_data_sz;
    char *post = NULL, *post_data = NULL;
    int status = AM_ERROR;
    struct request_data *req_data;

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(realm)) return AM_EINVAL;

    req_data = (struct request_data *) conn->data;

    post_data_sz = am_asprintf(&post_data,
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            "<RequestSet vers=\"1.0\" svcid=\"auth\" reqid=\"0\">"
            "<Request><![CDATA["
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AuthContext version=\"1.0\">"
            "<Request authIdentifier=\"0\">"
            "<NewAuthContext orgName=\"%s\"/></Request></AuthContext>]]>"
            "</Request></RequestSet>",
            realm);
    if (post_data == NULL) return AM_ENOMEM;

    post_sz = am_asprintf(&post, "POST %s/authservice HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "Connection: Keep-Alive\r\n"
            "Content-Type: text/xml; charset=UTF-8\r\n"
            "Content-Length: %d\r\n\r\n"
            "%s", conn->uv.path, conn->uv.host, conn->uv.port, post_data_sz, post_data);
    if (post == NULL) {
        free(post_data);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    free(post_data);
    free(post);

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    if (status == AM_SUCCESS && conn->http_status == 200 && ISVALID(req_data->data)) {
        char *begin = strstr(req_data->data, "Response authIdentifier=\"");
        if (begin != NULL) {
            char *end = strstr(begin + 25, "\"");
            if (end != NULL) {
                *token = strndup(begin + 25, end - begin - 25);
            }
        }
        if (ISINVALID(*token)) {
            status = AM_NOT_FOUND;
        }

        if (status == AM_SUCCESS && ISVALID(conn->req_headers)) {
            am_request_t req_temp;
            int decode_status;

            memset(&req_temp, 0, sizeof(am_request_t));
            req_temp.token = strdup(*token);

            decode_status = am_session_decode(&req_temp);
            if (decode_status == AM_SUCCESS && req_temp.session_info.error == AM_SUCCESS) {

                if (ISVALID(req_temp.session_info.si)) {
                    am_asprintf(&conn->req_headers, "%s%s\r\n", conn->req_headers, req_temp.session_info.si);
                } else {
                    am_free(conn->req_headers);
                    conn->req_headers = NULL;
                }

                AM_LOG_DEBUG(conn->instance_id, "%s app token SI: %s, S1: %s", thisfunc,
                        LOGEMPTY(req_temp.session_info.si), LOGEMPTY(req_temp.session_info.s1));
            }
            am_request_free(&req_temp);
        }
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    am_free(req_data->data);
    req_data->data = NULL;
    return status;
}
示例#7
0
文件: net_ops.c 项目: j3guile/OpenAM
int am_agent_logout(unsigned long instance_id, const char *openam,
        const char *token, const char *server_id,
        struct am_ssl_options *info, void(*log)(const char *, ...)) {
    static const char *thisfunc = "am_agent_logout():";
    am_net_t conn;
    int status = AM_ERROR;
    size_t post_sz, post_data_sz;
    char *post = NULL, *post_data = NULL;
    struct request_data req_data;

    if (!ISVALID(token) || !ISVALID(openam)) return AM_EINVAL;

    memset(&req_data, 0, sizeof(struct request_data));
    memset(&conn, 0, sizeof(am_net_t));
    conn.log = log;
    conn.instance_id = instance_id;
    conn.timeout = AM_NET_CONNECT_TIMEOUT;
    conn.url = openam;
    if (info != NULL) {
        memcpy(&conn.ssl.info, info, sizeof(struct am_ssl_options));
    }

    if (ISVALID(server_id)) {
        am_asprintf(&conn.req_headers, "Cookie: amlbcookie=%s\r\n", server_id);
    }

    req_data.event = create_event();
    if (req_data.event == NULL) return AM_ENOMEM;

    conn.data = &req_data;
    conn.on_connected = on_connected_cb;
    conn.on_close = on_close_cb;
    conn.on_data = on_agent_request_data_cb;
    conn.on_complete = on_complete_cb;

    if (am_net_connect(&conn) == 0) {
        post_data_sz = am_asprintf(&post_data,
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                "<RequestSet vers=\"1.0\" svcid=\"auth\" reqid=\"0\">"
                "<Request><![CDATA["
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AuthContext version=\"1.0\">"
                "<Request authIdentifier=\"%s\">"
                "<Logout/></Request></AuthContext>]]>"
                "</Request></RequestSet>",
                token);
        if (post_data != NULL) {
            post_sz = am_asprintf(&post, "POST %s/authservice HTTP/1.1\r\n"
                    "Host: %s:%d\r\n"
                    "User-Agent: "MODINFO"\r\n"
                    "Accept: text/xml\r\n"
                    "Connection: Close\r\n"
                    "Content-Type: text/xml; charset=UTF-8\r\n"
                    "%s"
                    "Content-Length: %d\r\n\r\n"
                    "%s", conn.uv.path, conn.uv.host, conn.uv.port,
                    NOTNULL(conn.req_headers), post_data_sz, post_data);
            if (post != NULL) {
                AM_LOG_DEBUG(instance_id, "%s sending request:\n%s", thisfunc, post);
                if (log != NULL) {
                    log("%s sending request:\n%s", thisfunc, post);
                }
                status = am_net_write(&conn, post, post_sz);
                free(post);
            }
            free(post_data);
        }
    }

    if (status == AM_SUCCESS) {
        wait_for_event(req_data.event, 0);
    } else {
        AM_LOG_DEBUG(instance_id, "%s disconnecting", thisfunc);
        if (log != NULL) {
            log("%s disconnecting", thisfunc);
        }
        am_net_diconnect(&conn);
    }

    AM_LOG_DEBUG(instance_id, "%s response status code: %d", thisfunc, conn.http_status);
    if (log != NULL) {
        log("%s response status code: %d", thisfunc, conn.http_status);
    }

    am_net_close(&conn);
    close_event(req_data.event);

    am_free(req_data.data);
    return status;
}
示例#8
0
文件: net_ops.c 项目: j3guile/OpenAM
int am_agent_login(unsigned long instance_id, const char *openam, const char *notifyurl,
        const char *user, const char *pass, const char *realm, int is_local,
        int lb_enable, struct am_ssl_options *info,
        char **agent_token, char **pxml, size_t *pxsz, struct am_namevalue **session_list,
        void(*log)(const char *, ...)) {
    static const char *thisfunc = "am_agent_login():";
    am_net_t conn;
    int status = AM_ERROR;
    struct request_data req_data;

    if (!ISVALID(realm) || !ISVALID(user) ||
            !ISVALID(pass) || !ISVALID(openam)) {
        return AM_EINVAL;
    }

    memset(&req_data, 0, sizeof(struct request_data));

    memset(&conn, 0, sizeof(am_net_t));
    conn.log = log;
    conn.instance_id = instance_id;
    conn.timeout = AM_NET_CONNECT_TIMEOUT;
    conn.url = openam;
    if (info != NULL) {
        memcpy(&conn.ssl.info, info, sizeof(struct am_ssl_options));
    }

    if (lb_enable) {
        conn.req_headers = strdup("Cookie: amlbcookie=");
    }

    req_data.event = create_event();
    if (req_data.event == NULL) return AM_ENOMEM;

    conn.data = &req_data;
    conn.on_connected = on_connected_cb;
    conn.on_close = on_close_cb;
    conn.on_data = on_agent_request_data_cb;
    conn.on_complete = on_complete_cb;

    if (am_net_connect(&conn) == 0) {

        do {
            /* authenticate with agent profile/password and module Application (PLL endpoint) */
            status = send_authcontext_request(&conn, realm, agent_token);
            if (status != AM_SUCCESS) break;

            status = send_login_request(&conn, agent_token, user, pass);
            if (status != AM_SUCCESS) break;

            if (!is_local) {
                /* send agent attribute request (/identity/xml/read REST endpoint);
                 * no interest in a remote profile in case of a local-only configuration
                 */
                status = send_attribute_request(&conn, agent_token, pxml, pxsz, user, realm);
                if (status != AM_SUCCESS) break;
            }

            /* send session request (PLL endpoint) */
            status = send_session_request(&conn, agent_token, notifyurl, session_list);
            if (status != AM_SUCCESS) break;

            /* subscribe to a policy change notification (PLL endpoint) */
            status = send_policychange_request(&conn, agent_token, notifyurl);
        } while (0);

        if (status != AM_SUCCESS) {
            AM_LOG_DEBUG(instance_id, "%s disconnecting", thisfunc);
            if (log != NULL) {
                log("%s disconnecting", thisfunc);
            }
            am_net_diconnect(&conn);
        }
    }

    am_net_close(&conn);
    close_event(req_data.event);

    am_free(req_data.data);
    return status;
}
示例#9
0
文件: net_ops.c 项目: j3guile/OpenAM
static int send_policychange_request(am_net_t *conn, char **token, const char *notifyurl) {
    static const char *thisfunc = "send_policychange_request():";
    size_t post_sz, post_data_sz;
    char *post = NULL, *post_data = NULL;
    int status = AM_ERROR;
    struct request_data *req_data;

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(*token)) return AM_EINVAL;

    req_data = (struct request_data *) conn->data;

    post_data_sz = am_asprintf(&post_data,
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            "<RequestSet vers=\"1.0\" svcid=\"Policy\" reqid=\"1\">"
            "<Request><![CDATA["
            "<PolicyService version=\"1.0\">"
            "<PolicyRequest requestId=\"1\" appSSOToken=\"%s\">"
            "<RemovePolicyListener notificationURL=\"%s\" serviceName=\"iPlanetAMWebAgentService\"/>"
            "</PolicyRequest>"
            "</PolicyService>]]>"
            "</Request>"
            "<Request><![CDATA["
            "<PolicyService version=\"1.0\">"
            "<PolicyRequest requestId=\"2\" appSSOToken=\"%s\">"
            "<AddPolicyListener notificationURL=\"%s\" serviceName=\"iPlanetAMWebAgentService\"/>"
            "</PolicyRequest>"
            "</PolicyService>]]>"
            "</Request>"
            "</RequestSet>",
            *token, NOTNULL(notifyurl), *token, NOTNULL(notifyurl));
    if (post_data == NULL) return AM_ENOMEM;

    post_sz = am_asprintf(&post, "POST %s/policyservice HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "Connection: Close\r\n"
            "Content-Type: text/xml; charset=UTF-8\r\n"
            "%s"
            "Content-Length: %d\r\n\r\n"
            "%s", conn->uv.path, conn->uv.host, conn->uv.port,
            NOTNULL(conn->req_headers), post_data_sz, post_data);
    if (post == NULL) {
        free(post_data);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    free(post_data);
    free(post);

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s authenticate response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s authenticate response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    am_free(req_data->data);
    req_data->data = NULL;
    return status;
}
示例#10
0
文件: net_ops.c 项目: j3guile/OpenAM
static int send_session_request(am_net_t *conn, char **token, const char *notifyurl,
        struct am_namevalue **session_list) {
    static const char *thisfunc = "send_session_request():";
    size_t post_sz, post_data_sz, token_sz;
    char *post = NULL, *post_data = NULL, *token_in = NULL, *token_b64;
    int status = AM_ERROR;
    struct request_data *req_data;

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(*token)) return AM_EINVAL;

    token_sz = am_asprintf(&token_in, "token:%s", *token);
    token_b64 = base64_encode(token_in, &token_sz);

    req_data = (struct request_data *) conn->data;

    post_data_sz = am_asprintf(&post_data,
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            "<RequestSet vers=\"1.0\" svcid=\"Session\" reqid=\"0\">"
            "<Request><![CDATA["
            "<SessionRequest vers=\"1.0\" reqid=\"1\" requester=\"%s\">"
            "<GetSession reset=\"true\">"
            "<SessionID>%s</SessionID>"
            "</GetSession>"
            "</SessionRequest>]]>"
            "</Request>"
            "<Request><![CDATA["
            "<SessionRequest vers=\"1.0\" reqid=\"2\" requester=\"%s\">"
            "<AddSessionListener>"
            "<URL>%s</URL>"
            "<SessionID>%s</SessionID>"
            "</AddSessionListener>"
            "</SessionRequest>]]>"
            "</Request>"
            "</RequestSet>",
            NOTNULL(token_b64), *token, NOTNULL(token_b64), notifyurl, *token);
    if (post_data == NULL) {
        AM_FREE(token_b64, token_in);
        return AM_ENOMEM;
    }

    post_sz = am_asprintf(&post, "POST %s/sessionservice HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "Connection: Keep-Alive\r\n"
            "Content-Type: text/xml; charset=UTF-8\r\n"
            "%s"
            "Content-Length: %d\r\n\r\n"
            "%s", conn->uv.path, conn->uv.host, conn->uv.port,
            NOTNULL(conn->req_headers), post_data_sz, post_data);
    if (post == NULL) {
        AM_FREE(post_data, token_b64, token_in);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    AM_FREE(post, post_data, token_b64, token_in);

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    if (status == AM_SUCCESS && conn->http_status == 200 && ISVALID(req_data->data)) {
        if (session_list != NULL) {
            *session_list = am_parse_session_xml(conn->instance_id, req_data->data, req_data->data_size);
        }
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    am_free(req_data->data);
    req_data->data = NULL;
    return status;
}
示例#11
0
文件: net_ops.c 项目: j3guile/OpenAM
static int send_attribute_request(am_net_t *conn, char **token, char **pxml, size_t *pxsz,
        const char *user, const char *realm) {
    static const char *thisfunc = "send_attribute_request():";
    size_t post_sz;
    char *post = NULL;
    int status = AM_ERROR;
    struct request_data *req_data;
    char *token_enc;
    char *realm_enc = url_encode(realm);
    char *user_enc = url_encode(user);

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(*token) || !ISVALID(realm) || !ISVALID(user)) return AM_EINVAL;

    token_enc = url_encode(*token);
    req_data = (struct request_data *) conn->data;

    post_sz = am_asprintf(&post, "GET %s/identity/xml/read?"
            "name=%s&attributes_names=realm&attributes_values_realm=%s&attributes_names=objecttype"
            "&attributes_values_objecttype=Agent&admin=%s HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "%s"
            "Connection: Keep-Alive\r\n\r\n",
            conn->uv.path,
            user_enc, realm_enc, token_enc,
            conn->uv.host, conn->uv.port, NOTNULL(conn->req_headers));
    if (post == NULL) {
        AM_FREE(realm_enc, user_enc, token_enc);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    free(post);

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    if (status == AM_SUCCESS && conn->http_status == 200 && ISVALID(req_data->data)) {
        if (stristr(req_data->data, "exception") != NULL) {
            status = AM_ERROR;
        } else {
            if (pxml != NULL) {
                *pxml = malloc(req_data->data_size + 1);
                if (*pxml != NULL) {
                    memcpy(*pxml, req_data->data, req_data->data_size);
                    (*pxml)[req_data->data_size] = 0;
                } else {
                    status = AM_ENOMEM;
                }
            }
            if (pxsz != NULL) *pxsz = req_data->data_size;
        }
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    AM_FREE(req_data->data, realm_enc, user_enc, token_enc);
    req_data->data = NULL;
    return status;
}
示例#12
0
文件: net_ops.c 项目: j3guile/OpenAM
static int send_login_request(am_net_t *conn, char **token, const char *user,
        const char *password) {
    static const char *thisfunc = "send_login_request():";
    size_t post_sz, post_data_sz, xml_esc_sz;
    char *post = NULL, *post_data = NULL;
    int status = AM_ERROR;
    struct request_data *req_data;
    char *user_xml_esc = NULL, *pass_xml_esc = NULL;

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(*token) || !ISVALID(user)) return AM_EINVAL;

    /* do xml-escape */
    xml_esc_sz = strlen(user);
    user_xml_esc = malloc(xml_esc_sz * 6 + 1); /* worst case */
    if (user_xml_esc != NULL) {
        memcpy(user_xml_esc, user, xml_esc_sz);
        xml_entity_escape(user_xml_esc, xml_esc_sz);
    } else {
        return AM_ENOMEM;
    }

    if (ISVALID(password)) {
        xml_esc_sz = strlen(password);
        pass_xml_esc = malloc(xml_esc_sz * 6 + 1); /* worst case */
        if (pass_xml_esc != NULL) {
            memcpy(pass_xml_esc, password, xml_esc_sz);
            xml_entity_escape(pass_xml_esc, xml_esc_sz);
        } else {
            free(user_xml_esc);
            return AM_ENOMEM;
        }
    }

    req_data = (struct request_data *) conn->data;

    post_data_sz = am_asprintf(&post_data,
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            "<RequestSet vers=\"1.0\" svcid=\"auth\" reqid=\"0\">"
            "<Request><![CDATA["
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AuthContext version=\"1.0\">"
            "<Request authIdentifier=\"%s\"><Login>"
            "<IndexTypeNamePair indexType=\"moduleInstance\"><IndexName>Application</IndexName>"
            "</IndexTypeNamePair></Login></Request></AuthContext>]]>"
            "</Request>"
            "<Request><![CDATA["
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AuthContext version=\"1.0\">"
            "<Request authIdentifier=\"%s\"><SubmitRequirements>"
            "<Callbacks length=\"2\"><NameCallback><Prompt>Enter application name.</Prompt>"
            "<Value>%s</Value>"
            "</NameCallback><PasswordCallback echoPassword=\"true\"><Prompt>Enter secret string.</Prompt>"
            "<Value>%s</Value>"
            "</PasswordCallback></Callbacks>"
            "</SubmitRequirements></Request></AuthContext>]]>"
            "</Request>"
            "</RequestSet>",
            *token, *token, user_xml_esc, NOTNULL(pass_xml_esc));

    AM_FREE(user_xml_esc, pass_xml_esc);
    if (post_data == NULL) {
        return AM_ENOMEM;
    }

    post_sz = am_asprintf(&post, "POST %s/authservice HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "Connection: Keep-Alive\r\n"
            "Content-Type: text/xml; charset=UTF-8\r\n"
            "%s"
            "Content-Length: %d\r\n\r\n"
            "%s", conn->uv.path, conn->uv.host, conn->uv.port,
            NOTNULL(conn->req_headers), post_data_sz, post_data);
    if (post == NULL) {
        free(post_data);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    free(post_data);
    free(post);
    free(*token); /* delete pre-login/authcontext token */
    *token = NULL;

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s authenticate response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s authenticate response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    status = AM_ERROR;

    if (ISVALID(req_data->data)) {
        char *begin = strstr(req_data->data, "LoginStatus status=\"success\" ssoToken=\"");
        if (begin != NULL) {
            char *end = strstr(begin + 39, "\"");
            if (end != NULL) {
                *token = strndup(begin + 39, end - begin - 39);
                if (ISVALID(*token)) status = AM_SUCCESS;
            }
        }
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    am_free(req_data->data);
    req_data->data = NULL;
    return status;
}
示例#13
0
文件: net_ops.c 项目: j3guile/OpenAM
/**
 * Validate the specified URL by using HTTP HEAD request.
 */
int am_url_validate(unsigned long instance_id, const char* url,
        struct am_ssl_options* info, int* httpcode, void(*log)(const char *, ...)) {

    static const char* thisfunc = "am_url_validate():";
    char* get = NULL;
    am_net_t conn;
    size_t get_sz;
    int status = AM_ERROR;
    struct request_data request_data;

    AM_LOG_DEBUG(instance_id, "%s%s", thisfunc, LOGEMPTY(url));

    if (!ISVALID(url)) {
        return AM_EINVAL;
    }

    memset(&request_data, 0, sizeof(struct request_data));
    memset(&conn, 0, sizeof(am_net_t));
    conn.log = log;
    conn.instance_id = instance_id;
    conn.timeout = AM_NET_CONNECT_TIMEOUT;
    conn.url = url;
    if (info != NULL) {
        memcpy(&conn.ssl.info, info, sizeof(struct am_ssl_options));
    }

    request_data.event = create_event();
    if (request_data.event == NULL) {
        return AM_ENOMEM;
    }

    conn.data = &request_data;
    conn.on_connected = on_connected_cb;
    conn.on_close = on_close_cb;
    conn.on_data = on_agent_request_data_cb;
    conn.on_complete = on_complete_cb;

    if (am_net_connect(&conn) == 0) {
        AM_LOG_DEBUG(instance_id, "am_net_connect(%s) returns zero", url);
        if (log != NULL) {
            log("am_net_connect(%s) returns zero", url);
        }
        get_sz = am_asprintf(&get, "HEAD %s HTTP/1.1\r\n"
                "Host: %s:%d\r\n"
                "User-Agent: "MODINFO"\r\n"
                "Accept: text/plain\r\n"
                "Connection: close\r\n\r\n",
                conn.uv.path, conn.uv.host, conn.uv.port);
        if (get != NULL) {
            AM_LOG_DEBUG(instance_id, "%s sending request:\n%s", thisfunc, get);
            if (log != NULL) {
                log("%s sending request:\n%s", thisfunc, get);
            }
            status = am_net_write(&conn, get, get_sz);
            free(get);
        }
    } else {
        AM_LOG_DEBUG(instance_id, "am_net_connect(%s) returns NON zero", url);
        if (log != NULL) {
            log("am_net_connect(%s) returns NON zero", url);
        }
    }

    AM_LOG_DEBUG(instance_id, "status is set to %d", status);
    if (log != NULL) {
        log("status is set to %d", status);
    }

    if (status == AM_SUCCESS) {
        wait_for_event(request_data.event, 0);
    } else {
        AM_LOG_DEBUG(instance_id, "%s disconnecting", thisfunc);
        if (log != NULL) {
            log("%s disconnecting", thisfunc);
        }
        am_net_diconnect(&conn);
    }

    AM_LOG_DEBUG(instance_id, "%s response status code: %d", thisfunc, conn.http_status);
    if (log != NULL) {
        log("%s response status code: %d", thisfunc, conn.http_status);
    }
    if (httpcode) {
        *httpcode = conn.http_status;
    }

    am_net_close(&conn);
    close_event(request_data.event);

    am_free(request_data.data);
    return status;
}
示例#14
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;
}
示例#15
0
static void parse_config_value(am_xml_parser_ctx_t *x, const char *prm, int type,
        int *itm_sz, void *itm, const char *val, int len) {

    if (itm == NULL || val == NULL || len <= 0 || strcmp(x->current_name, prm) != 0) {
        return;
    }

    switch (type) {
        case CONF_STRING:
        {
            char **value = (char **) itm;
            *value = strndup(val, len);
            if (x->log_enable) {
                if (strstr(prm, "password") != NULL) {
                    AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '********'",
                            prm);
                    break;
                }
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '%s'",
                        prm, LOGEMPTY(*value));
            }
        }
            break;
        case CONF_NUMBER:
        {
            int *value = (int *) itm;
            if (strncasecmp(val, "on", len) == 0 || strncasecmp(val, "true", len) == 0 ||
                    strncasecmp(val, "local", len) == 0) {
                *value = 1;
            } else if (strncasecmp(val, "off", len) == 0 || strncasecmp(val, "false", len) == 0 ||
                    strncasecmp(val, "centralized", len) == 0) {
                *value = 0;
            } else {
                char *t = strndup(val, len);
                if (t != NULL) {
                    *value = strtol(t, NULL, AM_BASE_TEN);
                    free(t);
                }
            }
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '%d'", prm, *value);
            }
        }
            break;
        case CONF_DEBUG_LEVEL:
        {
            int *value = (int *) itm;
            *value = AM_LOG_LEVEL_NONE;
            if (strncasecmp(val, "all", 3) == 0) {
                *value = AM_LOG_LEVEL_DEBUG;
            } else if (strncasecmp(val, "error", len) == 0) {
                *value = AM_LOG_LEVEL_ERROR;
            } else if (strncasecmp(val, "info", len) == 0) {
                *value = AM_LOG_LEVEL_INFO;
            } else if (strncasecmp(val, "message", len) == 0) {
                *value = AM_LOG_LEVEL_WARNING;
            } else if (strncasecmp(val, "warning", len) == 0) {
                *value = AM_LOG_LEVEL_WARNING;
            }
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '%d'",
                        prm, *value);
            }
        }
            break;
        case CONF_ATTR_MODE:
        {
            int *value = (int *) itm;
            *value = AM_SET_ATTRS_NONE;
            if (strncasecmp(val, "HTTP_HEADER", len) == 0) {
                *value = AM_SET_ATTRS_AS_HEADER;
            } else if (strncasecmp(val, "HTTP_COOKIE", len) == 0) {
                *value = AM_SET_ATTRS_AS_COOKIE;
            }
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '%d'",
                        prm, *value);
            }
        }
            break;
        case CONF_AUDIT_LEVEL:
        {
            int *value = (int *) itm;
            *value = 0;
            if (strncasecmp(val, "LOG_ALLOW", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT_ALLOW;
            } else if (strncasecmp(val, "LOG_BOTH", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT_ALLOW;
                *value |= AM_LOG_LEVEL_AUDIT_DENY;
            } else if (strncasecmp(val, "LOG_DENY", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT_DENY;
            } else if (strncasecmp(val, "ALL", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT;
                *value |= AM_LOG_LEVEL_AUDIT_REMOTE;
            } else if (strncasecmp(val, "LOCAL", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT;
            } else if (strncasecmp(val, "REMOTE", len) == 0) {
                *value |= AM_LOG_LEVEL_AUDIT_REMOTE;
            }
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to '%d'",
                        prm, *value);
            }
        }
            break;
        case CONF_STRING_LIST:
        {
            int old_sz = *itm_sz;
            char ***value = (char ***) itm;
            char **value_tmp;
            char *v = strndup(val, len);
            if (v == NULL) break;
            value_tmp = (char **) realloc(*value, sizeof (char *) *(++(*itm_sz)));
            if (value_tmp == NULL) {//TODO: realloc failure?
                (*itm_sz)--;
                if (*itm_sz < 0) *itm_sz = 0;
                free(v);
                break;
            }
            *value = value_tmp;
            (*value)[old_sz] = v;
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to %d value(s)",
                        prm, *itm_sz);
            }
        }
            break;
        case CONF_NUMBER_LIST:
        {
            int old_sz = *itm_sz;
            int **value = (int **) itm;
            int *value_tmp;
            char *v = strndup(val, len);
            if (v == NULL) break;
            value_tmp = (int *) realloc(*value, sizeof (int) *(++(*itm_sz)));
            if (value_tmp == NULL) {
                (*itm_sz)--;
                if (*itm_sz < 0) *itm_sz = 0;
                free(v);
                break;
            }
            *value = value_tmp;
            (*value)[old_sz] = strtol(v, NULL, AM_BASE_TEN);
            free(v);
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to %d value(s)",
                        prm, *itm_sz);
            }
        }
            break;
        case CONF_STRING_MAP:
        {
            int old_sz = *itm_sz;
            am_config_map_t **value = (am_config_map_t **) itm;
            am_config_map_t *value_tmp;
            size_t slen = (size_t) len;
            char *v, *mv;

            if (val[0] != '[') break;
            v = strndup(val, len);
            if (v == NULL) break;

            mv = match_group(x->rgx, 2 /* groups in [key]=value */, v, &slen);
            free(v);
            if (mv == NULL) break;

            value_tmp = (am_config_map_t *) realloc(*value, sizeof (am_config_map_t) *(++(*itm_sz)));
            if (value_tmp == NULL) {
                (*itm_sz)--;
                if (*itm_sz < 0) *itm_sz = 0;
                free(mv);
                break;
            }
            *value = value_tmp;
            (&(*value)[old_sz])->name = mv;
            (&(*value)[old_sz])->value = mv + strlen(mv) + 1;
            if (x->log_enable) {
                AM_LOG_DEBUG(x->conf->instance_id, "am_parse_config_xml() %s is set to %d value(s)",
                        prm, *itm_sz);
            }
        }
            break;
        default:
            AM_LOG_WARNING(x->conf->instance_id, "am_parse_config_xml() unknown type value %d setting %s", type, prm);
            break;
    }
}
示例#16
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);
}