Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / matrixssl / examples / httpsClient.c
blob5b3c19700016141b54bc42376154724595a89824
1 /*
2 * httpClient.c
3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * Simple example program for MatrixSSL
6 * Sends a HTTPS request and echos the response back to the sender.
7 */
8 /*
9 * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
10 * The latest version of this code is available at http://www.matrixssl.org
12 * This software is open source; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This General Public License does NOT permit incorporating this software
18 * into proprietary programs. If you are unable to comply with the GPL, a
19 * commercial license for this software may be purchased from PeerSec Networks
20 * at http://www.peersec.com
22 * This program is distributed in WITHOUT ANY WARRANTY; without even the
23 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 * See the GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * http://www.gnu.org/copyleft/gpl.html
31 /******************************************************************************/
33 #include <stdlib.h>
34 #include <stdio.h>
35 #ifndef WINCE
36 #include <time.h>
37 #endif
39 /******************************************************************************/
41 #include "sslSocket.h"
43 /******************************************************************************/
45 #define HTTPS_PORT 4433
46 #define HTTPS_IP "127.0.0.1"
48 static char CAfile[] = "CAcertSrv.pem";
51 #define ITERATIONS 100 /* How many individual connections to make */
52 #define REQUESTS 10 /* How many requests per each connection */
53 #define REUSE 0 /* 0 if session resumption disabled */
55 #define ENFORCE_CERT_VALIDATION 1 /* 0 to allow connection without validation */
58 static const char request[] = "GET / HTTP/1.0\r\n"
59 "User-Agent: MatrixSSL httpClient\r\n"
60 "Accept: */*\r\n"
61 "\r\n";
63 static const char requestAgain[] = "GET /again HTTP/1.0\r\n"
64 "User-Agent: MatrixSSL httpClient\r\n"
65 "Accept: */*\r\n"
66 "\r\n";
68 static const char quitString[] = "GET /quit";
71 Callback that is registered to receive server certificate
72 information for custom validation
74 static int certChecker(sslCertInfo_t *cert, void *arg);
76 /******************************************************************************/
78 Example ssl client that connects to a server and sends https messages
80 #if VXWORKS
81 int _httpsClient(char *arg1)
82 #elif WINCE
83 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
84 LPWSTR lpCmdLine, int nCmdShow)
85 #else
86 int main(int argc, char **argv)
87 #endif
89 sslSessionId_t *sessionId;
90 sslConn_t *conn;
91 sslKeys_t *keys;
92 WSADATA wsaData;
93 SOCKET fd;
94 short cipherSuite;
95 unsigned char *ip, *c, *requestBuf;
96 unsigned char buf[1024];
97 int iterations, requests, connectAgain, status;
98 int quit, rc, bytes, i, j, err;
99 time_t t0, t1;
100 #if REUSE
101 int anonStatus;
102 #endif
103 #if VXWORKS
104 int argc;
105 char **argv;
106 parseCmdLineArgs(arg1, &argc, &argv);
107 #endif /* VXWORKS */
109 #if WINCE
110 int argc;
111 char **argv;
112 char args[256];
115 * parseCmdLineArgs expects an ASCII string and CE is unicoded, so convert
116 * the command line. args will get hacked up, so you can't pass in a
117 * static string.
119 WideCharToMultiByte(CP_ACP, 0, lpCmdLine, -1, args, 256, NULL, NULL);
122 * Parse the command line into an argv array. This allocs memory, so
123 * we have to free argv when we're done.
125 parseCmdLineArgs(args, &argc, &argv);
126 #endif /* WINCE */
128 conn = NULL;
130 First (optional) argument is ip address to connect to (port is hardcoded)
131 Second (optional) argument is number of iterations to perform
132 Third (optional) argument is number of keepalive HTTP requests
133 Fourth (optional) argument is cipher suite number to use (0 for any)
135 ip = HTTPS_IP;
136 iterations = ITERATIONS;
137 requests = REQUESTS;
138 cipherSuite = 0x0000;
139 if (argc > 1) {
140 ip = argv[1];
141 if (argc > 2) {
142 iterations = atoi(argv[2]);
143 socketAssert(iterations > 0);
144 if (argc > 3) {
145 requests = atoi(argv[3]);
146 socketAssert(requests > 0);
147 if (argc > 4) {
148 cipherSuite = (short)atoi(argv[4]);
154 Initialize Windows sockets (no-op on other platforms)
156 WSAStartup(MAKEWORD(1,1), &wsaData);
158 Initialize the MatrixSSL Library, and read in the certificate file
159 used to validate the server.
161 if (matrixSslOpen() < 0) {
162 fprintf(stderr, "matrixSslOpen failed, exiting...");
164 sessionId = NULL;
165 if (matrixSslReadKeys(&keys, NULL, NULL, NULL, CAfile) < 0) {
166 goto promptAndExit;
169 Intialize loop control variables
171 quit = 0;
172 connectAgain = 1;
173 i = 1;
175 Just reuse the requestBuf and malloc to largest possible message size
177 requestBuf = malloc(sizeof(requestAgain));
178 t0 = time(0);
180 Main ITERATIONS loop
182 while (!quit && (i < iterations)) {
184 sslConnect uses port and ip address to connect to SSL server.
185 Generates a new session
187 if (connectAgain) {
188 if ((fd = socketConnect(ip, HTTPS_PORT, &err)) == INVALID_SOCKET) {
189 fprintf(stdout, "Error connecting to server %s:%d\n", ip, HTTPS_PORT);
190 matrixSslFreeKeys(keys);
191 goto promptAndExit;
193 if (sslConnect(&conn, fd, keys, sessionId, cipherSuite, certChecker) < 0) {
194 quit = 1;
195 socketShutdown(fd);
196 fprintf(stderr, "Error connecting to %s:%d\n", ip, HTTPS_PORT);
197 continue;
199 i++;
200 connectAgain = 0;
201 j = 1;
203 if (conn == NULL) {
204 quit++;
205 continue;
208 Copy the HTTP request header into the buffer, based of whether or
209 not we want httpReflector to keep the socket open or not
211 if (j == requests) {
212 bytes = (int)strlen(request);
213 memcpy(requestBuf, request, bytes);
214 } else {
215 bytes = (int)strlen(requestAgain);
216 memcpy(requestBuf, requestAgain, bytes);
219 Send request.
220 < 0 return indicates an error.
221 0 return indicates not all data was sent and we must retry
222 > 0 indicates that all requested bytes were sent
224 writeMore:
225 rc = sslWrite(conn, requestBuf, bytes, &status);
226 if (rc < 0) {
227 fprintf(stdout, "Internal sslWrite error\n");
228 socketShutdown(conn->fd);
229 sslFreeConnection(&conn);
230 continue;
231 } else if (rc == 0) {
232 goto writeMore;
235 Read response
236 < 0 return indicates an error.
237 0 return indicates an EOF or CLOSE_NOTIFY in this situation
238 > 0 indicates that some bytes were read. Keep reading until we see
239 the /r/n/r/n from the response header. There may be data following
240 this header, but we don't try too hard to read it for this example.
242 c = buf;
243 readMore:
244 if ((rc = sslRead(conn, c, sizeof(buf) - (int)(c - buf), &status)) > 0) {
245 c += rc;
246 if (c - buf < 4 || memcmp(c - 4, "\r\n\r\n", 4) != 0) {
247 goto readMore;
249 } else {
250 if (rc < 0) {
251 fprintf(stdout, "sslRead error. dropping connection.\n");
253 if (rc < 0 || status == SSLSOCKET_EOF ||
254 status == SSLSOCKET_CLOSE_NOTIFY) {
255 socketShutdown(conn->fd);
256 sslFreeConnection(&conn);
257 continue;
259 goto readMore;
262 Determine if we want to do a pipelined HTTP request/response
264 if (j++ < requests) {
265 fprintf(stdout, "R");
266 fflush(stdout);
267 continue;
268 } else {
269 fprintf(stdout, "C");
270 fflush(stdout);
273 Reuse the session. Comment out these two lines to test the entire
274 public key renegotiation each iteration
276 #if REUSE
277 matrixSslFreeSessionId(sessionId);
278 matrixSslGetSessionId(conn->ssl, &sessionId);
280 This example shows how a user might want to limit a client to
281 resuming handshakes only with authenticated servers. In this
282 example, the client will force any non-authenticated (anonymous)
283 server to go through a complete handshake each time. This is
284 strictly an example of one policy decision an implementation
285 might wish to make.
287 matrixSslGetAnonStatus(conn->ssl, &anonStatus);
288 if (anonStatus) {
289 matrixSslFreeSessionId(sessionId);
290 sessionId = NULL;
292 #endif
294 Send a closure alert for clean shutdown of remote SSL connection
295 This is for good form, some implementations just close the socket
297 sslWriteClosureAlert(conn);
299 Session done. Connect again if more iterations remaining
301 socketShutdown(conn->fd);
302 sslFreeConnection(&conn);
303 connectAgain = 1;
306 t1 = time(0);
307 free(requestBuf);
308 matrixSslFreeSessionId(sessionId);
309 if (conn && conn->ssl) {
310 socketShutdown(conn->fd);
311 sslFreeConnection(&conn);
313 fprintf(stdout, "\n%d connections in %d seconds (%f c/s)\n",
314 i, (int)(t1 - t0), (double)i / (t1 - t0));
315 fprintf(stdout, "\n%d requests in %d seconds (%f r/s)\n",
316 i * requests, (int)(t1 - t0),
317 (double)(i * requests) / (t1 - t0));
319 Close listening socket, free remaining items
321 matrixSslFreeKeys(keys);
322 matrixSslClose();
323 WSACleanup();
324 promptAndExit:
325 fprintf(stdout, "Press return to exit...\n");
326 getchar();
328 #if WINCE || VXWORKS
329 if (argv) {
330 free((void*) argv);
332 #endif /* WINCE */
333 return 0;
336 /******************************************************************************/
338 Stub for a user-level certificate validator. Just using
339 the default validation value here.
341 static int certChecker(sslCertInfo_t *cert, void *arg)
343 sslCertInfo_t *next;
344 sslKeys_t *keys;
346 Make sure we are checking the last cert in the chain
348 next = cert;
349 keys = arg;
350 while (next->next != NULL) {
351 next = next->next;
353 #if ENFORCE_CERT_VALIDATION
355 This case passes the true RSA authentication status through
357 return next->verified;
358 #else
360 This case passes an authenticated server through, but flags a
361 non-authenticated server correctly. The user can call the
362 matrixSslGetAnonStatus later to see the status of this connection.
364 if (next->verified != 1) {
365 return SSL_ALLOW_ANON_CONNECTION;
367 return next->verified;
368 #endif /* ENFORCE_CERT_VALIDATION */
371 /******************************************************************************/