1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "httpd.h" 18#include "http_core.h" 19#include "http_log.h" 20#include "util_fcgi.h" 21 22/* we know core's module_index is 0 */ 23#undef APLOG_MODULE_INDEX 24#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX 25 26AP_DECLARE(void) ap_fcgi_header_to_array(ap_fcgi_header *h, 27 unsigned char a[]) 28{ 29 a[AP_FCGI_HDR_VERSION_OFFSET] = h->version; 30 a[AP_FCGI_HDR_TYPE_OFFSET] = h->type; 31 a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET] = h->requestIdB1; 32 a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET] = h->requestIdB0; 33 a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET] = h->contentLengthB1; 34 a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET] = h->contentLengthB0; 35 a[AP_FCGI_HDR_PADDING_LEN_OFFSET] = h->paddingLength; 36 a[AP_FCGI_HDR_RESERVED_OFFSET] = h->reserved; 37} 38 39AP_DECLARE(void) ap_fcgi_header_from_array(ap_fcgi_header *h, 40 unsigned char a[]) 41{ 42 h->version = a[AP_FCGI_HDR_VERSION_OFFSET]; 43 h->type = a[AP_FCGI_HDR_TYPE_OFFSET]; 44 h->requestIdB1 = a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET]; 45 h->requestIdB0 = a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET]; 46 h->contentLengthB1 = a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET]; 47 h->contentLengthB0 = a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET]; 48 h->paddingLength = a[AP_FCGI_HDR_PADDING_LEN_OFFSET]; 49 h->reserved = a[AP_FCGI_HDR_RESERVED_OFFSET]; 50} 51 52AP_DECLARE(void) ap_fcgi_header_fields_from_array(unsigned char *version, 53 unsigned char *type, 54 apr_uint16_t *request_id, 55 apr_uint16_t *content_len, 56 unsigned char *padding_len, 57 unsigned char a[]) 58{ 59 *version = a[AP_FCGI_HDR_VERSION_OFFSET]; 60 *type = a[AP_FCGI_HDR_TYPE_OFFSET]; 61 *request_id = (a[AP_FCGI_HDR_REQUEST_ID_B1_OFFSET] << 8) 62 + a[AP_FCGI_HDR_REQUEST_ID_B0_OFFSET]; 63 *content_len = (a[AP_FCGI_HDR_CONTENT_LEN_B1_OFFSET] << 8) 64 + a[AP_FCGI_HDR_CONTENT_LEN_B0_OFFSET]; 65 *padding_len = a[AP_FCGI_HDR_PADDING_LEN_OFFSET]; 66} 67 68AP_DECLARE(void) ap_fcgi_begin_request_body_to_array(ap_fcgi_begin_request_body *h, 69 unsigned char a[]) 70{ 71 a[AP_FCGI_BRB_ROLEB1_OFFSET] = h->roleB1; 72 a[AP_FCGI_BRB_ROLEB0_OFFSET] = h->roleB0; 73 a[AP_FCGI_BRB_FLAGS_OFFSET] = h->flags; 74 a[AP_FCGI_BRB_RESERVED0_OFFSET] = h->reserved[0]; 75 a[AP_FCGI_BRB_RESERVED1_OFFSET] = h->reserved[1]; 76 a[AP_FCGI_BRB_RESERVED2_OFFSET] = h->reserved[2]; 77 a[AP_FCGI_BRB_RESERVED3_OFFSET] = h->reserved[3]; 78 a[AP_FCGI_BRB_RESERVED4_OFFSET] = h->reserved[4]; 79} 80 81AP_DECLARE(void) ap_fcgi_fill_in_header(ap_fcgi_header *header, 82 unsigned char type, 83 apr_uint16_t request_id, 84 apr_uint16_t content_len, 85 unsigned char padding_len) 86{ 87 header->version = AP_FCGI_VERSION_1; 88 89 header->type = type; 90 91 header->requestIdB1 = ((request_id >> 8) & 0xff); 92 header->requestIdB0 = ((request_id) & 0xff); 93 94 header->contentLengthB1 = ((content_len >> 8) & 0xff); 95 header->contentLengthB0 = ((content_len) & 0xff); 96 97 header->paddingLength = padding_len; 98 99 header->reserved = 0; 100} 101 102AP_DECLARE(void) ap_fcgi_fill_in_request_body(ap_fcgi_begin_request_body *brb, 103 int role, 104 unsigned char flags) 105{ 106 brb->roleB1 = ((role >> 8) & 0xff); 107 brb->roleB0 = (role & 0xff); 108 brb->flags = flags; 109 brb->reserved[0] = 0; 110 brb->reserved[1] = 0; 111 brb->reserved[2] = 0; 112 brb->reserved[3] = 0; 113 brb->reserved[4] = 0; 114} 115 116AP_DECLARE(apr_size_t) ap_fcgi_encoded_env_len(apr_table_t *env, 117 apr_size_t maxlen, 118 int *starting_elem) 119{ 120 const apr_array_header_t *envarr; 121 const apr_table_entry_t *elts; 122 apr_size_t envlen, actualenvlen; 123 int i; 124 125 if (maxlen > AP_FCGI_MAX_CONTENT_LEN) { 126 maxlen = AP_FCGI_MAX_CONTENT_LEN; 127 } 128 129 envarr = apr_table_elts(env); 130 elts = (const apr_table_entry_t *) envarr->elts; 131 132 /* envlen - speculative, may overflow the limit 133 * actualenvlen - len required without overflowing 134 */ 135 envlen = actualenvlen = 0; 136 for (i = *starting_elem; i < envarr->nelts; ) { 137 apr_size_t keylen, vallen; 138 139 if (!elts[i].key) { 140 (*starting_elem)++; 141 i++; 142 continue; 143 } 144 145 keylen = strlen(elts[i].key); 146 147 if (keylen >> 7 == 0) { 148 envlen += 1; 149 } 150 else { 151 envlen += 4; 152 } 153 154 envlen += keylen; 155 156 vallen = strlen(elts[i].val); 157 158 if (vallen >> 7 == 0) { 159 envlen += 1; 160 } 161 else { 162 envlen += 4; 163 } 164 165 envlen += vallen; 166 167 if (envlen > maxlen) { 168 break; 169 } 170 171 actualenvlen = envlen; 172 (*starting_elem)++; 173 i++; 174 } 175 176 return actualenvlen; 177} 178 179AP_DECLARE(apr_status_t) ap_fcgi_encode_env(request_rec *r, 180 apr_table_t *env, 181 void *buffer, 182 apr_size_t buflen, 183 int *starting_elem) 184{ 185 apr_status_t rv = APR_SUCCESS; 186 const apr_array_header_t *envarr; 187 const apr_table_entry_t *elts; 188 char *itr; 189 int i; 190 191 envarr = apr_table_elts(env); 192 elts = (const apr_table_entry_t *) envarr->elts; 193 194 itr = buffer; 195 196 for (i = *starting_elem; i < envarr->nelts; ) { 197 apr_size_t keylen, vallen; 198 199 if (!elts[i].key) { 200 (*starting_elem)++; 201 i++; 202 continue; 203 } 204 205 keylen = strlen(elts[i].key); 206 207 if (keylen >> 7 == 0) { 208 if (buflen < 1) { 209 rv = APR_ENOSPC; /* overflow */ 210 break; 211 } 212 itr[0] = keylen & 0xff; 213 itr += 1; 214 buflen -= 1; 215 } 216 else { 217 if (buflen < 4) { 218 rv = APR_ENOSPC; /* overflow */ 219 break; 220 } 221 itr[0] = ((keylen >> 24) & 0xff) | 0x80; 222 itr[1] = ((keylen >> 16) & 0xff); 223 itr[2] = ((keylen >> 8) & 0xff); 224 itr[3] = ((keylen) & 0xff); 225 itr += 4; 226 buflen -= 4; 227 } 228 229 vallen = strlen(elts[i].val); 230 231 if (vallen >> 7 == 0) { 232 if (buflen < 1) { 233 rv = APR_ENOSPC; /* overflow */ 234 break; 235 } 236 itr[0] = vallen & 0xff; 237 itr += 1; 238 buflen -= 1; 239 } 240 else { 241 if (buflen < 4) { 242 rv = APR_ENOSPC; /* overflow */ 243 break; 244 } 245 itr[0] = ((vallen >> 24) & 0xff) | 0x80; 246 itr[1] = ((vallen >> 16) & 0xff); 247 itr[2] = ((vallen >> 8) & 0xff); 248 itr[3] = ((vallen) & 0xff); 249 itr += 4; 250 buflen -= 4; 251 } 252 253 if (buflen < keylen) { 254 rv = APR_ENOSPC; /* overflow */ 255 break; 256 } 257 memcpy(itr, elts[i].key, keylen); 258 itr += keylen; 259 buflen -= keylen; 260 261 if (buflen < vallen) { 262 rv = APR_ENOSPC; /* overflow */ 263 break; 264 } 265 memcpy(itr, elts[i].val, vallen); 266 itr += vallen; 267 268 if (buflen == vallen) { 269 (*starting_elem)++; 270 i++; 271 break; /* filled up predicted space, as expected */ 272 } 273 274 buflen -= vallen; 275 276 (*starting_elem)++; 277 i++; 278 } 279 280 if (rv != APR_SUCCESS) { 281 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 282 APLOGNO(02492) "ap_fcgi_encode_env: out of space " 283 "encoding environment"); 284 } 285 286 return rv; 287} 288