3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * Simple example program for MatrixSSL
6 * Accepts a HTTPS request and echos the response back to the sender.
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 /******************************************************************************/
37 /******************************************************************************/
39 #include "sslSocket.h"
41 #define HTTPS_PORT 4433
42 static char keyfile
[] = "privkeySrv.pem";
43 static char certfile
[] = "certSrv.pem";
45 static const char responseHdr
[] = "HTTP/1.0 200 OK\r\n"
46 "Server: PeerSec Networks MatrixSSL\r\n"
47 "Pragma: no-cache\r\n"
48 "Cache-Control: no-cache\r\n"
49 "Content-type: text/plain\r\n"
52 "Successful MatrixSSL request:\n";
54 static const char quitString
[] = "GET /quit";
55 static const char againString
[] = "GET /again";
59 /******************************************************************************/
61 Helper framework for testing matrixSslReadKeysMem
63 #define USE_MEM_CERTS 0
66 static int32
getFileBin(char *fileName
, unsigned char **bin
, int32
*binLen
);
69 /******************************************************************************/
71 This example application acts as an https server that accepts incoming
72 client requests and reflects incoming data back to that client.
75 int _httpsReflector(char *arg1
)
77 int WINAPI
WinMain (HINSTANCE hInstance
, HINSTANCE hPrevInstance
,
78 LPWSTR lpCmdLine
, int nCmdShow
)
80 int main(int argc
, char **argv
)
87 unsigned char buf
[1024];
88 unsigned char *response
, *c
;
89 int responseHdrLen
, acceptAgain
, flags
;
90 int bytes
, status
, quit
, again
, rc
, err
;
92 unsigned char *servBin
, *servKeyBin
, *caBin
;
93 int servBinLen
, caBinLen
, servKeyBinLen
;
98 Initialize Windows sockets (no-op on other platforms)
100 WSAStartup(MAKEWORD(1,1), &wsaData
);
102 Initialize the MatrixSSL Library, and read in the public key (certificate)
105 if (matrixSslOpen() < 0) {
106 fprintf(stderr
, "matrixSslOpen failed, exiting...");
111 Example of DER binary certs for matrixSslReadKeysMem
113 getFileBin("certSrv.der", &servBin
, &servBinLen
);
114 getFileBin("privkeySrv.der", &servKeyBin
, &servKeyBinLen
);
115 getFileBin("CAcertCln.der", &caBin
, &caBinLen
);
117 matrixSslReadKeysMem(&keys
, servBin
, servBinLen
,
118 servKeyBin
, servKeyBinLen
, caBin
, caBinLen
);
127 if (matrixSslReadKeys(&keys
, certfile
, keyfile
, NULL
, NULL
) < 0) {
128 fprintf(stderr
, "Error reading or parsing %s or %s.\n",
132 #endif /* USE_MEM_CERTS */
134 "Run httpsClient or type https://127.0.0.1:%d into your local Web browser.\n",
137 Create the listen socket
139 if ((listenfd
= socketListen(HTTPS_PORT
, &err
)) == INVALID_SOCKET
) {
140 fprintf(stderr
, "Cannot listen on port %d\n", HTTPS_PORT
);
144 Set blocking or not on the listen socket
146 setSocketBlock(listenfd
);
148 Loop control initalization
162 sslAccept creates a new server session
164 /* TODO - deadlock on blocking socket accept. Should disable blocking here */
165 if ((fd
= socketAccept(listenfd
, &err
)) == INVALID_SOCKET
) {
166 fprintf(stdout
, "Error accepting connection: %d\n", err
);
169 if ((rc
= sslAccept(&cp
, fd
, keys
, NULL
, flags
)) != 0) {
179 < 0 return indicates an error.
180 0 return indicates an EOF or CLOSE_NOTIFY in this situation
181 > 0 indicates that some bytes were read. Keep reading until we see
182 the /r/n/r/n from the GET request. We don't actually parse the request,
183 we just echo it back.
187 if ((rc
= sslRead(cp
, c
, sizeof(buf
) - (int)(c
- buf
), &status
)) > 0) {
189 if (c
- buf
< 4 || memcmp(c
- 4, "\r\n\r\n", 4) != 0) {
194 fprintf(stdout
, "sslRead error. dropping connection.\n");
196 if (rc
< 0 || status
== SSLSOCKET_EOF
||
197 status
== SSLSOCKET_CLOSE_NOTIFY
) {
198 socketShutdown(cp
->fd
);
199 sslFreeConnection(&cp
);
206 Done reading. If the incoming data starts with the quitString,
207 quit the application after this request
209 if (memcmp(buf
, quitString
, min(c
- buf
,
210 (int)strlen(quitString
))) == 0) {
212 fprintf(stdout
, "Q");
215 If the incoming data starts with the againString,
216 we are getting a pipeline request on the same session. Don't
217 close and wait for new connection in this case.
219 if (memcmp(buf
, againString
,
220 min(c
- buf
, (int)strlen(againString
))) == 0) {
222 fprintf(stdout
, "A");
224 fprintf(stdout
, "R");
228 Copy the canned response header and decoded data from socket as the
231 responseHdrLen
= (int)strlen(responseHdr
);
232 bytes
= responseHdrLen
+ (int)(c
- buf
);
233 response
= malloc(bytes
);
234 memcpy(response
, responseHdr
, responseHdrLen
);
235 memcpy(response
+ responseHdrLen
, buf
, c
- buf
);
238 < 0 return indicates an error.
239 0 return indicates not all data was sent and we must retry
240 > 0 indicates that all requested bytes were sent
243 rc
= sslWrite(cp
, response
, bytes
, &status
);
246 fprintf(stdout
, "Internal sslWrite error\n");
247 socketShutdown(cp
->fd
);
248 sslFreeConnection(&cp
);
250 } else if (rc
== 0) {
255 If we saw an /again request, loop up and process another pipelined
256 HTTP request. The /again request is supported in the httpsClient
263 Send a closure alert for clean shutdown of remote SSL connection
264 This is for good form, some implementations just close the socket
266 sslWriteClosureAlert(cp
);
268 Close the socket and wait for next connection (new session)
270 socketShutdown(cp
->fd
);
271 sslFreeConnection(&cp
);
275 Close listening socket, free remaining items
278 socketShutdown(cp
->fd
);
279 sslFreeConnection(&cp
);
281 socketShutdown(listenfd
);
283 matrixSslFreeKeys(keys
);
287 fprintf(stdout
, "\n\nPress return to exit...\n");
295 static int32
getFileBin(char *fileName
, unsigned char **bin
,
305 if (fileName
== NULL
) {
308 if ((stat(fileName
, &fstat
) != 0) || (fp
= fopen(fileName
, "rb")) == NULL
) {
309 return -7; /* FILE_NOT_FOUND */
312 *bin
= malloc(fstat
.st_size
);
314 return -8; /* SSL_MEM_ERROR */
316 while (((tmp
= fread(*bin
+ *binLen
, sizeof(char), 512, fp
)) > 0) &&
317 (*binLen
< fstat
.st_size
)) {
318 *binLen
+= (int32
)tmp
;
325 /******************************************************************************/