Esempio n. 1
0
static int amagent_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp,
        server_rec *s) {
    /* main process init */
    int status;
    apr_status_t rv = APR_SUCCESS;
    void *data;

#define AMAGENT_INIT_ONCE "AMAGENT_INIT_ONCE"
    apr_pool_userdata_get(&data, AMAGENT_INIT_ONCE, s->process->pool);
    if (!data) {
        /* module has already been initialized */
        apr_pool_userdata_set((const void *) 1, AMAGENT_INIT_ONCE,
                apr_pool_cleanup_null, s->process->pool);
        return rv;
    }
    apr_pool_cleanup_register(pconf, s, amagent_cleanup, apr_pool_cleanup_null);
    ap_add_version_component(pconf, MODINFO);
    LOG_S(APLOG_DEBUG, s, "amagent_init() %d", getpid());

#ifndef _WIN32
    status = am_init();
    if (status != AM_SUCCESS) {
        rv = APR_EINIT;
        LOG_S(APLOG_ERR, s, "amagent_init() status: %s", am_strerror(status));
    }
#endif
    return rv;
}
Esempio n. 2
0
static am_status_t set_custom_response(am_request_t *rq, const char *text, const char *cont_type) {
    request_rec *r = (request_rec *) (rq != NULL ? rq->ctx : NULL);
    if (r == NULL || !ISVALID(text)) return AM_EINVAL;
    if (rq->status == AM_INTERNAL_REDIRECT) {
        ap_internal_redirect(text, r);
        rq->status = AM_DONE;
    } else if (rq->status == AM_REDIRECT) {
        apr_table_add(r->headers_out, "Location", text);
        ap_custom_response(r, HTTP_MOVED_TEMPORARILY, text);
    } else {
        if (rq->status == AM_PDP_DONE) {
            request_rec *sr = ap_sub_req_method_uri(am_method_num_to_str(rq->method),
                    rq->post_data_url, r, NULL);

            sr->headers_in = r->headers_in;
            sr->notes = r->notes;

            am_log_debug(rq->instance_id, "set_custom_response(): issuing sub-request %s to %s",
                    sr->method, rq->post_data_url);

            ap_run_sub_req(sr);
            ap_destroy_sub_req(sr);
            rq->status = AM_DONE;

        } else {
            size_t tl = strlen(text);
            if (ISVALID(cont_type)) {
                ap_set_content_type(r, cont_type);
            }
            ap_set_content_length(r, tl);
            ap_rwrite(text, (int) tl, r);
            ap_custom_response(r,
                    am_status_value(rq->status == AM_SUCCESS ||
                    rq->status == AM_DONE ? AM_SUCCESS : rq->status), text);
            ap_rflush(r);
        }
    }
    am_log_info(rq->instance_id, "set_custom_response(): status: %s", am_strerror(rq->status));
    return AM_SUCCESS;
}
Esempio n. 3
0
static int amagent_auth_handler(request_rec *r) {
    const char *thisfunc = "amagent_auth_handler():";
    int rv;
    am_request_t d;
    am_config_t *boot = NULL;

    amagent_config_t *c = ap_get_module_config(r->server->module_config, &amagent_module);

    if (c == NULL || !c->enabled || c->error != AM_SUCCESS) {
        /* amagent module is not enabled for this 
         * server/virtualhost - we are not handling this request
         **/
        return DECLINED;
    }

    if (c->error != AM_SUCCESS) {
        LOG_R(APLOG_ERR, r, "%s is not configured to handle the request "
                "to %s (unable to load bootstrap configuration from %s, error: %s)",
                DESCRIPTION, r->uri, c->config, am_strerror(c->error));
        return HTTP_FORBIDDEN;
    }

    LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): [%s] [%ld]", c->config, c->config_id);

    /* register and update instance logger configuration (for already registered
     * instances - update logging level only 
     */
    am_log_register_instance(c->config_id, c->debug_file, c->debug_level,
            c->audit_file, c->audit_level);

    am_log_debug(c->config_id, "%s begin", thisfunc);

    /* fetch agent configuration instance (from cache if available) */
    rv = am_get_agent_config(c->config_id, c->config, &boot);
    if (boot == NULL || rv != AM_SUCCESS) {
        LOG_R(APLOG_ERR, r, "%s is not configured to handle the request "
                "to %s (unable to get agent configuration instance, configuration: %s, error: %s)",
                DESCRIPTION, r->uri, c->config, am_strerror(rv));
        am_log_error(c->config_id, "amagent_auth_handler(): failed to get agent configuration instance, error: %s",
                am_strerror(rv));
        return HTTP_FORBIDDEN;
    }

    /* set up request processor data structure */
    memset(&d, 0, sizeof (am_request_t));
    d.conf = boot;
    d.status = AM_ERROR;
    d.instance_id = c->config_id;
    d.ctx = r;
    d.method = get_method_num(r, c->config_id);
    d.content_type = apr_table_get(r->headers_in, "Content-Type");
    d.cookies = apr_table_get(r->headers_in, "Cookie");

    if (ISVALID(d.conf->client_ip_header)) {
        d.client_ip = (char *) apr_table_get(r->headers_in, d.conf->client_ip_header);
    }
    if (!ISVALID(d.client_ip)) {
#ifdef APACHE24
        d.client_ip = (char *) r->connection->client_ip;
#else
        d.client_ip = (char *) r->connection->remote_ip;
#endif
    }

    if (ISVALID(d.conf->client_hostname_header)) {
        d.client_host = (char *) apr_table_get(r->headers_in, d.conf->client_hostname_header);
    }

    d.am_get_request_url_f = get_request_url;
    d.am_get_post_data_f = get_request_body;
    d.am_set_post_data_f = set_request_body;
    d.am_set_user_f = set_user;
    d.am_set_header_in_request_f = set_header_in_request;
    d.am_add_header_in_response_f = add_header_in_response;
    d.am_set_cookie_f = set_cookie;
    d.am_set_custom_response_f = set_custom_response;
    d.am_set_method_f = set_method;

    am_process_request(&d);

    rv = am_status_value(d.status);

    am_log_debug(c->config_id, "amagent_auth_handler(): exit status: %s (%d)",
            am_strerror(d.status), d.status);

    am_config_free(&d.conf);
    am_request_free(&d);

    LOG_R(APLOG_DEBUG, r, "amagent_auth_handler(): return status: %d", rv);
    return rv;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
static void *net_async_connect(void *arg) {
    am_net_t *n = (am_net_t *) arg;
    static const char *thisfunc = "net_async_connect():";
    struct in6_addr serveraddr;
    struct addrinfo *rp, hints;
    int err = 0, on = 1;
    char port[7];
    am_timer_t tmr;

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

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

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

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

    n->error = 0;

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

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

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

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

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

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

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

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

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

    if (n->error != 0) {
        set_event(n->ce);
    }
    return NULL;
}
Esempio n. 10
0
am_config_t *am_parse_config_xml(unsigned long instance_id, const char *xml, size_t xml_sz, char log_enable) {
    static const char *thisfunc = "am_parse_config_xml():";
    am_config_t *r = NULL;
    char *begin, *stream = NULL;
    size_t data_sz;
    pcre *x = NULL;
    const char *error = NULL;
    int erroroffset;

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

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

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

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

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

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

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

    pcre_free(x);

    decrypt_agent_passwords(r);
    update_agent_configuration_ttl(r);
    return r;
}