Blame server/util_fcgi.c

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#include "httpd.h"
Packit 90a5c9
#include "http_core.h"
Packit 90a5c9
#include "http_log.h"
Packit 90a5c9
#include "util_fcgi.h"
Packit 90a5c9
Packit 90a5c9
/* we know core's module_index is 0 */
Packit 90a5c9
#undef APLOG_MODULE_INDEX
Packit 90a5c9
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_header_to_array(ap_fcgi_header *h,
Packit 90a5c9
                                         unsigned char a[])
Packit 90a5c9
{
Packit 90a5c9
    a[AP_FCGI_HDR_VERSION_OFFSET]        = h->version;
Packit 90a5c9
    a[AP_FCGI_HDR_TYPE_OFFSET]           = h->type;
Packit 90a5c9
    a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET]  = h->requestIdB1;
Packit 90a5c9
    a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET]  = h->requestIdB0;
Packit 90a5c9
    a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET] = h->contentLengthB1;
Packit 90a5c9
    a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET] = h->contentLengthB0;
Packit 90a5c9
    a[AP_FCGI_HDR_PADDING_LEN_OFFSET]    = h->paddingLength;
Packit 90a5c9
    a[AP_FCGI_HDR_RESERVED_OFFSET]       = h->reserved;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_header_from_array(ap_fcgi_header *h,
Packit 90a5c9
                                           unsigned char a[])
Packit 90a5c9
{
Packit 90a5c9
    h->version         = a[AP_FCGI_HDR_VERSION_OFFSET];
Packit 90a5c9
    h->type            = a[AP_FCGI_HDR_TYPE_OFFSET];
Packit 90a5c9
    h->requestIdB1     = a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET];
Packit 90a5c9
    h->requestIdB0     = a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET];
Packit 90a5c9
    h->contentLengthB1 = a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET];
Packit 90a5c9
    h->contentLengthB0 = a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET];
Packit 90a5c9
    h->paddingLength   = a[AP_FCGI_HDR_PADDING_LEN_OFFSET];
Packit 90a5c9
    h->reserved        = a[AP_FCGI_HDR_RESERVED_OFFSET];
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_header_fields_from_array(unsigned char *version,
Packit 90a5c9
                                                  unsigned char *type,
Packit 90a5c9
                                                  apr_uint16_t *request_id,
Packit 90a5c9
                                                  apr_uint16_t *content_len,
Packit 90a5c9
                                                  unsigned char *padding_len,
Packit 90a5c9
                                                  unsigned char a[])
Packit 90a5c9
{
Packit 90a5c9
    *version         = a[AP_FCGI_HDR_VERSION_OFFSET];
Packit 90a5c9
    *type            = a[AP_FCGI_HDR_TYPE_OFFSET];
Packit 90a5c9
    *request_id      = (a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET] << 8)
Packit 90a5c9
                     +  a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET];
Packit 90a5c9
    *content_len     = (a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET] << 8)
Packit 90a5c9
                     +  a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET];
Packit 90a5c9
    *padding_len     = a[AP_FCGI_HDR_PADDING_LEN_OFFSET];
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_begin_request_body_to_array(ap_fcgi_begin_request_body *h,
Packit 90a5c9
                                                     unsigned char a[])
Packit 90a5c9
{
Packit 90a5c9
    a[AP_FCGI_BRB_ROLEB1_OFFSET]    = h->roleB1;
Packit 90a5c9
    a[AP_FCGI_BRB_ROLEB0_OFFSET]    = h->roleB0;
Packit 90a5c9
    a[AP_FCGI_BRB_FLAGS_OFFSET]     = h->flags;
Packit 90a5c9
    a[AP_FCGI_BRB_RESERVED0_OFFSET] = h->reserved[0];
Packit 90a5c9
    a[AP_FCGI_BRB_RESERVED1_OFFSET] = h->reserved[1];
Packit 90a5c9
    a[AP_FCGI_BRB_RESERVED2_OFFSET] = h->reserved[2];
Packit 90a5c9
    a[AP_FCGI_BRB_RESERVED3_OFFSET] = h->reserved[3];
Packit 90a5c9
    a[AP_FCGI_BRB_RESERVED4_OFFSET] = h->reserved[4];
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_fill_in_header(ap_fcgi_header *header,
Packit 90a5c9
                                        unsigned char type,
Packit 90a5c9
                                        apr_uint16_t request_id,
Packit 90a5c9
                                        apr_uint16_t content_len,
Packit 90a5c9
                                        unsigned char padding_len)
Packit 90a5c9
{
Packit 90a5c9
    header->version = AP_FCGI_VERSION_1;
Packit 90a5c9
Packit 90a5c9
    header->type = type;
Packit 90a5c9
Packit 90a5c9
    header->requestIdB1 = ((request_id >> 8) & 0xff);
Packit 90a5c9
    header->requestIdB0 = ((request_id) & 0xff);
Packit 90a5c9
Packit 90a5c9
    header->contentLengthB1 = ((content_len >> 8) & 0xff);
Packit 90a5c9
    header->contentLengthB0 = ((content_len) & 0xff);
Packit 90a5c9
Packit 90a5c9
    header->paddingLength = padding_len;
Packit 90a5c9
Packit 90a5c9
    header->reserved = 0;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_fcgi_fill_in_request_body(ap_fcgi_begin_request_body *brb,
Packit 90a5c9
                                              int role,
Packit 90a5c9
                                              unsigned char flags)
Packit 90a5c9
{
Packit 90a5c9
    brb->roleB1 = ((role >> 8) & 0xff);
Packit 90a5c9
    brb->roleB0 = (role & 0xff);
Packit 90a5c9
    brb->flags = flags;
Packit 90a5c9
    brb->reserved[0] = 0;
Packit 90a5c9
    brb->reserved[1] = 0;
Packit 90a5c9
    brb->reserved[2] = 0;
Packit 90a5c9
    brb->reserved[3] = 0;
Packit 90a5c9
    brb->reserved[4] = 0;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_size_t) ap_fcgi_encoded_env_len(apr_table_t *env,
Packit 90a5c9
                                               apr_size_t maxlen,
Packit 90a5c9
                                               int *starting_elem)
Packit 90a5c9
{
Packit 90a5c9
    const apr_array_header_t *envarr;
Packit 90a5c9
    const apr_table_entry_t *elts;
Packit 90a5c9
    apr_size_t envlen, actualenvlen;
Packit 90a5c9
    int i;
Packit 90a5c9
Packit 90a5c9
    if (maxlen > AP_FCGI_MAX_CONTENT_LEN) {
Packit 90a5c9
        maxlen = AP_FCGI_MAX_CONTENT_LEN;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    envarr = apr_table_elts(env);
Packit 90a5c9
    elts = (const apr_table_entry_t *) envarr->elts;
Packit 90a5c9
Packit 90a5c9
    /* envlen - speculative, may overflow the limit
Packit 90a5c9
     * actualenvlen - len required without overflowing
Packit 90a5c9
     */
Packit 90a5c9
    envlen = actualenvlen = 0;
Packit 90a5c9
    for (i = *starting_elem; i < envarr->nelts; ) {
Packit 90a5c9
        apr_size_t keylen, vallen;
Packit 90a5c9
Packit 90a5c9
        if (!elts[i].key) {
Packit 90a5c9
            (*starting_elem)++;
Packit 90a5c9
            i++;
Packit 90a5c9
            continue;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        keylen = strlen(elts[i].key);
Packit 90a5c9
Packit 90a5c9
        if (keylen >> 7 == 0) {
Packit 90a5c9
            envlen += 1;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            envlen += 4;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        envlen += keylen;
Packit 90a5c9
Packit 90a5c9
        vallen = elts[i].val ? strlen(elts[i].val) : 0;
Packit 90a5c9
Packit 90a5c9
        if (vallen >> 7 == 0) {
Packit 90a5c9
            envlen += 1;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            envlen += 4;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        envlen += vallen;
Packit 90a5c9
Packit 90a5c9
        if (envlen > maxlen) {
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        actualenvlen = envlen;
Packit 90a5c9
        (*starting_elem)++;
Packit 90a5c9
        i++;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return actualenvlen;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_fcgi_encode_env(request_rec *r,
Packit 90a5c9
                                            apr_table_t *env,
Packit 90a5c9
                                            void *buffer,
Packit 90a5c9
                                            apr_size_t buflen,
Packit 90a5c9
                                            int *starting_elem)
Packit 90a5c9
{
Packit 90a5c9
    apr_status_t rv = APR_SUCCESS;
Packit 90a5c9
    const apr_array_header_t *envarr;
Packit 90a5c9
    const apr_table_entry_t *elts;
Packit 90a5c9
    char *itr;
Packit 90a5c9
    int i;
Packit 90a5c9
Packit 90a5c9
    envarr = apr_table_elts(env);
Packit 90a5c9
    elts = (const apr_table_entry_t *) envarr->elts;
Packit 90a5c9
Packit 90a5c9
    itr = buffer;
Packit 90a5c9
Packit 90a5c9
    for (i = *starting_elem; i < envarr->nelts; ) {
Packit 90a5c9
        apr_size_t keylen, vallen;
Packit 90a5c9
Packit 90a5c9
        if (!elts[i].key) {
Packit 90a5c9
            (*starting_elem)++;
Packit 90a5c9
            i++;
Packit 90a5c9
            continue;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        keylen = strlen(elts[i].key);
Packit 90a5c9
Packit 90a5c9
        if (keylen >> 7 == 0) {
Packit 90a5c9
            if (buflen < 1) {
Packit 90a5c9
                rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            itr[0] = keylen & 0xff;
Packit 90a5c9
            itr += 1;
Packit 90a5c9
            buflen -= 1;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            if (buflen < 4) {
Packit 90a5c9
                rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            itr[0] = ((keylen >> 24) & 0xff) | 0x80;
Packit 90a5c9
            itr[1] = ((keylen >> 16) & 0xff);
Packit 90a5c9
            itr[2] = ((keylen >> 8) & 0xff);
Packit 90a5c9
            itr[3] = ((keylen) & 0xff);
Packit 90a5c9
            itr += 4;
Packit 90a5c9
            buflen -= 4;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        vallen = elts[i].val ? strlen(elts[i].val) : 0;
Packit 90a5c9
Packit 90a5c9
        if (vallen >> 7 == 0) {
Packit 90a5c9
            if (buflen < 1) {
Packit 90a5c9
                rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            itr[0] = vallen & 0xff;
Packit 90a5c9
            itr += 1;
Packit 90a5c9
            buflen -= 1;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            if (buflen < 4) {
Packit 90a5c9
                rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
            itr[0] = ((vallen >> 24) & 0xff) | 0x80;
Packit 90a5c9
            itr[1] = ((vallen >> 16) & 0xff);
Packit 90a5c9
            itr[2] = ((vallen >> 8) & 0xff);
Packit 90a5c9
            itr[3] = ((vallen) & 0xff);
Packit 90a5c9
            itr += 4;
Packit 90a5c9
            buflen -= 4;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (buflen < keylen) {
Packit 90a5c9
            rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
        memcpy(itr, elts[i].key, keylen);
Packit 90a5c9
        itr += keylen;
Packit 90a5c9
        buflen -= keylen;
Packit 90a5c9
Packit 90a5c9
        if (buflen < vallen) {
Packit 90a5c9
            rv = APR_ENOSPC; /* overflow */
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (elts[i].val) {
Packit 90a5c9
            memcpy(itr, elts[i].val, vallen);
Packit 90a5c9
            itr += vallen;
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (buflen == vallen) {
Packit 90a5c9
            (*starting_elem)++;
Packit 90a5c9
            i++;
Packit 90a5c9
            break; /* filled up predicted space, as expected */
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        buflen -= vallen;
Packit 90a5c9
Packit 90a5c9
        (*starting_elem)++;
Packit 90a5c9
        i++;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (rv != APR_SUCCESS) {
Packit 90a5c9
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02492)
Packit 90a5c9
                      "ap_fcgi_encode_env: out of space "
Packit 90a5c9
                      "encoding environment");
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    return rv;
Packit 90a5c9
}