Browse code

Fix crash on Windows when --enable-stats is set

Shawn Webb authored on 2014/05/07 03:30:43
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,288 +0,0 @@
1
-/*
2
- *  Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
3
- *
4
- *  Author: Shawn Webb
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#include <stdio.h>
22
-#include <stdlib.h>
23
-#include <string.h>
24
-
25
-#if HAVE_UNISTD_H
26
-#include <unistd.h>
27
-#endif
28
-
29
-#include <ctype.h>
30
-
31
-#include <sys/types.h>
32
-#include <fcntl.h>
33
-
34
-#include <errno.h>
35
-
36
-#if !defined(_WIN32)
37
-#include <sys/socket.h>
38
-#include <sys/select.h>
39
-#include <netinet/in.h>
40
-#include <netdb.h>
41
-#endif
42
-
43
-#include <openssl/ssl.h>
44
-#include <openssl/err.h>
45
-#include "libclamav/crypto.h"
46
-
47
-#include "libclamav/others.h"
48
-#include "libclamav/clamav.h"
49
-#include "libclamav/www.h"
50
-
51
-int connect_host(const char *host, const char *port, uint32_t timeout, int useAsync)
52
-{
53
-    int sockfd;
54
-    struct addrinfo hints, *servinfo, *p;
55
-    int flags, error;
56
-    socklen_t len;
57
-    fd_set read_fds, write_fds;
58
-    struct timeval tv;
59
-
60
-    memset(&hints, 0x00, sizeof(struct addrinfo));
61
-    hints.ai_family = AF_UNSPEC;
62
-    hints.ai_socktype = SOCK_STREAM;
63
-
64
-    if (getaddrinfo(host, port, &hints, &servinfo))
65
-        return -1;
66
-
67
-    for (p = servinfo; p != NULL; p = p->ai_next) {
68
-        sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
69
-        if (sockfd < 0)
70
-            continue;
71
-
72
-        if (useAsync) {
73
-            flags = fcntl(sockfd, F_GETFL, 0);
74
-            if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
75
-                close(sockfd);
76
-                continue;
77
-            }
78
-        }
79
-
80
-        if ((error = connect(sockfd, p->ai_addr, p->ai_addrlen))) {
81
-            if (useAsync) {
82
-                if (errno != EINPROGRESS) {
83
-                    close(sockfd);
84
-                    continue;
85
-                }
86
-                errno = 0;
87
-
88
-                FD_ZERO(&write_fds);
89
-                FD_ZERO(&read_fds);
90
-                FD_SET(sockfd, &read_fds);
91
-                FD_SET(sockfd, &write_fds);
92
-
93
-                /* TODO: Make this timeout configurable */
94
-                tv.tv_sec = timeout;
95
-                tv.tv_usec = 0;
96
-                if (select(sockfd + 1, &read_fds, &write_fds, NULL, &tv) <= 0) {
97
-                    close(sockfd);
98
-                    continue;
99
-                }
100
-
101
-                if (FD_ISSET(sockfd, &read_fds) || FD_ISSET(sockfd, &write_fds)) {
102
-                    len = sizeof(error);
103
-                    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
104
-                        close(sockfd);
105
-                        continue;
106
-                    }
107
-                } else {
108
-                    close(sockfd);
109
-                    continue;
110
-                }
111
-            } else {
112
-                close(sockfd);
113
-                continue;
114
-            }
115
-        }
116
-
117
-
118
-        /* Connected to host */
119
-        break;
120
-    }
121
-
122
-    if (!(p)) {
123
-        freeaddrinfo(servinfo);
124
-        if (sockfd >= 0)
125
-            close(sockfd);
126
-        return -1;
127
-    }
128
-
129
-    freeaddrinfo(servinfo);
130
-
131
-    /* Return to using a synchronous socket to make Linux happy */
132
-    if (useAsync) {
133
-        if (fcntl(sockfd, F_SETFL, flags) < 0) {
134
-            close(sockfd);
135
-            return -1;
136
-        }
137
-    }
138
-
139
-    return sockfd;
140
-}
141
-
142
-size_t encoded_size(const char *postdata)
143
-{
144
-    const char *p;
145
-    size_t len=0;
146
-
147
-    for (p = postdata; *p != '\0'; p++)
148
-        len += isalnum(*p) ? 1 : 3;
149
-
150
-    return len;
151
-}
152
-
153
-char *encode_data(const char *postdata)
154
-{
155
-    char *buf;
156
-    size_t bufsz, i, j;
157
-
158
-    bufsz = encoded_size(postdata);
159
-    if (bufsz == 0)
160
-        return NULL;
161
-
162
-    buf = cli_calloc(1, bufsz+1);
163
-    if (!(buf))
164
-        return NULL;
165
-
166
-    for (i=0, j=0; postdata[i] != '\0'; i++) {
167
-        if (isalnum(postdata[i])) {
168
-            buf[j++] = postdata[i];
169
-        } else {
170
-            sprintf(buf+j, "%%%02x", postdata[i]);
171
-            j += 3;
172
-        }
173
-    }
174
-
175
-    return buf;
176
-}
177
-
178
-void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata, uint32_t timeout)
179
-{
180
-    int sockfd, n;
181
-    unsigned int i;
182
-    char *buf, *encoded=NULL;
183
-    size_t bufsz;
184
-    ssize_t recvsz;
185
-    char chunkedlen[21];
186
-    fd_set readfds;
187
-    struct timeval tv;
188
-    char *acceptable_methods[] = {
189
-        "GET",
190
-        "PUT",
191
-        "POST",
192
-        NULL
193
-    };
194
-
195
-    for (i=0; acceptable_methods[i] != NULL; i++)
196
-        if (!strcmp(method, acceptable_methods[i]))
197
-            break;
198
-
199
-    if (acceptable_methods[i] == NULL)
200
-        return;
201
-
202
-    bufsz = strlen(method);
203
-    bufsz += sizeof("   HTTP/1.1") + 2; /* Yes. Three blank spaces. +1 for the \n */
204
-    bufsz += strlen(url);
205
-    bufsz += sizeof("Host: \r\n");
206
-    bufsz += strlen(host);
207
-    bufsz += sizeof("Connection: Close\r\n");
208
-    bufsz += 4; /* +4 for \r\n\r\n */
209
-
210
-    if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
211
-        encoded = encode_data(postdata);
212
-        if (!(encoded))
213
-            return;
214
-
215
-        snprintf(chunkedlen, sizeof(chunkedlen), "%zu", strlen(encoded));
216
-        bufsz += sizeof("Content-Type: application/x-www-form-urlencoded\r\n");
217
-        bufsz += sizeof("Content-Length: \r\n");
218
-        bufsz += strlen(chunkedlen);
219
-        bufsz += strlen(encoded);
220
-    }
221
-
222
-    buf = cli_calloc(1, bufsz);
223
-    if (!(buf)) {
224
-        if ((encoded))
225
-            free(encoded);
226
-
227
-        return;
228
-    }
229
-
230
-    snprintf(buf, bufsz, "%s %s HTTP/1.1\r\n", method, url);
231
-    snprintf(buf+strlen(buf), bufsz-strlen(buf), "Host: %s\r\n", host);
232
-    snprintf(buf+strlen(buf), bufsz-strlen(buf), "Connection: Close\r\n");
233
-
234
-    if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
235
-        snprintf(buf+strlen(buf), bufsz-strlen(buf), "Content-Type: application/x-www-form-urlencoded\r\n");
236
-        snprintf(buf+strlen(buf), bufsz-strlen(buf), "Content-Length: %s\r\n", chunkedlen);
237
-        snprintf(buf+strlen(buf), bufsz-strlen(buf), "\r\n");
238
-        snprintf(buf+strlen(buf), bufsz-strlen(buf), "%s", encoded);
239
-        free(encoded);
240
-    }
241
-
242
-    sockfd = connect_host(host, port, timeout, 1);
243
-    if (sockfd < 0) {
244
-        free(buf);
245
-        return;
246
-    }
247
-
248
-    cli_dbgmsg("stats - Connected to %s:%s\n", host, port);
249
-
250
-    if (send(sockfd, buf, strlen(buf), 0) != strlen(buf)) {
251
-        close(sockfd);
252
-        free(buf);
253
-        return;
254
-    }
255
-
256
-    cli_dbgmsg("stats - Sending %s\n", buf);
257
-
258
-    while (1) {
259
-        FD_ZERO(&readfds);
260
-        FD_SET(sockfd, &readfds);
261
-
262
-        /*
263
-         * Check to make sure the stats submitted okay (so that we don't kill the HTTP request
264
-         * while it's being processed). Give a ten-second timeout so we don't have a major
265
-         * impact on scanning.
266
-         */
267
-        tv.tv_sec = timeout;
268
-        tv.tv_usec = 0;
269
-        if ((n = select(sockfd+1, &readfds, NULL, NULL, &tv)) <= 0)
270
-            break;
271
-
272
-        if (FD_ISSET(sockfd, &readfds)) {
273
-            memset(buf, 0x00, bufsz);
274
-            if ((recvsz = recv(sockfd, buf, bufsz-1, 0) <= 0))
275
-                break;
276
-
277
-            buf[bufsz-1] = '\0';
278
-
279
-            if (strstr(buf, "STATOK")) {
280
-                cli_dbgmsg("stats - Data received okay\n");
281
-                break;
282
-            }
283
-        }
284
-    }
285
-
286
-    close(sockfd);
287
-    free(buf);
288
-}