void closeProxyConnection(struct proxyConnection *cp) { if(!(cp->error || cp->done) && !(cp->secure_eof && cp->plain_eof)) return; DLOG("Closing connection"); int secure_fd=cp->secure->fd; int status=0; if(cp->secure_up && !cp->error) { sslWriteClosureAlert(cp->secure); } status=close(cp->secure->fd); socketShutdown(cp->secure->fd); sslFreeConnection(&cp->secure); status=close(cp->plain); socketShutdown(cp->plain); memset(cp,0,sizeof(struct proxyConnection)); ILOG("Connection closed"); }
int main(int argc, char **argv) #endif { sslConn_t *cp; sslKeys_t *keys; SOCKET listenfd, fd; WSADATA wsaData; unsigned char buf[1024]; unsigned char *response, *c; int responseHdrLen, acceptAgain, flags; int bytes, status, quit, again, rc, err; #if USE_MEM_CERTS unsigned char *servBin, *servKeyBin, *caBin; int servBinLen, caBinLen, servKeyBinLen; #endif cp = NULL; /* Initialize Windows sockets (no-op on other platforms) */ WSAStartup(MAKEWORD(1,1), &wsaData); /* Initialize the MatrixSSL Library, and read in the public key (certificate) and private key. */ if (matrixSslOpen() < 0) { fprintf(stderr, "matrixSslOpen failed, exiting..."); } #if USE_MEM_CERTS /* Example of DER binary certs for matrixSslReadKeysMem */ getFileBin("certSrv.der", &servBin, &servBinLen); getFileBin("privkeySrv.der", &servKeyBin, &servKeyBinLen); getFileBin("CACertCln.der", &caBin, &caBinLen); matrixSslReadKeysMem(&keys, servBin, servBinLen, servKeyBin, servKeyBinLen, caBin, caBinLen); free(servBin); free(servKeyBin); free(caBin); #else /* Standard PEM files */ if (matrixSslReadKeys(&keys, certfile, keyfile, NULL, NULL) < 0) { fprintf(stderr, "Error reading or parsing %s or %s.\n", certfile, keyfile); goto promptAndExit; } #endif /* USE_MEM_CERTS */ fprintf(stdout, "Run httpsClient or type https://127.0.0.1:%d into your local Web browser.\n", HTTPS_PORT); /* Create the listen socket */ if ((listenfd = socketListen(HTTPS_PORT, &err)) == INVALID_SOCKET) { fprintf(stderr, "Cannot listen on port %d\n", HTTPS_PORT); goto promptAndExit; } /* Set blocking or not on the listen socket */ setSocketBlock(listenfd); /* Loop control initalization */ quit = 0; again = 0; flags = 0; acceptAgain = 1; /* Main connection loop */ while (!quit) { if (acceptAgain) { /* sslAccept creates a new server session */ /* TODO - deadlock on blocking socket accept. Should disable blocking here */ if ((fd = socketAccept(listenfd, &err)) == INVALID_SOCKET) { fprintf(stdout, "Error accepting connection: %d\n", err); continue; } if ((rc = sslAccept(&cp, fd, keys, NULL, flags)) != 0) { socketShutdown(fd); continue; } flags = 0; acceptAgain = 0; } /* Read response < 0 return indicates an error. 0 return indicates an EOF or CLOSE_NOTIFY in this situation > 0 indicates that some bytes were read. Keep reading until we see the /r/n/r/n from the GET request. We don't actually parse the request, we just echo it back. */ c = buf; readMore: if ((rc = sslRead(cp, c, sizeof(buf) - (int)(c - buf), &status)) > 0) { c += rc; if (c - buf < 4 || memcmp(c - 4, "\r\n\r\n", 4) != 0) { goto readMore; } } else { if (rc < 0) { fprintf(stdout, "sslRead error. dropping connection.\n"); } if (rc < 0 || status == SSLSOCKET_EOF || status == SSLSOCKET_CLOSE_NOTIFY) { socketShutdown(cp->fd); sslFreeConnection(&cp); acceptAgain = 1; continue; } goto readMore; } /* Done reading. If the incoming data starts with the quitString, quit the application after this request */ if (memcmp(buf, quitString, min(c - buf, (int)strlen(quitString))) == 0) { quit++; fprintf(stdout, "Q"); } /* If the incoming data starts with the againString, we are getting a pipeline request on the same session. Don't close and wait for new connection in this case. */ if (memcmp(buf, againString, min(c - buf, (int)strlen(againString))) == 0) { again++; fprintf(stdout, "A"); } else { fprintf(stdout, "R"); again = 0; } /* Copy the canned response header and decoded data from socket as the response (reflector) */ responseHdrLen = (int)strlen(responseHdr); bytes = responseHdrLen + (int)(c - buf); response = malloc(bytes); memcpy(response, responseHdr, responseHdrLen); memcpy(response + responseHdrLen, buf, c - buf); /* Send response. < 0 return indicates an error. 0 return indicates not all data was sent and we must retry > 0 indicates that all requested bytes were sent */ writeMore: rc = sslWrite(cp, response, bytes, &status); if (rc < 0) { free(response); fprintf(stdout, "Internal sslWrite error\n"); socketShutdown(cp->fd); sslFreeConnection(&cp); continue; } else if (rc == 0) { goto writeMore; } free(response); /* If we saw an /again request, loop up and process another pipelined HTTP request. The /again request is supported in the httpsClient example code. */ if (again) { continue; } /* Send a closure alert for clean shutdown of remote SSL connection This is for good form, some implementations just close the socket */ sslWriteClosureAlert(cp); /* Close the socket and wait for next connection (new session) */ socketShutdown(cp->fd); sslFreeConnection(&cp); acceptAgain = 1; } /* Close listening socket, free remaining items */ if (cp && cp->ssl) { socketShutdown(cp->fd); sslFreeConnection(&cp); } socketShutdown(listenfd); matrixSslFreeKeys(keys); matrixSslClose(); WSACleanup(); promptAndExit: fprintf(stdout, "\n\nPress return to exit...\n"); getchar(); return 0; }
int main(int argc, char **argv) #endif { sslSessionId_t *sessionId; sslConn_t *conn; sslKeys_t *keys; WSADATA wsaData; SOCKET fd; short cipherSuite; unsigned char *ip, *c, *requestBuf; unsigned char buf[1024]; int iterations, requests, connectAgain, status; int quit, rc, bytes, i, j, err; time_t t0, t1; #if REUSE int anonStatus; #endif #if VXWORKS int argc; char **argv; parseCmdLineArgs(arg1, &argc, &argv); #endif /* VXWORKS */ #if WINCE int argc; char **argv; char args[256]; /* * parseCmdLineArgs expects an ASCII string and CE is unicoded, so convert * the command line. args will get hacked up, so you can't pass in a * static string. */ WideCharToMultiByte(CP_ACP, 0, lpCmdLine, -1, args, 256, NULL, NULL); /* * Parse the command line into an argv array. This allocs memory, so * we have to free argv when we're done. */ parseCmdLineArgs(args, &argc, &argv); #endif /* WINCE */ conn = NULL; /* First (optional) argument is ip address to connect to (port is hardcoded) Second (optional) argument is number of iterations to perform Third (optional) argument is number of keepalive HTTP requests Fourth (optional) argument is cipher suite number to use (0 for any) */ ip = HTTPS_IP; iterations = ITERATIONS; requests = REQUESTS; cipherSuite = 0x0000; if (argc > 1) { ip = argv[1]; if (argc > 2) { iterations = atoi(argv[2]); socketAssert(iterations > 0); if (argc > 3) { requests = atoi(argv[3]); socketAssert(requests > 0); if (argc > 4) { cipherSuite = (short)atoi(argv[4]); } } } } /* Initialize Windows sockets (no-op on other platforms) */ WSAStartup(MAKEWORD(1,1), &wsaData); /* Initialize the MatrixSSL Library, and read in the certificate file used to validate the server. */ if (matrixSslOpen() < 0) { fprintf(stderr, "matrixSslOpen failed, exiting..."); } sessionId = NULL; if (matrixSslReadKeys(&keys, NULL, NULL, NULL, CAfile) < 0) { goto promptAndExit; } /* Intialize loop control variables */ quit = 0; connectAgain = 1; i = 1; /* Just reuse the requestBuf and malloc to largest possible message size */ requestBuf = malloc(sizeof(requestAgain)); t0 = time(0); /* Main ITERATIONS loop */ while (!quit && (i < iterations)) { /* sslConnect uses port and ip address to connect to SSL server. Generates a new session */ if (connectAgain) { if ((fd = socketConnect(ip, HTTPS_PORT, &err)) == INVALID_SOCKET) { fprintf(stdout, "Error connecting to server %s:%d\n", ip, HTTPS_PORT); matrixSslFreeKeys(keys); goto promptAndExit; } if (sslConnect(&conn, fd, keys, sessionId, cipherSuite, certChecker) < 0) { quit = 1; socketShutdown(fd); fprintf(stderr, "Error connecting to %s:%d\n", ip, HTTPS_PORT); continue; } i++; connectAgain = 0; j = 1; } if (conn == NULL) { quit++; continue; } /* Copy the HTTP request header into the buffer, based of whether or not we want httpReflector to keep the socket open or not */ if (j == requests) { bytes = (int)strlen(request); memcpy(requestBuf, request, bytes); } else { bytes = (int)strlen(requestAgain); memcpy(requestBuf, requestAgain, bytes); } /* Send request. < 0 return indicates an error. 0 return indicates not all data was sent and we must retry > 0 indicates that all requested bytes were sent */ writeMore: rc = sslWrite(conn, requestBuf, bytes, &status); if (rc < 0) { fprintf(stdout, "Internal sslWrite error\n"); socketShutdown(conn->fd); sslFreeConnection(&conn); continue; } else if (rc == 0) { goto writeMore; } /* Read response < 0 return indicates an error. 0 return indicates an EOF or CLOSE_NOTIFY in this situation > 0 indicates that some bytes were read. Keep reading until we see the /r/n/r/n from the response header. There may be data following this header, but we don't try too hard to read it for this example. */ c = buf; readMore: if ((rc = sslRead(conn, c, sizeof(buf) - (int)(c - buf), &status)) > 0) { c += rc; if (c - buf < 4 || memcmp(c - 4, "\r\n\r\n", 4) != 0) { goto readMore; } } else { if (rc < 0) { fprintf(stdout, "sslRead error. dropping connection.\n"); } if (rc < 0 || status == SSLSOCKET_EOF || status == SSLSOCKET_CLOSE_NOTIFY) { socketShutdown(conn->fd); sslFreeConnection(&conn); continue; } goto readMore; } /* Determine if we want to do a pipelined HTTP request/response */ if (j++ < requests) { fprintf(stdout, "R"); continue; } else { fprintf(stdout, "C"); } /* Reuse the session. Comment out these two lines to test the entire public key renegotiation each iteration */ #if REUSE matrixSslFreeSessionId(sessionId); matrixSslGetSessionId(conn->ssl, &sessionId); /* This example shows how a user might want to limit a client to resuming handshakes only with authenticated servers. In this example, the client will force any non-authenticated (anonymous) server to go through a complete handshake each time. This is strictly an example of one policy decision an implementation might wish to make. */ matrixSslGetAnonStatus(conn->ssl, &anonStatus); if (anonStatus) { matrixSslFreeSessionId(sessionId); sessionId = NULL; } #endif /* Send a closure alert for clean shutdown of remote SSL connection This is for good form, some implementations just close the socket */ sslWriteClosureAlert(conn); /* Session done. Connect again if more iterations remaining */ socketShutdown(conn->fd); sslFreeConnection(&conn); connectAgain = 1; } t1 = time(0); free(requestBuf); matrixSslFreeSessionId(sessionId); if (conn && conn->ssl) { socketShutdown(conn->fd); sslFreeConnection(&conn); } fprintf(stdout, "\n%d connections in %d seconds (%f c/s)\n", i, (int)(t1 - t0), (double)i / (t1 - t0)); fprintf(stdout, "\n%d requests in %d seconds (%f r/s)\n", i * requests, (int)(t1 - t0), (double)(i * requests) / (t1 - t0)); /* Close listening socket, free remaining items */ matrixSslFreeKeys(keys); matrixSslClose(); WSACleanup(); promptAndExit: fprintf(stdout, "Press return to exit...\n"); getchar(); #if WINCE || VXWORKS if (argv) { free((void*) argv); } #endif /* WINCE */ return 0; }