]> granicus.if.org Git - apache/blob - server/util_fcgi.c
Merge r1741310, r1741461 from trunk:
[apache] / server / util_fcgi.c
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
26 AP_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
39 AP_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
52 AP_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
68 AP_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
81 AP_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
102 AP_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
116 AP_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
179 AP_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, APLOGNO(02492)
282                       "ap_fcgi_encode_env: out of space "
283                       "encoding environment");
284     }
285
286     return rv;
287 }