Example #1
0
/**
 *  Add a String in AJP message, and transform the String in ASCII
 *  if convert is set and we're on an EBCDIC machine
 *
 * @param msg       AJP Message to get value from
 * @param value     Pointer to String
 * @param convert   When set told to convert String to ASCII
 * @return          APR_SUCCESS or error
 */
apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
                                      int convert)
{
    apr_size_t len;

    if (value == NULL) {
        return(ajp_msg_append_uint16(msg, 0xFFFF));
    }

    len = strlen(value);
    if ((msg->len + len + 3) > msg->max_size) {
        return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
    }

    /* ignore error - we checked once */
    ajp_msg_append_uint16(msg, (apr_uint16_t)len);

    /* We checked for space !!  */
    memcpy(msg->buf + msg->len, value, len + 1); /* including \0 */

    if (convert) {
        /* convert from EBCDIC if needed */
        ap_xlate_proto_to_ascii((char *)msg->buf + msg->len, len + 1);
    }

    msg->len += len + 1;

    return APR_SUCCESS;
}
ngx_int_t
ajp_msg_append_string(ajp_msg_t *msg, ngx_str_t *value)
{
    ngx_buf_t *buf;

    if (value == NULL) {
        return(ajp_msg_append_uint16(msg, 0xFFFF));
    }

    buf = msg->buf;

    if ((buf->last + 2 + value->len + 1) > buf->end) {
        return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
    }

    ajp_msg_append_uint16(msg, (uint16_t) value->len);

    ngx_memcpy(buf->last, value->data, value->len);
    buf->last  += value->len;

    *buf->last++ = '\0';

    return NGX_OK;
}
Example #3
0
static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
                                          request_rec *r,
                                          apr_uri_t *uri)
{
    int method;
    apr_uint32_t i, num_headers = 0;
    apr_byte_t is_ssl;
    char *remote_host;
    const char *session_route, *envvar;
    const apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
    const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts;

    ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, "Into ajp_marshal_into_msgb");

    if ((method = sc_for_req_method_by_id(r)) == UNKNOWN_METHOD) {
        ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(02437)
               "ajp_marshal_into_msgb - Sending unknown method %s as request attribute",
               r->method);
        method = SC_M_JK_STORED;
    }

    is_ssl = (apr_byte_t) ap_proxy_conn_is_https(r->connection);

    if (r->headers_in && apr_table_elts(r->headers_in)) {
        const apr_array_header_t *t = apr_table_elts(r->headers_in);
        num_headers = t->nelts;
    }

    remote_host = (char *)ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_HOST, NULL);

    ajp_msg_reset(msg);

    if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST)     ||
        ajp_msg_append_uint8(msg, (apr_byte_t) method)           ||
        ajp_msg_append_string(msg, r->protocol)                  ||
        ajp_msg_append_string(msg, uri->path)                    ||
        ajp_msg_append_string(msg, r->useragent_ip)              ||
        ajp_msg_append_string(msg, remote_host)                  ||
        ajp_msg_append_string(msg, ap_get_server_name(r))        ||
        ajp_msg_append_uint16(msg, (apr_uint16_t)r->connection->local_addr->port) ||
        ajp_msg_append_uint8(msg, is_ssl)                        ||
        ajp_msg_append_uint16(msg, (apr_uint16_t) num_headers)) {

        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00968)
               "ajp_marshal_into_msgb: "
               "Error appending the message beginning");
        return APR_EGENERAL;
    }

    for (i = 0 ; i < num_headers ; i++) {
        int sc;
        const apr_array_header_t *t = apr_table_elts(r->headers_in);
        const apr_table_entry_t *elts = (apr_table_entry_t *)t->elts;

        if ((sc = sc_for_req_header(elts[i].key)) != UNKNOWN_METHOD) {
            if (ajp_msg_append_uint16(msg, (apr_uint16_t)sc)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00969)
                       "ajp_marshal_into_msgb: "
                       "Error appending the header name");
                return AJP_EOVERFLOW;
            }
        }
        else {
            if (ajp_msg_append_string(msg, elts[i].key)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00970)
                       "ajp_marshal_into_msgb: "
                       "Error appending the header name");
                return AJP_EOVERFLOW;
            }
        }

        if (ajp_msg_append_string(msg, elts[i].val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00971)
                   "ajp_marshal_into_msgb: "
                   "Error appending the header value");
            return AJP_EOVERFLOW;
        }
        ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
                   "ajp_marshal_into_msgb: Header[%d] [%s] = [%s]",
                   i, elts[i].key, elts[i].val);
    }

/* XXXX need to figure out how to do this
    if (s->secret) {
        if (ajp_msg_append_uint8(msg, SC_A_SECRET) ||
            ajp_msg_append_string(msg, s->secret)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                   "Error ajp_marshal_into_msgb - "
                   "Error appending secret");
            return APR_EGENERAL;
        }
    }
 */

    if (r->user) {
        if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
            ajp_msg_append_string(msg, r->user)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00972)
                   "ajp_marshal_into_msgb: "
                   "Error appending the remote user");
            return AJP_EOVERFLOW;
        }
    }
    if (r->ap_auth_type) {
        if (ajp_msg_append_uint8(msg, SC_A_AUTH_TYPE) ||
            ajp_msg_append_string(msg, r->ap_auth_type)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00973)
                   "ajp_marshal_into_msgb: "
                   "Error appending the auth type");
            return AJP_EOVERFLOW;
        }
    }
    /* XXXX  ebcdic (args converted?) */
    if (uri->query) {
        if (ajp_msg_append_uint8(msg, SC_A_QUERY_STRING) ||
            ajp_msg_append_string(msg, uri->query)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00974)
                   "ajp_marshal_into_msgb: "
                   "Error appending the query string");
            return AJP_EOVERFLOW;
        }
    }
    if ((session_route = apr_table_get(r->notes, "session-route"))) {
        if (ajp_msg_append_uint8(msg, SC_A_JVM_ROUTE) ||
            ajp_msg_append_string(msg, session_route)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00975)
                   "ajp_marshal_into_msgb: "
                   "Error appending the jvm route");
            return AJP_EOVERFLOW;
        }
    }
/* XXX: Is the subprocess_env a right place?
 * <Location /examples>
 *   ProxyPass ajp://remote:8009/servlets-examples
 *   SetEnv SSL_SESSION_ID CUSTOM_SSL_SESSION_ID
 * </Location>
 */
    /*
     * Only lookup SSL variables if we are currently running HTTPS.
     * Furthermore ensure that only variables get set in the AJP message
     * that are not NULL and not empty.
     */
    if (is_ssl) {
        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_CLIENT_CERT_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_CERT)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00976)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL certificates");
                return AJP_EOVERFLOW;
            }
        }

        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_CIPHER_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_CIPHER)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00977)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL ciphers");
                return AJP_EOVERFLOW;
            }
        }

        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_SESSION_INDICATOR))
            && envvar[0]) {
            if (ajp_msg_append_uint8(msg, SC_A_SSL_SESSION)
                || ajp_msg_append_string(msg, envvar)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00978)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL session");
                return AJP_EOVERFLOW;
            }
        }

        /* ssl_key_size is required by Servlet 2.3 API */
        if ((envvar = ap_proxy_ssl_val(r->pool, r->server, r->connection, r,
                                       AJP13_SSL_KEY_SIZE_INDICATOR))
            && envvar[0]) {

            if (ajp_msg_append_uint8(msg, SC_A_SSL_KEY_SIZE)
                || ajp_msg_append_uint16(msg, (unsigned short) atoi(envvar))) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00979)
                              "ajp_marshal_into_msgb: "
                              "Error appending the SSL key size");
                return APR_EGENERAL;
            }
        }
    }
    /* If the method was unrecognized, encode it as an attribute */
    if (method == SC_M_JK_STORED) {
        if (ajp_msg_append_uint8(msg, SC_A_STORED_METHOD)
            || ajp_msg_append_string(msg, r->method)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02438)
                          "ajp_marshal_into_msgb: "
                          "Error appending the method '%s' as request attribute",
                          r->method);
            return AJP_EOVERFLOW;
        }
    }
    /* Forward the remote port information, which was forgotten
     * from the builtin data of the AJP 13 protocol.
     * Since the servlet spec allows to retrieve it via getRemotePort(),
     * we provide the port to the Tomcat connector as a request
     * attribute. Modern Tomcat versions know how to retrieve
     * the remote port from this attribute.
     */
    {
        const char *key = SC_A_REQ_REMOTE_PORT;
        char *val = apr_itoa(r->pool, r->useragent_addr->port);
        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, key)   ||
            ajp_msg_append_string(msg, val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00980)
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %s=%s",
                    key, val);
            return AJP_EOVERFLOW;
        }
    }
    /* Forward the local ip address information, which was forgotten
     * from the builtin data of the AJP 13 protocol.
     * Since the servlet spec allows to retrieve it via getLocalAddr(),
     * we provide the address to the Tomcat connector as a request
     * attribute. Modern Tomcat versions know how to retrieve
     * the local address from this attribute.
     */
    {
        const char *key = SC_A_REQ_LOCAL_ADDR;
        char *val = r->connection->local_ip;
        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, key)   ||
            ajp_msg_append_string(msg, val)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02646)
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %s=%s",
                    key, val);
            return AJP_EOVERFLOW;
        }
    }
    /* Use the environment vars prefixed with AJP_
     * and pass it to the header striping that prefix.
     */
    for (i = 0; i < (apr_uint32_t)arr->nelts; i++) {
        if (!strncmp(elts[i].key, "AJP_", 4)) {
            if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
                ajp_msg_append_string(msg, elts[i].key + 4)   ||
                ajp_msg_append_string(msg, elts[i].val)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00981)
                        "ajp_marshal_into_msgb: "
                        "Error appending attribute %s=%s",
                        elts[i].key, elts[i].val);
                return AJP_EOVERFLOW;
            }
        }
    }

    if (ajp_msg_append_uint8(msg, SC_A_ARE_DONE)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00982)
               "ajp_marshal_into_msgb: "
               "Error appending the message end");
        return AJP_EOVERFLOW;
    }

    ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r,
            "ajp_marshal_into_msgb: Done");
    return APR_SUCCESS;
}
Example #4
0
/*
 * Message structure
 *
 *
 AJPV13_REQUEST/AJPV14_REQUEST=
 request_prefix (1) (byte)
 method         (byte)
 protocol       (string)
 req_uri        (string)
 remote_addr    (string)
 remote_host    (string)
 server_name    (string)
 server_port    (short)
 is_ssl         (boolean)
 num_headers    (short)
 num_headers*(req_header_name header_value)

 ?context       (byte)(string)
 ?servlet_path  (byte)(string)
 ?remote_user   (byte)(string)
 ?auth_type     (byte)(string)
 ?query_string  (byte)(string)
 ?jvm_route     (byte)(string)
 ?ssl_cert      (byte)(string)
 ?ssl_cipher    (byte)(string)
 ?ssl_session   (byte)(string)
 ?ssl_key_size  (byte)(int)  
 request_terminator (byte)
 ?body          content_length*(var binary)
 */
ngx_int_t 
ajp_marshal_into_msgb(ajp_msg_t *msg, 
        ngx_http_request_t *r, ngx_http_ajp_loc_conf_t *alcf)
{
    int                  sc;
    int                  method;
    u_char               is_ssl = 0;
    uint16_t             port;
    ngx_uint_t           i, num_headers = 0;
    ngx_str_t            uri, *remote_host, *remote_addr;
    ngx_str_t            temp_str, *jvm_route, port_str;
    ngx_log_t           *log;
    ngx_list_part_t     *part;
    ngx_table_elt_t     *header;
    struct sockaddr_in  *addr;

    log = r->connection->log;

    if ((method = sc_for_req_method_by_id(r)) == UNKNOWN_METHOD) {
        ngx_log_error(NGX_LOG_ERR, log, 0,
                "ajp_marshal_into_msgb - No such method %ui", r->method);
        return NGX_ERROR;
    }

    /* TODO: is_ssl = ?*/

    part = &r->headers_in.headers.part;

    if (alcf->upstream.pass_request_headers) {
        num_headers = sc_for_req_get_headers_num(part);
    }

    remote_host = remote_addr = &r->connection->addr_text;

    addr = (struct sockaddr_in *) r->connection->local_sockaddr;
    /*'struct sockaddr_in' and 'struct sockaddr_in6' has the same offset of port*/
    port = ntohs(addr->sin_port);

    if (sc_for_req_get_uri(r, &uri) != 0) {
        return NGX_ERROR;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
            "Into ajp_marshal_into_msgb, uri: \"%V\", version: \"%V\"",
            &uri, &r->http_protocol);

    ajp_msg_reset(msg);

    if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST)         ||
            ajp_msg_append_uint8(msg, method)                        ||
            ajp_msg_append_string(msg, &r->http_protocol)            ||
            ajp_msg_append_string(msg, &uri)                         ||
            ajp_msg_append_string(msg, remote_addr)                  ||
            ajp_msg_append_string(msg, remote_host)                  ||
            ajp_msg_append_string(msg, &r->headers_in.server)        ||
            ajp_msg_append_uint16(msg, port)                         ||
            ajp_msg_append_uint8(msg, is_ssl)                        ||
            ajp_msg_append_uint16(msg, (uint16_t) num_headers)) {

        ngx_log_error(NGX_LOG_ERR, log, 0,
                "ajp_marshal_into_msgb: "
                "Error appending the message begining");
        return AJP_EOVERFLOW;
    }

    header = part->elts;
    if (alcf->upstream.pass_request_headers) {
        for (i = 0; /* void */; i++) {

            if (i >= part->nelts) {
                if (part->next == NULL) {
                    break;
                }

                part = part->next;
                header = part->elts;
                i = 0;
            }

            if ((sc = sc_for_req_header(&header[i])) != UNKNOWN_METHOD) {
                if (ajp_msg_append_uint16(msg, (uint16_t)sc)) {
                    ngx_log_error(NGX_LOG_ERR, log, 0,
                            "ajp_marshal_into_msgb: "
                            "Error appending the header name");
                    return AJP_EOVERFLOW;
                }
            }
            else {
                if (ajp_msg_append_string(msg, &header[i].key)) {
                    ngx_log_error(NGX_LOG_ERR, log, 0,
                            "ajp_marshal_into_msgb: "
                            "Error appending the header name");
                    return AJP_EOVERFLOW;
                }
            }

            if (sc == SC_REQ_CONNECTION) {
                if (alcf->keep_conn) {
                    header[i].value.data = (u_char *)"keep-alive"; 
                    header[i].value.len = sizeof("keep-alive") - 1; 
                }
                else {
                    header[i].value.data = (u_char *)"close"; 
                    header[i].value.len = sizeof("close") - 1; 
                }
            }

            if (ajp_msg_append_string(msg, &header[i].value)) {
                ngx_log_error(NGX_LOG_ERR, log, 0,
                        "ajp_marshal_into_msgb: "
                        "Error appending the header value");
                return AJP_EOVERFLOW;
            }

            ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
                    "ajp_marshal_into_msgb: Header[%d] [%V] = [%V], size:%z",
                    i, &header[i].key, &header[i].value, ngx_buf_size(msg->buf));
        }
    }

    if (r->headers_in.user.len != 0) {
        if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
                ajp_msg_append_string(msg, &r->headers_in.user)) {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ajp_marshal_into_msgb: "
                    "Error appending the remote user");
            return AJP_EOVERFLOW;
        }
    }

    sc_for_req_auth_type(r, &temp_str);
    if (temp_str.len > 0) {
        if (ajp_msg_append_uint8(msg, SC_A_AUTH_TYPE) ||
                ajp_msg_append_string(msg, &temp_str)) 
        {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ajp_marshal_into_msgb: "
                    "Error appending the auth type");
            return AJP_EOVERFLOW;
        }
    }

    if (r->args.len > 0) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
                "ajp_marshal_into_msgb: append_args=\"%V\"", &r->args);

        if (ajp_msg_append_uint8(msg, SC_A_QUERY_STRING) ||
                ajp_msg_append_string(msg, &r->args)) {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ajp_marshal_into_msgb: "
                    "Error appending the query string");
            return AJP_EOVERFLOW;
        }
    }

    jvm_route = sc_for_req_get_header_vaule_by_hash(&r->headers_in.headers.part,
            (u_char *)"session-route", sizeof("session-route") - 1);
    if (jvm_route != NULL) {
        if (ajp_msg_append_uint8(msg, SC_A_JVM_ROUTE) ||
                ajp_msg_append_string(msg, jvm_route)) {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ajp_marshal_into_msgb: "
                    "Error appending the jvm route");
            return AJP_EOVERFLOW;
        }
    }

    /*TODO SSL*/

    /* Forward the remote port information, which was forgotten
     * from the builtin data of the AJP 13 protocol.
     * Since the servlet spec allows to retrieve it via getRemotePort(),
     * we provide the port to the Tomcat connector as a request
     * attribute. Modern Tomcat versions know how to retrieve
     * the remote port from this attribute.
     */
    {
        u_char buf[6] = {0};
        temp_str.data = (u_char *)SC_A_REQ_REMOTE_PORT;
        temp_str.len = sizeof(SC_A_REQ_REMOTE_PORT) - 1;

        addr = (struct sockaddr_in *) r->connection->sockaddr;

        /*'struct sockaddr_in' and 'struct sockaddr_in6' has the same offset of port*/
        port = ntohs(addr->sin_port);

        /*port < 65536*/
        ngx_snprintf(buf, 6, "%d", port);
        port_str.data = buf;
        port_str.len = ngx_strlen(buf);

        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
                ajp_msg_append_string(msg, &temp_str)   ||
                ajp_msg_append_string(msg, &port_str)) {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %V=%V",
                    &temp_str, &port_str);
            return AJP_EOVERFLOW;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
                "ajp_marshal_into_msgb: attribute %V %V", &temp_str, &port_str);
    }

    if (ajp_msg_append_uint8(msg, SC_A_ARE_DONE)) {
        ngx_log_error(NGX_LOG_ERR, log, 0,
                "ajp_marshal_into_msgb: "
                "Error appending the message end");
        return AJP_EOVERFLOW;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
            "ajp_marshal_into_msgb: Done, buff_size:%z", ngx_buf_size(msg->buf));

    return NGX_OK;
}