1 #include "ngx_http_ajp.h"
2
3 extern volatile ngx_cycle_t *ngx_cycle;
4
5
6 static ngx_int_t
ajp_msg_check_header(ajp_msg_t * msg)7 ajp_msg_check_header(ajp_msg_t *msg)
8 {
9 u_char *head = msg->buf->pos;
10
11 if (!((head[0] == 0x41 && head[1] == 0x42) ||
12 (head[0] == 0x12 && head[1] == 0x34)))
13 {
14 ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
15 "ajp_check_msg_header() got bad signature %02Xd%02Xd",
16 head[0], head[1]);
17
18 return NGX_ERROR;
19 }
20
21 return NGX_OK;
22 }
23
24
25 ngx_int_t
ajp_msg_is_zero_length(u_char * head)26 ajp_msg_is_zero_length(u_char *head)
27 {
28
29 if (head[0] == 0x41 && head[1] == 0x42 &&
30 head[3] == 0x00 && head[4] == 0x00)
31 {
32 return 1;
33 }
34
35 return 0;
36 }
37
38
39 ngx_int_t
ajp_msg_parse_begin(ajp_msg_t * msg)40 ajp_msg_parse_begin(ajp_msg_t *msg)
41 {
42 ngx_buf_t *buf = msg->buf;
43
44 if (buf->last <= buf->pos + AJP_HEADER_LEN) {
45 return NGX_ERROR;
46 }
47
48 if (ajp_msg_check_header(msg) != NGX_OK) {
49 return NGX_ERROR;
50 }
51
52 buf->pos += AJP_HEADER_LEN;
53
54 return NGX_OK;
55 }
56
57
58 ngx_int_t
ajp_msg_reset(ajp_msg_t * msg)59 ajp_msg_reset(ajp_msg_t *msg)
60 {
61 ngx_buf_t *buf = msg->buf;
62
63 if (buf->end > buf->start + AJP_HEADER_LEN) {
64 buf->pos = buf->last = buf->start + AJP_HEADER_LEN;
65
66 } else {
67 return NGX_ERROR;
68 }
69
70 return NGX_OK;
71 }
72
73
74 ajp_msg_t *
ajp_msg_reuse(ajp_msg_t * msg)75 ajp_msg_reuse(ajp_msg_t *msg)
76 {
77 memset(msg, 0, sizeof(ajp_msg_t));
78
79 return msg;
80 }
81
82
83 ngx_int_t
ajp_msg_end(ajp_msg_t * msg)84 ajp_msg_end(ajp_msg_t *msg)
85 {
86 size_t len;
87 ngx_buf_t *buf;
88
89 buf = msg->buf;
90 len = buf->last - buf->start - AJP_HEADER_LEN;
91
92 if (msg->server_side) {
93 buf->start[0] = 0x41;
94 buf->start[1] = 0x42;
95 } else {
96 buf->start[0] = 0x12;
97 buf->start[1] = 0x34;
98 }
99
100 buf->start[2] = (u_char)((len >> 8) & 0xFF);
101 buf->start[3] = (u_char)(len & 0xFF);
102
103 buf->pos = buf->start;
104
105 return NGX_OK;
106 }
107
108
109 ngx_int_t
ajp_log_overflow(ajp_msg_t * msg,const char * context)110 ajp_log_overflow(ajp_msg_t *msg, const char *context)
111 {
112 ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0,
113 "%s(): BufferOverflowException pos:%p, last:%p, end:%p",
114 context, msg->buf->pos, msg->buf->last, msg->buf->end);
115
116 return AJP_EOVERFLOW;
117 }
118
119
120 ngx_int_t
ajp_msg_append_uint32(ajp_msg_t * msg,uint32_t value)121 ajp_msg_append_uint32(ajp_msg_t *msg, uint32_t value)
122 {
123 ngx_buf_t *buf;
124
125 buf = msg->buf;
126
127 if ((buf->last + 4) > buf->end) {
128 return ajp_log_overflow(msg, "ajp_msg_append_uint32");
129 }
130
131 *buf->last++ = (u_char)((value >> 24) & 0xFF);
132 *buf->last++ = (u_char)((value >> 16) & 0xFF);
133 *buf->last++ = (u_char)((value >> 8) & 0xFF);
134 *buf->last++ = (u_char)(value & 0xFF);
135
136 return NGX_OK;
137 }
138
139
140 ngx_int_t
ajp_msg_append_uint16(ajp_msg_t * msg,uint16_t value)141 ajp_msg_append_uint16(ajp_msg_t *msg, uint16_t value)
142 {
143 ngx_buf_t *buf;
144
145 buf = msg->buf;
146
147 if ((buf->last + 2) > buf->end) {
148 return ajp_log_overflow(msg, "ajp_msg_append_uint16");
149 }
150
151 *buf->last++ = (u_char)((value >> 8) & 0xFF);
152 *buf->last++ = (u_char)(value & 0xFF);
153
154 return NGX_OK;
155 }
156
157
158 ngx_int_t
ajp_msg_append_uint8(ajp_msg_t * msg,u_char value)159 ajp_msg_append_uint8(ajp_msg_t *msg, u_char value)
160 {
161 ngx_buf_t *buf;
162
163 buf = msg->buf;
164
165 if ((buf->last + 1) > buf->end) {
166 return ajp_log_overflow(msg, "ajp_msg_append_uint8");
167 }
168
169 *buf->last++ = value;
170
171 return NGX_OK;
172 }
173
174
175 ngx_int_t
ajp_msg_append_string(ajp_msg_t * msg,ngx_str_t * value)176 ajp_msg_append_string(ajp_msg_t *msg, ngx_str_t *value)
177 {
178 ngx_buf_t *buf;
179
180 if (value == NULL) {
181 return(ajp_msg_append_uint16(msg, 0xFFFF));
182 }
183
184 buf = msg->buf;
185
186 if ((buf->last + 2 + value->len + 1) > buf->end) {
187 return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
188 }
189
190 ajp_msg_append_uint16(msg, (uint16_t) value->len);
191
192 ngx_memcpy(buf->last, value->data, value->len);
193 buf->last += value->len;
194
195 *buf->last++ = '\0';
196
197 return NGX_OK;
198 }
199
200
201 ngx_int_t
ajp_msg_get_uint32(ajp_msg_t * msg,uint32_t * rvalue)202 ajp_msg_get_uint32(ajp_msg_t *msg, uint32_t *rvalue)
203 {
204 uint32_t value;
205 ngx_buf_t *buf;
206
207 buf = msg->buf;
208 if ((buf->pos + 4) > buf->last) {
209 return ajp_log_overflow(msg, "ajp_msg_get_uint32");
210 }
211
212 value = ((*buf->pos++ & 0xFF) << 24);
213 value |= ((*buf->pos++ & 0xFF) << 16);
214 value |= ((*buf->pos++ & 0xFF) << 8);
215 value |= ((*buf->pos++ & 0xFF));
216
217 *rvalue = value;
218
219 return NGX_OK;
220 }
221
222
223 ngx_int_t
ajp_msg_get_uint16(ajp_msg_t * msg,uint16_t * rvalue)224 ajp_msg_get_uint16(ajp_msg_t *msg, uint16_t *rvalue)
225 {
226 uint16_t value;
227 ngx_buf_t *buf;
228
229 buf = msg->buf;
230
231 if ((buf->pos + 2) > buf->last) {
232 return ajp_log_overflow(msg, "ajp_msg_get_uint16");
233 }
234
235 value = ((*buf->pos++ & 0xFF) << 8);
236 value += ((*buf->pos++) & 0xFF);
237
238 *rvalue = value;
239
240 return NGX_OK;
241 }
242
243
244 ngx_int_t
ajp_msg_peek_uint16(ajp_msg_t * msg,uint16_t * rvalue)245 ajp_msg_peek_uint16(ajp_msg_t *msg, uint16_t *rvalue)
246 {
247 uint16_t value;
248 ngx_buf_t *buf;
249
250 buf = msg->buf;
251
252 if ((buf->pos + 2) > buf->last) {
253 return ajp_log_overflow(msg, "ajp_msg_peek_uint16");
254 }
255
256 value = ((*buf->pos & 0xFF) << 8);
257 value += ((*buf->pos + 1) & 0xFF);
258
259 *rvalue = value;
260
261 return NGX_OK;
262 }
263
264
265 ngx_int_t
ajp_msg_peek_uint8(ajp_msg_t * msg,u_char * rvalue)266 ajp_msg_peek_uint8(ajp_msg_t *msg, u_char *rvalue)
267 {
268 if ((msg->buf->pos + 1) > msg->buf->last) {
269 return ajp_log_overflow(msg, "ajp_msg_peek_uint8");
270 }
271
272 *rvalue = *msg->buf->pos;
273
274 return NGX_OK;
275 }
276
277
278 ngx_int_t
ajp_msg_get_uint8(ajp_msg_t * msg,u_char * rvalue)279 ajp_msg_get_uint8(ajp_msg_t *msg, u_char *rvalue)
280 {
281 if ((msg->buf->pos + 1) > msg->buf->last) {
282 return ajp_log_overflow(msg, "ajp_msg_get_uint8");
283 }
284
285 *rvalue = *msg->buf->pos++;
286
287 return NGX_OK;
288 }
289
290
291 ngx_int_t
ajp_msg_get_string(ajp_msg_t * msg,ngx_str_t * value)292 ajp_msg_get_string(ajp_msg_t *msg, ngx_str_t *value)
293 {
294 u_char *start;
295 uint16_t size;
296 ngx_int_t status;
297 ngx_buf_t *buf;
298
299 buf = msg->buf;
300 status = ajp_msg_get_uint16(msg, &size);
301
302 start = buf->pos;
303
304 if ((status != NGX_OK) || (start + size + 1 > buf->last)) {
305 return ajp_log_overflow(msg, "ajp_msg_get_string");
306 }
307
308 buf->pos += (size_t)size;
309 buf->pos++; /* a String in AJP is NULL terminated */
310
311 value->data = start;
312 value->len = size;
313
314 return NGX_OK;
315 }
316
317
318 ngx_int_t
ajp_msg_create(ngx_pool_t * pool,size_t size,ajp_msg_t ** rmsg)319 ajp_msg_create(ngx_pool_t *pool, size_t size, ajp_msg_t **rmsg)
320 {
321 ajp_msg_t *msg;
322
323 msg = (ajp_msg_t *)ngx_pcalloc(pool, sizeof(ajp_msg_t));
324 if (msg == NULL) {
325 return NGX_ERROR;
326 }
327
328 msg->server_side = 0;
329
330 msg->buf = ngx_create_temp_buf(pool, size);
331
332 if (msg->buf == NULL) {
333 return NGX_ERROR;
334 }
335
336 *rmsg = msg;
337
338 return NGX_OK;
339 }
340
341
342 ngx_int_t
ajp_msg_create_buffer(ngx_pool_t * pool,size_t size,ajp_msg_t * msg)343 ajp_msg_create_buffer(ngx_pool_t *pool, size_t size, ajp_msg_t *msg)
344 {
345 msg->server_side = 0;
346
347 msg->buf = ngx_create_temp_buf(pool, size);
348 if (msg->buf == NULL) {
349 return NGX_ERROR;
350 }
351
352 return NGX_OK;
353 }
354
355
356 ngx_int_t
ajp_msg_create_without_buffer(ngx_pool_t * pool,ajp_msg_t ** rmsg)357 ajp_msg_create_without_buffer(ngx_pool_t *pool, ajp_msg_t **rmsg)
358 {
359 ajp_msg_t *msg;
360
361 msg = (ajp_msg_t *)ngx_pcalloc(pool, sizeof(ajp_msg_t));
362 if (msg == NULL) {
363 return NGX_ERROR;
364 }
365
366 msg->server_side = 0;
367
368 *rmsg = msg;
369
370 return NGX_OK;
371 }
372
373
374 ngx_int_t
ajp_alloc_data_msg(ngx_pool_t * pool,ajp_msg_t * msg)375 ajp_alloc_data_msg(ngx_pool_t *pool, ajp_msg_t *msg)
376 {
377 ngx_int_t rc;
378
379 if ((rc = ajp_msg_create_buffer(pool, AJP_HEADER_SZ + 1, msg)) != NGX_OK) {
380 return rc;
381 }
382
383 ajp_msg_reset(msg);
384
385 return NGX_OK;
386 }
387
388
389 ngx_int_t
ajp_data_msg_end(ajp_msg_t * msg,size_t len)390 ajp_data_msg_end(ajp_msg_t *msg, size_t len)
391 {
392 ngx_buf_t *buf;
393
394 buf = msg->buf;
395
396 buf->last = buf->start + AJP_HEADER_SZ;
397
398 ajp_msg_end(msg);
399
400 buf->start[AJP_HEADER_SZ - 2] = (u_char)((len >> 8) & 0xFF);
401 buf->start[AJP_HEADER_SZ - 1] = (u_char)(len & 0xFF);
402
403 /* len include AJP_HEADER_SIZE_LEN */
404 len += AJP_HEADER_SZ_LEN;
405 buf->start[AJP_HEADER_LEN - 2] = (u_char)((len >> 8) & 0xFF);
406 buf->start[AJP_HEADER_LEN - 1] = (u_char)(len & 0xFF);
407
408 return NGX_OK;
409 }
410
411
412 u_char *
ajp_msg_dump(ngx_pool_t * pool,ajp_msg_t * msg,char * err)413 ajp_msg_dump(ngx_pool_t *pool, ajp_msg_t *msg, char *err)
414 {
415 size_t i, len, dump;
416 u_char *rv, *p, *last;
417 ngx_buf_t *buf;
418
419 buf = msg->buf;
420
421 dump = DUMP_LENGTH;
422 if (dump >(size_t)(buf->last - buf->pos)) {
423 dump = buf->last - buf->pos;
424 }
425
426 len = dump + 256;
427 p = rv = ngx_pcalloc(pool, len);
428 if (rv == NULL) {
429 return NULL;
430 }
431
432 last = rv + len;
433
434 p = ngx_snprintf(p, len,
435 "ajp_msg_dump(): \"%s\", start:%p, pos:%p, last:%p \n"
436 "dump packet: \n",
437 err, buf->start, buf->pos, buf->last);
438
439 for (i = 0; i < dump; i ++) {
440 p = ngx_snprintf(p, last - p, "%02xd ", buf->pos[i]);
441
442 if ((i+1) % 16 == 0) {
443 p = ngx_snprintf(p, last - p, "\n");
444 }
445 }
446
447 p = ngx_snprintf(p, last - p, "\n");
448
449 return rv;
450 }
451
452
453 /* TODO: health check */
454 ngx_int_t
ajp_msg_serialize_ping(ajp_msg_t * msg)455 ajp_msg_serialize_ping(ajp_msg_t *msg)
456 {
457 ngx_int_t rc;
458
459 ajp_msg_reset(msg);
460
461 if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_PING)) != NGX_OK) {
462 return rc;
463 }
464
465 return NGX_OK;
466 }
467
468
469 /* TODO: health check */
470 ngx_int_t
ajp_msg_serialize_cping(ajp_msg_t * msg)471 ajp_msg_serialize_cping(ajp_msg_t *msg)
472 {
473 ngx_int_t rc;
474
475 ajp_msg_reset(msg);
476
477 if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_CPING)) != NGX_OK) {
478 return rc;
479 }
480
481 return NGX_OK;
482 }
483