diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 13:58:15 +0100 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 13:58:15 +0100 |
commit | 4aca87515a5083ae0e31ce3177189fd43b6d05ac (patch) | |
tree | 7b1d9a31393ca090757dc6f0d3859b4fcd93f271 /release/src/router/matrixssl/examples/httpsReflector.c | |
parent | 008d0be72b2f160382c6e880765e96b64a050c65 (diff) | |
download | tomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.gz tomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.bz2 |
patch to Vanilla Tomato 1.28
Diffstat (limited to 'release/src/router/matrixssl/examples/httpsReflector.c')
-rw-r--r-- | release/src/router/matrixssl/examples/httpsReflector.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/release/src/router/matrixssl/examples/httpsReflector.c b/release/src/router/matrixssl/examples/httpsReflector.c new file mode 100644 index 00000000..4a901dfc --- /dev/null +++ b/release/src/router/matrixssl/examples/httpsReflector.c @@ -0,0 +1,331 @@ +/* + * httpReflector.c + * Release $Name: MATRIXSSL_1_8_8_OPEN $ + * + * Simple example program for MatrixSSL + * Accepts a HTTPS request and echos the response back to the sender. + */ +/* + * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved. + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from PeerSec Networks + * at http://www.peersec.com + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/******************************************************************************/ + +#include "sslSocket.h" + +#define HTTPS_PORT 4433 +static char keyfile[] = "privkeySrv.pem"; +static char certfile[] = "certSrv.pem"; + +static const char responseHdr[] = "HTTP/1.0 200 OK\r\n" + "Server: PeerSec Networks MatrixSSL\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "Content-type: text/plain\r\n" + "\r\n" + "PeerSec Networks\n" + "Successful MatrixSSL request:\n"; + +static const char quitString[] = "GET /quit"; +static const char againString[] = "GET /again"; + + + +/******************************************************************************/ +/* + Helper framework for testing matrixSslReadKeysMem +*/ +#define USE_MEM_CERTS 0 +#if USE_MEM_CERTS +#include <sys/stat.h> +static int32 getFileBin(char *fileName, unsigned char **bin, int32 *binLen); +#endif + +/******************************************************************************/ +/* + This example application acts as an https server that accepts incoming + client requests and reflects incoming data back to that client. +*/ +#if VXWORKS +int _httpsReflector(char *arg1) +#elif WINCE +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, int nCmdShow) +#else +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; +} + + + +#if USE_MEM_CERTS +static int32 getFileBin(char *fileName, unsigned char **bin, + int32 *binLen) +{ + FILE *fp; + struct stat fstat; + size_t tmp = 0; + + *binLen = 0; + *bin = NULL; + + if (fileName == NULL) { + return -1; + } + if ((stat(fileName, &fstat) != 0) || (fp = fopen(fileName, "rb")) == NULL) { + return -7; /* FILE_NOT_FOUND */ + } + + *bin = malloc(fstat.st_size); + if (*bin == NULL) { + return -8; /* SSL_MEM_ERROR */ + } + while (((tmp = fread(*bin + *binLen, sizeof(char), 512, fp)) > 0) && + (*binLen < fstat.st_size)) { + *binLen += (int32)tmp; + } + fclose(fp); + return 0; +} +#endif + +/******************************************************************************/ + + + + + + |