diff options
Diffstat (limited to 'web/attachments/410030-checkhttpgzipdeflate.patch')
-rw-r--r-- | web/attachments/410030-checkhttpgzipdeflate.patch | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/web/attachments/410030-checkhttpgzipdeflate.patch b/web/attachments/410030-checkhttpgzipdeflate.patch new file mode 100644 index 0000000..0850a70 --- /dev/null +++ b/web/attachments/410030-checkhttpgzipdeflate.patch | |||
@@ -0,0 +1,328 @@ | |||
1 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
2 | index 433c28e..a71cfe6 100644 | ||
3 | --- a/plugins/check_http.c | ||
4 | +++ b/plugins/check_http.c | ||
5 | @@ -41,7 +41,9 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
6 | #include "netutils.h" | ||
7 | #include "utils.h" | ||
8 | #include "base64.h" | ||
9 | +#include "zlib.h" | ||
10 | #include <ctype.h> | ||
11 | +#include <stdlib.h> | ||
12 | |||
13 | #define INPUT_DELIMITER ";" | ||
14 | #define STICKY_NONE 0 | ||
15 | @@ -114,6 +116,8 @@ int followsticky = STICKY_NONE; | ||
16 | int use_ssl = FALSE; | ||
17 | int use_sni = FALSE; | ||
18 | int verbose = FALSE; | ||
19 | +int decompress = FALSE; | ||
20 | +int chunked = FALSE; | ||
21 | int sd; | ||
22 | int min_page_len = 0; | ||
23 | int max_page_len = 0; | ||
24 | @@ -134,6 +138,14 @@ char *perfd_size (int page_len); | ||
25 | void print_help (void); | ||
26 | void print_usage (void); | ||
27 | |||
28 | +int page_content_decompress(const char *in_buf,int in_size, | ||
29 | + char **data,int *out_size,int type); | ||
30 | +int find_header_info(const char* header, | ||
31 | + char* content,const char* keyword); | ||
32 | +int get_content_encoding(const char* header); | ||
33 | +int get_transfer_encoding(const char* header); | ||
34 | +char* decodechunked(char * chunked, unsigned int *inputlen); | ||
35 | + | ||
36 | int | ||
37 | main (int argc, char **argv) | ||
38 | { | ||
39 | @@ -214,6 +226,8 @@ process_arguments (int argc, char **argv) | ||
40 | {"invert-regex", no_argument, NULL, INVERT_REGEX}, | ||
41 | {"use-ipv4", no_argument, 0, '4'}, | ||
42 | {"use-ipv6", no_argument, 0, '6'}, | ||
43 | + {"decompress",no_argument,0,'d'}, | ||
44 | + {"chunked",no_argument,0,'X'}, | ||
45 | {0, 0, 0, 0} | ||
46 | }; | ||
47 | |||
48 | @@ -234,7 +248,7 @@ process_arguments (int argc, char **argv) | ||
49 | } | ||
50 | |||
51 | while (1) { | ||
52 | - c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option); | ||
53 | + c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLSm:M:NdX", longopts, &option); | ||
54 | if (c == -1 || c == EOF) | ||
55 | break; | ||
56 | |||
57 | @@ -406,6 +420,12 @@ process_arguments (int argc, char **argv) | ||
58 | case 'v': /* verbose */ | ||
59 | verbose = TRUE; | ||
60 | break; | ||
61 | + case 'd': /* decompress */ | ||
62 | + decompress = TRUE; | ||
63 | + break; | ||
64 | + case 'X': /*chunked*/ | ||
65 | + chunked = TRUE; | ||
66 | + break; | ||
67 | case 'm': /* min_page_length */ | ||
68 | { | ||
69 | char *tmp; | ||
70 | @@ -793,6 +813,9 @@ check_http (void) | ||
71 | int page_len = 0; | ||
72 | int result = STATE_OK; | ||
73 | |||
74 | + char *uncompress_page; | ||
75 | + int uncompress_page_size; | ||
76 | + | ||
77 | /* try to connect to the host at the given port number */ | ||
78 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) | ||
79 | die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n")); | ||
80 | @@ -870,18 +893,15 @@ check_http (void) | ||
81 | my_send (buf, strlen (buf)); | ||
82 | |||
83 | /* fetch the page */ | ||
84 | - full_page = strdup(""); | ||
85 | + full_page =(char*)malloc(sizeof(char)*4096); | ||
86 | while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) { | ||
87 | - buffer[i] = '\0'; | ||
88 | - asprintf (&full_page_new, "%s%s", full_page, buffer); | ||
89 | - free (full_page); | ||
90 | - full_page = full_page_new; | ||
91 | + full_page = realloc(full_page, pagesize + i); | ||
92 | + memcpy(full_page + pagesize, buffer, i); | ||
93 | pagesize += i; | ||
94 | - | ||
95 | - if (no_body && document_headers_done (full_page)) { | ||
96 | - i = 0; | ||
97 | - break; | ||
98 | - } | ||
99 | + if (no_body && document_headers_done (full_page)) { | ||
100 | + i = 0; | ||
101 | + break; | ||
102 | + } | ||
103 | } | ||
104 | |||
105 | if (i < 0 && errno != ECONNRESET) { | ||
106 | @@ -951,6 +971,28 @@ check_http (void) | ||
107 | } | ||
108 | page += (size_t) strspn (page, "\r\n"); | ||
109 | header[pos - header] = 0; | ||
110 | + | ||
111 | + /*deal chunked data*/ | ||
112 | + if(get_transfer_encoding(header)==1 && chunked) { | ||
113 | + pagesize = pagesize - (page-header); | ||
114 | + page = decodechunked(page,&pagesize); | ||
115 | + } | ||
116 | + else { | ||
117 | + pagesize = get_content_length(header); | ||
118 | + } | ||
119 | + | ||
120 | + /*decompress the page content*/ | ||
121 | + int content_encoding = get_content_encoding(header); | ||
122 | + if(decompress && (content_encoding == 1 || content_encoding == 2)) { | ||
123 | + result = page_content_decompress(page,pagesize,&uncompress_page, | ||
124 | + &uncompress_page_size,content_encoding); | ||
125 | + | ||
126 | + if(result == 0) { | ||
127 | + page = uncompress_page; | ||
128 | + pagesize = uncompress_page_size; | ||
129 | + } | ||
130 | + } | ||
131 | + | ||
132 | if (verbose) | ||
133 | printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, | ||
134 | (no_body ? " [[ skipped ]]" : page)); | ||
135 | @@ -1384,6 +1426,8 @@ print_help (void) | ||
136 | printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | ||
137 | |||
138 | printf (UT_VERBOSE); | ||
139 | + printf (UT_DECOMPRESS); | ||
140 | + printf (UT_CHUNKED); | ||
141 | |||
142 | printf ("\n"); | ||
143 | printf ("%s\n", _("Notes:")); | ||
144 | @@ -1432,3 +1476,167 @@ print_usage (void) | ||
145 | printf (" [-A string] [-k string] [-S] [--sni] [-C <age>] [-T <content-type>]\n"); | ||
146 | printf (" [-j method]\n"); | ||
147 | } | ||
148 | + | ||
149 | +/* HTTP gzip or deflate decompress; | ||
150 | + * type = 1 represent gzip format | ||
151 | + * type = 2 represent deflate format */ | ||
152 | +int page_content_decompress(const char *in_buf,int in_size, | ||
153 | + char **out_buf_ptr, int *out_size,int type) | ||
154 | +{ | ||
155 | + z_stream stream = {0}; /* decompression stream */ | ||
156 | + char *out_buf = NULL; | ||
157 | + int out_buf_bytes = 0; | ||
158 | + char tmp_buf[4096]; | ||
159 | + int result; | ||
160 | + int new_bytes; | ||
161 | + | ||
162 | + stream.zalloc = (alloc_func)0; | ||
163 | + stream.zfree = (free_func)0; | ||
164 | + stream.opaque = (voidpf)0; | ||
165 | + stream.next_in = (void*) in_buf; | ||
166 | + stream.avail_in = in_size; | ||
167 | + stream.next_out = tmp_buf; | ||
168 | + stream.avail_out = sizeof tmp_buf; | ||
169 | + | ||
170 | + switch (type) { | ||
171 | + case 1: /*gzip*/ | ||
172 | + if(inflateInit2(&stream,MAX_WBITS+32) != Z_OK) | ||
173 | + return -1; | ||
174 | + break; | ||
175 | + case 2: /*deflate*/ | ||
176 | + if(inflateInit2(&stream,-MAX_WBITS) != Z_OK) | ||
177 | + return -1; | ||
178 | + } | ||
179 | + | ||
180 | + do { | ||
181 | + result = inflate(&stream,Z_NO_FLUSH); | ||
182 | + switch (result) { | ||
183 | + case Z_BUF_ERROR: | ||
184 | + if(stream.avail_in == 0) | ||
185 | + goto DONE; /*zlib bug */ | ||
186 | + case Z_ERRNO: | ||
187 | + case Z_NEED_DICT: | ||
188 | + case Z_MEM_ERROR: | ||
189 | + case Z_DATA_ERROR: | ||
190 | + inflateEnd(&stream); | ||
191 | + free(out_buf); | ||
192 | + return -1; | ||
193 | + } | ||
194 | + if(stream.avail_out < sizeof tmp_buf) { | ||
195 | + new_bytes = sizeof tmp_buf - stream.avail_out; | ||
196 | + out_buf = realloc(out_buf,out_buf_bytes + new_bytes); | ||
197 | + memcpy (out_buf + out_buf_bytes,tmp_buf,new_bytes); | ||
198 | + out_buf_bytes += new_bytes; | ||
199 | + stream.next_out = tmp_buf; | ||
200 | + stream.avail_out = sizeof tmp_buf; | ||
201 | + } | ||
202 | + else { | ||
203 | + inflateEnd(&stream); | ||
204 | + free(out_buf); | ||
205 | + return -1; | ||
206 | + } | ||
207 | + } | ||
208 | + while(result != Z_STREAM_END); | ||
209 | + | ||
210 | +DONE: | ||
211 | + | ||
212 | + if(inflateEnd(&stream) != Z_OK) { | ||
213 | + free(out_buf); | ||
214 | + return -1; | ||
215 | + } | ||
216 | + | ||
217 | + *out_size = out_buf_bytes; | ||
218 | + out_buf = realloc(out_buf,out_buf_bytes + 1); | ||
219 | + out_buf[out_buf_bytes] = 0; | ||
220 | + *out_buf_ptr = out_buf; | ||
221 | + | ||
222 | + return 0; | ||
223 | +} | ||
224 | + | ||
225 | +/*find content from header data by keyword*/ | ||
226 | +int find_header_info(const char* header,char* content,const char* keyword) { | ||
227 | + char* start = strstr(header,keyword); | ||
228 | + if(start != 0) { | ||
229 | + start = start + strcspn(start,": "); | ||
230 | + start += strspn(start,": "); | ||
231 | + char* end = start + strcspn(start," \r\n"); | ||
232 | + if( content != NULL) { | ||
233 | + memcpy(content,start,end-start); | ||
234 | + } | ||
235 | + return 1; | ||
236 | + } | ||
237 | + else{ | ||
238 | + return 0; | ||
239 | + } | ||
240 | +} | ||
241 | + | ||
242 | +/*find Content-Encoding from the header info; | ||
243 | + *if Content-Encoding equal 'gzip' return 1,or return 0. | ||
244 | + */ | ||
245 | +int get_content_encoding(const char* header) { | ||
246 | + int result = 0; | ||
247 | + int ret = 0; | ||
248 | + char* content_encoding = (char*)malloc(sizeof(char)*10); | ||
249 | + result = find_header_info(header,content_encoding,"Content-Encoding"); | ||
250 | + | ||
251 | + if(result && strncmp(content_encoding,"gzip",4)==0) { | ||
252 | + ret = 1; | ||
253 | + } | ||
254 | + else if(result && strncmp(content_encoding,"deflate",7)==0) { | ||
255 | + ret = 2; | ||
256 | + } | ||
257 | + else { | ||
258 | + ret = 0; | ||
259 | + } | ||
260 | + if(content_encoding != NULL) { | ||
261 | + free(content_encoding); | ||
262 | + } | ||
263 | + return ret; | ||
264 | +} | ||
265 | + | ||
266 | +/*find Transfer-Encoding from the header info; | ||
267 | + * if Content-Encoding equal 'chunked' return 1,or return 0. | ||
268 | + */ | ||
269 | +int get_transfer_encoding(const char* header) { | ||
270 | + int result = 0; | ||
271 | + int ret = 0; | ||
272 | + char *transfer_encoding = (char*)malloc(sizeof(char)*10); | ||
273 | + result = find_header_info(header,transfer_encoding,"Transfer-Encoding"); | ||
274 | + | ||
275 | + if(result && strncmp(transfer_encoding,"chunked",7)==0){ | ||
276 | + ret = 1; | ||
277 | + } | ||
278 | + else { | ||
279 | + ret = 0; | ||
280 | + } | ||
281 | + | ||
282 | + if(transfer_encoding != NULL) { | ||
283 | + free(transfer_encoding); | ||
284 | + } | ||
285 | + return ret; | ||
286 | +} | ||
287 | + | ||
288 | +/* Returns NULL on invalid input */ | ||
289 | +char* decodechunked(char * chunked, unsigned int *inputlen) { | ||
290 | + char *orig = chunked, *dest = chunked; | ||
291 | + unsigned long chunklen; | ||
292 | + while((chunklen = strtoul(orig, &orig, 16))) { | ||
293 | + /* process one more chunk: */ | ||
294 | + /* skip chunk-extension part */ | ||
295 | + while(*orig && (*orig != '\r')) | ||
296 | + orig++; | ||
297 | + /* skip '\r\n' after chunk length */ | ||
298 | + orig += 2; | ||
299 | + if(( chunklen > (chunked + *inputlen - orig))) | ||
300 | + /* insane chunk length. Well... */ | ||
301 | + return NULL; | ||
302 | + memmove(dest, orig, chunklen); | ||
303 | + dest += chunklen; | ||
304 | + orig += chunklen; | ||
305 | + /* and go to the next chunk */ | ||
306 | + } | ||
307 | + *dest = '\0'; | ||
308 | + *inputlen = dest - chunked; | ||
309 | + | ||
310 | + return chunked; | ||
311 | +} | ||
312 | diff --git a/plugins/utils.h b/plugins/utils.h | ||
313 | index 3c3f189..78a74aa 100644 | ||
314 | --- a/plugins/utils.h | ||
315 | +++ b/plugins/utils.h | ||
316 | @@ -204,4 +204,12 @@ The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n\ | ||
317 | copies of the plugins under the terms of the GNU General Public License.\n\ | ||
318 | For more information about these matters, see the file named COPYING.\n") | ||
319 | |||
320 | +#define UT_DECOMPRESS _("\ | ||
321 | + -d, --decompress\n\ | ||
322 | + Decompress the contents of page which were compressed by gzip or deflate.\n") | ||
323 | + | ||
324 | +#define UT_CHUNKED _("\ | ||
325 | + -X, --chunked\n\ | ||
326 | + Deal with the data which was transferred by chunked encoding.") | ||
327 | + | ||
328 | #endif /* NP_UTILS_H */ | ||