2 * SSL server demonstration program
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #ifndef _CRT_SECURE_NO_DEPRECATE
37 #define _CRT_SECURE_NO_DEPRECATE 1
48 #include "tropicssl/havege.h"
49 #include "tropicssl/certs.h"
50 #include "tropicssl/x509.h"
51 #include "tropicssl/ssl.h"
52 #include "tropicssl/net.h"
54 #define HTTP_RESPONSE \
55 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
56 "<h2><p><center>Successful connection using: %s\r\n"
59 * Computing a "safe" DH-1024 prime can take a very
60 * long time, so a precomputed value is provided below.
61 * You may run dh_genprime to generate a new value.
63 static const char *my_dhm_P
=
64 "E4004C1F94182000103D883A448B3F80"
65 "2CE4B44A83301270002C20D0321CFD00"
66 "11CCEF784C26A400F43DFB901BCA7538"
67 "F2C6B176001CF5A0FD16D2C48B1D0C1C"
68 "F6AC8E1DA6BCC3B4E1F96B0564965300"
69 "FFA1D0B601EB2800F489AA512C4B248C"
70 "01F76949A60BB7F00A40B1EAB64BDD48" "E8A700D60B7F1200FA8E77B0A979DABF";
72 static const char *my_dhm_G
= "4";
75 * Sorted by order of preference
77 static const int my_ciphers
[] = {
78 SSL_EDH_RSA_AES_256_SHA
,
79 SSL_EDH_RSA_CAMELLIA_256_SHA
,
80 SSL_EDH_RSA_DES_168_SHA
,
82 SSL_RSA_CAMELLIA_256_SHA
,
84 SSL_RSA_CAMELLIA_128_SHA
,
93 static void my_debug(void *ctx
, int level
, const char *str
)
95 if (level
< DEBUG_LEVEL
) {
96 fprintf((FILE *) ctx
, "%s", str
);
102 * These session callbacks use a simple chained list
103 * to store and retrieve the session information.
105 ssl_session
*s_list_1st
= NULL
;
106 ssl_session
*cur
, *prv
;
108 static int my_get_session(ssl_context
* ssl
)
110 time_t t
= time(NULL
);
112 if (ssl
->resume
== 0)
118 while (cur
!= NULL
) {
122 if (ssl
->timeout
!= 0 && t
- prv
->start
> ssl
->timeout
)
125 if (ssl
->session
->cipher
!= prv
->cipher
||
126 ssl
->session
->length
!= prv
->length
)
129 if (memcmp(ssl
->session
->id
, prv
->id
, prv
->length
) != 0)
132 memcpy(ssl
->session
->master
, prv
->master
, 48);
139 static int my_set_session(ssl_context
* ssl
)
141 time_t t
= time(NULL
);
146 while (cur
!= NULL
) {
147 if (ssl
->timeout
!= 0 && t
- cur
->start
> ssl
->timeout
)
148 break; /* expired, reuse this slot */
150 if (memcmp(ssl
->session
->id
, cur
->id
, cur
->length
) == 0)
151 break; /* client reconnected */
158 cur
= (ssl_session
*) malloc(sizeof(ssl_session
));
168 memcpy(cur
, ssl
->session
, sizeof(ssl_session
));
178 unsigned char buf
[1024];
187 * 1. Load the certificates and private RSA key
189 printf("\n . Loading the server cert. and key...");
192 memset(&ssl
, 0, sizeof(ssl_context
));
193 memset(&ssn
, 0, sizeof(ssl_session
));
194 memset(&srvcert
, 0, sizeof(x509_cert
));
195 memset(&rsa
, 0, sizeof(rsa_context
));
198 * This demonstration program uses embedded test certificates.
199 * Instead, you may want to use x509parse_crtfile() to read the
200 * server and CA certificates, as well as x509parse_keyfile().
202 ret
= x509parse_crt(&srvcert
, (const unsigned char *)test_srv_crt
,
203 strlen(test_srv_crt
));
205 printf(" failed\n ! x509parse_crt returned %d\n\n", ret
);
209 ret
= x509parse_crt(&srvcert
, (const unsigned char *)test_ca_crt
,
210 strlen(test_ca_crt
));
212 printf(" failed\n ! x509parse_crt returned %d\n\n", ret
);
216 ret
= x509parse_key(&rsa
, (const unsigned char *)test_srv_key
,
217 strlen(test_srv_key
), NULL
, 0);
219 printf(" failed\n ! x509parse_key returned %d\n\n", ret
);
226 * 2. Setup the listening TCP socket
228 printf(" . Bind on https://localhost:4433/ ...");
231 if ((ret
= net_bind(&listen_fd
, NULL
, 4433)) != 0) {
232 printf(" failed\n ! net_bind returned %d\n\n", ret
);
239 * 3. Wait until a client connects
242 ShellExecute(NULL
, "open", "https://localhost:4433/",
243 NULL
, NULL
, SW_SHOWNORMAL
);
247 memset(&ssl
, 0, sizeof(ssl
));
251 net_close(client_fd
);
254 printf(" . Waiting for a remote connection ...");
257 if ((ret
= net_accept(listen_fd
, &client_fd
, NULL
)) != 0) {
258 printf(" failed\n ! net_accept returned %d\n\n", ret
);
267 printf(" . Setting up the RNG and SSL data....");
272 if ((ret
= ssl_init(&ssl
)) != 0) {
273 printf(" failed\n ! ssl_init returned %d\n\n", ret
);
279 ssl_set_endpoint(&ssl
, SSL_IS_SERVER
);
280 ssl_set_authmode(&ssl
, SSL_VERIFY_NONE
);
282 ssl_set_rng(&ssl
, havege_rand
, &hs
);
283 ssl_set_dbg(&ssl
, my_debug
, stdout
);
284 ssl_set_bio(&ssl
, net_recv
, &client_fd
, net_send
, &client_fd
);
285 ssl_set_scb(&ssl
, my_get_session
, my_set_session
);
287 ssl_set_ciphers(&ssl
, my_ciphers
);
288 ssl_set_session(&ssl
, 1, 0, &ssn
);
290 ssl_set_ca_chain(&ssl
, srvcert
.next
, NULL
);
291 ssl_set_own_cert(&ssl
, &srvcert
, &rsa
);
292 ssl_set_dh_param(&ssl
, my_dhm_P
, my_dhm_G
);
297 printf(" . Performing the SSL/TLS handshake...");
300 while ((ret
= ssl_handshake(&ssl
)) != 0) {
301 if (ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
302 printf(" failed\n ! ssl_handshake returned %d\n\n",
311 * 6. Read the HTTP Request
313 printf(" < Read from client:");
317 len
= sizeof(buf
) - 1;
318 memset(buf
, 0, sizeof(buf
));
319 ret
= ssl_read(&ssl
, buf
, len
);
321 if (ret
== TROPICSSL_ERR_NET_TRY_AGAIN
)
326 case TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY
:
327 printf(" connection was closed gracefully\n");
330 case TROPICSSL_ERR_NET_CONN_RESET
:
331 printf(" connection was reset by peer\n");
335 printf(" ssl_read returned %d\n", ret
);
343 printf(" %d bytes read\n\n%s", len
, (char *)buf
);
348 * 7. Write the 200 Response
350 printf(" > Write to client:");
353 len
= sprintf((char *)buf
, HTTP_RESPONSE
, ssl_get_cipher(&ssl
));
355 while ((ret
= ssl_write(&ssl
, buf
, len
)) <= 0) {
356 if (ret
== TROPICSSL_ERR_NET_CONN_RESET
) {
357 printf(" failed\n ! peer closed the connection\n\n");
361 if (ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
362 printf(" failed\n ! ssl_write returned %d\n\n", ret
);
368 printf(" %d bytes written\n\n%s\n", len
, (char *)buf
);
370 ssl_close_notify(&ssl
);
375 net_close(client_fd
);
381 while (cur
!= NULL
) {
384 memset(prv
, 0, sizeof(ssl_session
));
388 memset(&ssl
, 0, sizeof(ssl_context
));
391 printf(" Press Enter to exit this program.\n");