PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/programs/ssl/ssl_client2.c

https://github.com/leg0/polarssl
C | 648 lines | 498 code | 86 blank | 64 comment | 178 complexity | 3a65e7b6efd620c6e489299526deff07 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * SSL client with certificate authentication
  3. *
  4. * Copyright (C) 2006-2011, Brainspark B.V.
  5. *
  6. * This file is part of PolarSSL (http://www.polarssl.org)
  7. * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. */
  25. #ifndef _CRT_SECURE_NO_DEPRECATE
  26. #define _CRT_SECURE_NO_DEPRECATE 1
  27. #endif
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include "polarssl/config.h"
  32. #include "polarssl/net.h"
  33. #include "polarssl/ssl.h"
  34. #include "polarssl/entropy.h"
  35. #include "polarssl/ctr_drbg.h"
  36. #include "polarssl/certs.h"
  37. #include "polarssl/x509.h"
  38. #include "polarssl/error.h"
  39. #define DFL_SERVER_NAME "localhost"
  40. #define DFL_SERVER_PORT 4433
  41. #define DFL_REQUEST_PAGE "/"
  42. #define DFL_DEBUG_LEVEL 0
  43. #define DFL_CA_FILE ""
  44. #define DFL_CA_PATH ""
  45. #define DFL_CRT_FILE ""
  46. #define DFL_KEY_FILE ""
  47. #define DFL_FORCE_CIPHER 0
  48. #define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED
  49. #define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
  50. #define DFL_MIN_VERSION -1
  51. #define DFL_MAX_VERSION -1
  52. #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
  53. #define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n"
  54. /*
  55. * global options
  56. */
  57. struct options
  58. {
  59. char *server_name; /* hostname of the server (client only) */
  60. int server_port; /* port on which the ssl service runs */
  61. int debug_level; /* level of debugging */
  62. char *request_page; /* page on server to request */
  63. char *ca_file; /* the file with the CA certificate(s) */
  64. char *ca_path; /* the path with the CA certificate(s) reside */
  65. char *crt_file; /* the file with the client certificate */
  66. char *key_file; /* the file with the client key */
  67. int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
  68. int renegotiation; /* enable / disable renegotiation */
  69. int allow_legacy; /* allow legacy renegotiation */
  70. int min_version; /* minimum protocol version accepted */
  71. int max_version; /* maximum protocol version accepted */
  72. int auth_mode; /* verify mode for connection */
  73. } opt;
  74. void my_debug( void *ctx, int level, const char *str )
  75. {
  76. if( level < opt.debug_level )
  77. {
  78. fprintf( (FILE *) ctx, "%s", str );
  79. fflush( (FILE *) ctx );
  80. }
  81. }
  82. /*
  83. * Enabled if debug_level > 1 in code below
  84. */
  85. int my_verify( void *data, x509_cert *crt, int depth, int *flags )
  86. {
  87. char buf[1024];
  88. ((void) data);
  89. printf( "\nVerify requested for (Depth %d):\n", depth );
  90. x509parse_cert_info( buf, sizeof( buf ) - 1, "", crt );
  91. printf( "%s", buf );
  92. if( ( (*flags) & BADCERT_EXPIRED ) != 0 )
  93. printf( " ! server certificate has expired\n" );
  94. if( ( (*flags) & BADCERT_REVOKED ) != 0 )
  95. printf( " ! server certificate has been revoked\n" );
  96. if( ( (*flags) & BADCERT_CN_MISMATCH ) != 0 )
  97. printf( " ! CN mismatch\n" );
  98. if( ( (*flags) & BADCERT_NOT_TRUSTED ) != 0 )
  99. printf( " ! self-signed or not signed by a trusted CA\n" );
  100. if( ( (*flags) & BADCRL_NOT_TRUSTED ) != 0 )
  101. printf( " ! CRL not trusted\n" );
  102. if( ( (*flags) & BADCRL_EXPIRED ) != 0 )
  103. printf( " ! CRL expired\n" );
  104. if( ( (*flags) & BADCERT_OTHER ) != 0 )
  105. printf( " ! other (unknown) flag\n" );
  106. if ( ( *flags ) == 0 )
  107. printf( " This certificate has no flags\n" );
  108. return( 0 );
  109. }
  110. #if defined(POLARSSL_FS_IO)
  111. #define USAGE_IO \
  112. " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \
  113. " default: \"\" (pre-loaded)\n" \
  114. " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \
  115. " default: \"\" (pre-loaded) (overrides ca_file)\n" \
  116. " crt_file=%%s Your own cert and chain (in bottom to top order, top may be omitted)\n" \
  117. " default: \"\" (pre-loaded)\n" \
  118. " key_file=%%s default: \"\" (pre-loaded)\n"
  119. #else
  120. #define USAGE_IO \
  121. " No file operations available (POLARSSL_FS_IO not defined)\n"
  122. #endif /* POLARSSL_FS_IO */
  123. #define USAGE \
  124. "\n usage: ssl_client2 param=<>...\n" \
  125. "\n acceptable parameters:\n" \
  126. " server_name=%%s default: localhost\n" \
  127. " server_port=%%d default: 4433\n" \
  128. " debug_level=%%d default: 0 (disabled)\n" \
  129. USAGE_IO \
  130. " request_page=%%s default: \".\"\n" \
  131. " renegotiation=%%d default: 1 (enabled)\n" \
  132. " allow_legacy=%%d default: 0 (disabled)\n" \
  133. "\n" \
  134. " min_version=%%s default: \"\" (ssl3)\n" \
  135. " max_version=%%s default: \"\" (tls1_2)\n" \
  136. " force_version=%%s default: \"\" (none)\n" \
  137. " options: ssl3, tls1, tls1_1, tls1_2\n" \
  138. " auth_mode=%%s default: \"optional\"\n" \
  139. " options: none, optional, required\n" \
  140. "\n" \
  141. " force_ciphersuite=<name> default: all enabled\n"\
  142. " acceptable ciphersuite names:\n"
  143. #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \
  144. !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
  145. !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \
  146. !defined(POLARSSL_CTR_DRBG_C)
  147. int main( int argc, char *argv[] )
  148. {
  149. ((void) argc);
  150. ((void) argv);
  151. printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
  152. "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
  153. "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
  154. "POLARSSL_CTR_DRBG_C not defined.\n");
  155. return( 0 );
  156. }
  157. #else
  158. int main( int argc, char *argv[] )
  159. {
  160. int ret = 0, len, server_fd;
  161. unsigned char buf[1024];
  162. char *pers = "ssl_client2";
  163. entropy_context entropy;
  164. ctr_drbg_context ctr_drbg;
  165. ssl_context ssl;
  166. x509_cert cacert;
  167. x509_cert clicert;
  168. rsa_context rsa;
  169. int i;
  170. char *p, *q;
  171. const int *list;
  172. /*
  173. * Make sure memory references are valid.
  174. */
  175. server_fd = 0;
  176. memset( &ssl, 0, sizeof( ssl_context ) );
  177. memset( &cacert, 0, sizeof( x509_cert ) );
  178. memset( &clicert, 0, sizeof( x509_cert ) );
  179. memset( &rsa, 0, sizeof( rsa_context ) );
  180. if( argc == 0 )
  181. {
  182. usage:
  183. if( ret == 0 )
  184. ret = 1;
  185. printf( USAGE );
  186. list = ssl_list_ciphersuites();
  187. while( *list )
  188. {
  189. printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
  190. list++;
  191. }
  192. printf("\n");
  193. goto exit;
  194. }
  195. opt.server_name = DFL_SERVER_NAME;
  196. opt.server_port = DFL_SERVER_PORT;
  197. opt.debug_level = DFL_DEBUG_LEVEL;
  198. opt.request_page = DFL_REQUEST_PAGE;
  199. opt.ca_file = DFL_CA_FILE;
  200. opt.ca_path = DFL_CA_PATH;
  201. opt.crt_file = DFL_CRT_FILE;
  202. opt.key_file = DFL_KEY_FILE;
  203. opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
  204. opt.renegotiation = DFL_RENEGOTIATION;
  205. opt.allow_legacy = DFL_ALLOW_LEGACY;
  206. opt.min_version = DFL_MIN_VERSION;
  207. opt.max_version = DFL_MAX_VERSION;
  208. opt.auth_mode = DFL_AUTH_MODE;
  209. for( i = 1; i < argc; i++ )
  210. {
  211. p = argv[i];
  212. if( ( q = strchr( p, '=' ) ) == NULL )
  213. goto usage;
  214. *q++ = '\0';
  215. if( strcmp( p, "server_name" ) == 0 )
  216. opt.server_name = q;
  217. else if( strcmp( p, "server_port" ) == 0 )
  218. {
  219. opt.server_port = atoi( q );
  220. if( opt.server_port < 1 || opt.server_port > 65535 )
  221. goto usage;
  222. }
  223. else if( strcmp( p, "debug_level" ) == 0 )
  224. {
  225. opt.debug_level = atoi( q );
  226. if( opt.debug_level < 0 || opt.debug_level > 65535 )
  227. goto usage;
  228. }
  229. else if( strcmp( p, "request_page" ) == 0 )
  230. opt.request_page = q;
  231. else if( strcmp( p, "ca_file" ) == 0 )
  232. opt.ca_file = q;
  233. else if( strcmp( p, "ca_path" ) == 0 )
  234. opt.ca_path = q;
  235. else if( strcmp( p, "crt_file" ) == 0 )
  236. opt.crt_file = q;
  237. else if( strcmp( p, "key_file" ) == 0 )
  238. opt.key_file = q;
  239. else if( strcmp( p, "force_ciphersuite" ) == 0 )
  240. {
  241. opt.force_ciphersuite[0] = -1;
  242. opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
  243. if( opt.force_ciphersuite[0] <= 0 )
  244. {
  245. ret = 2;
  246. goto usage;
  247. }
  248. opt.force_ciphersuite[1] = 0;
  249. }
  250. else if( strcmp( p, "renegotiation" ) == 0 )
  251. {
  252. opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
  253. SSL_RENEGOTIATION_DISABLED;
  254. }
  255. else if( strcmp( p, "allow_legacy" ) == 0 )
  256. {
  257. opt.allow_legacy = atoi( q );
  258. if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
  259. goto usage;
  260. }
  261. else if( strcmp( p, "min_version" ) == 0 )
  262. {
  263. if( strcmp( q, "ssl3" ) == 0 )
  264. opt.min_version = SSL_MINOR_VERSION_0;
  265. else if( strcmp( q, "tls1" ) == 0 )
  266. opt.min_version = SSL_MINOR_VERSION_1;
  267. else if( strcmp( q, "tls1_1" ) == 0 )
  268. opt.min_version = SSL_MINOR_VERSION_2;
  269. else if( strcmp( q, "tls1_2" ) == 0 )
  270. opt.min_version = SSL_MINOR_VERSION_3;
  271. else
  272. goto usage;
  273. }
  274. else if( strcmp( p, "max_version" ) == 0 )
  275. {
  276. if( strcmp( q, "ssl3" ) == 0 )
  277. opt.max_version = SSL_MINOR_VERSION_0;
  278. else if( strcmp( q, "tls1" ) == 0 )
  279. opt.max_version = SSL_MINOR_VERSION_1;
  280. else if( strcmp( q, "tls1_1" ) == 0 )
  281. opt.max_version = SSL_MINOR_VERSION_2;
  282. else if( strcmp( q, "tls1_2" ) == 0 )
  283. opt.max_version = SSL_MINOR_VERSION_3;
  284. else
  285. goto usage;
  286. }
  287. else if( strcmp( p, "force_version" ) == 0 )
  288. {
  289. if( strcmp( q, "ssl3" ) == 0 )
  290. {
  291. opt.min_version = SSL_MINOR_VERSION_0;
  292. opt.max_version = SSL_MINOR_VERSION_0;
  293. }
  294. else if( strcmp( q, "tls1" ) == 0 )
  295. {
  296. opt.min_version = SSL_MINOR_VERSION_1;
  297. opt.max_version = SSL_MINOR_VERSION_1;
  298. }
  299. else if( strcmp( q, "tls1_1" ) == 0 )
  300. {
  301. opt.min_version = SSL_MINOR_VERSION_2;
  302. opt.max_version = SSL_MINOR_VERSION_2;
  303. }
  304. else if( strcmp( q, "tls1_2" ) == 0 )
  305. {
  306. opt.min_version = SSL_MINOR_VERSION_3;
  307. opt.max_version = SSL_MINOR_VERSION_3;
  308. }
  309. else
  310. goto usage;
  311. }
  312. else if( strcmp( p, "auth_mode" ) == 0 )
  313. {
  314. if( strcmp( q, "none" ) == 0 )
  315. opt.auth_mode = SSL_VERIFY_NONE;
  316. else if( strcmp( q, "optional" ) == 0 )
  317. opt.auth_mode = SSL_VERIFY_OPTIONAL;
  318. else if( strcmp( q, "required" ) == 0 )
  319. opt.auth_mode = SSL_VERIFY_REQUIRED;
  320. else
  321. goto usage;
  322. }
  323. else
  324. goto usage;
  325. }
  326. /*
  327. * 0. Initialize the RNG and the session data
  328. */
  329. printf( "\n . Seeding the random number generator..." );
  330. fflush( stdout );
  331. entropy_init( &entropy );
  332. if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
  333. (unsigned char *) pers, strlen( pers ) ) ) != 0 )
  334. {
  335. printf( " failed\n ! ctr_drbg_init returned -0x%x\n", -ret );
  336. goto exit;
  337. }
  338. printf( " ok\n" );
  339. /*
  340. * 1.1. Load the trusted CA
  341. */
  342. printf( " . Loading the CA root certificate ..." );
  343. fflush( stdout );
  344. #if defined(POLARSSL_FS_IO)
  345. if( strlen( opt.ca_path ) )
  346. ret = x509parse_crtpath( &cacert, opt.ca_path );
  347. else if( strlen( opt.ca_file ) )
  348. ret = x509parse_crtfile( &cacert, opt.ca_file );
  349. else
  350. #endif
  351. #if defined(POLARSSL_CERTS_C)
  352. ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
  353. strlen( test_ca_crt ) );
  354. #else
  355. {
  356. ret = 1;
  357. printf("POLARSSL_CERTS_C not defined.");
  358. }
  359. #endif
  360. if( ret < 0 )
  361. {
  362. printf( " failed\n ! x509parse_crt returned -0x%x\n\n", -ret );
  363. goto exit;
  364. }
  365. printf( " ok (%d skipped)\n", ret );
  366. /*
  367. * 1.2. Load own certificate and private key
  368. *
  369. * (can be skipped if client authentication is not required)
  370. */
  371. printf( " . Loading the client cert. and key..." );
  372. fflush( stdout );
  373. #if defined(POLARSSL_FS_IO)
  374. if( strlen( opt.crt_file ) )
  375. ret = x509parse_crtfile( &clicert, opt.crt_file );
  376. else
  377. #endif
  378. #if defined(POLARSSL_CERTS_C)
  379. ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
  380. strlen( test_cli_crt ) );
  381. #else
  382. {
  383. ret = 1;
  384. printf("POLARSSL_CERTS_C not defined.");
  385. }
  386. #endif
  387. if( ret != 0 )
  388. {
  389. printf( " failed\n ! x509parse_crt returned -0x%x\n\n", -ret );
  390. goto exit;
  391. }
  392. #if defined(POLARSSL_FS_IO)
  393. if( strlen( opt.key_file ) )
  394. ret = x509parse_keyfile( &rsa, opt.key_file, "" );
  395. else
  396. #endif
  397. #if defined(POLARSSL_CERTS_C)
  398. ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
  399. strlen( test_cli_key ), NULL, 0 );
  400. #else
  401. {
  402. ret = 1;
  403. printf("POLARSSL_CERTS_C not defined.");
  404. }
  405. #endif
  406. if( ret != 0 )
  407. {
  408. printf( " failed\n ! x509parse_key returned -0x%x\n\n", -ret );
  409. goto exit;
  410. }
  411. printf( " ok\n" );
  412. /*
  413. * 2. Start the connection
  414. */
  415. printf( " . Connecting to tcp/%s/%-4d...", opt.server_name,
  416. opt.server_port );
  417. fflush( stdout );
  418. if( ( ret = net_connect( &server_fd, opt.server_name,
  419. opt.server_port ) ) != 0 )
  420. {
  421. printf( " failed\n ! net_connect returned -0x%x\n\n", -ret );
  422. goto exit;
  423. }
  424. printf( " ok\n" );
  425. /*
  426. * 3. Setup stuff
  427. */
  428. printf( " . Setting up the SSL/TLS structure..." );
  429. fflush( stdout );
  430. if( ( ret = ssl_init( &ssl ) ) != 0 )
  431. {
  432. printf( " failed\n ! ssl_init returned -0x%x\n\n", -ret );
  433. goto exit;
  434. }
  435. printf( " ok\n" );
  436. if( opt.debug_level > 0 )
  437. ssl_set_verify( &ssl, my_verify, NULL );
  438. ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
  439. ssl_set_authmode( &ssl, opt.auth_mode );
  440. ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
  441. ssl_set_dbg( &ssl, my_debug, stdout );
  442. ssl_set_bio( &ssl, net_recv, &server_fd,
  443. net_send, &server_fd );
  444. if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
  445. ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
  446. ssl_set_renegotiation( &ssl, opt.renegotiation );
  447. ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
  448. ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
  449. ssl_set_own_cert( &ssl, &clicert, &rsa );
  450. ssl_set_hostname( &ssl, opt.server_name );
  451. if( opt.min_version != -1 )
  452. ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
  453. if( opt.max_version != -1 )
  454. ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );
  455. /*
  456. * 4. Handshake
  457. */
  458. printf( " . Performing the SSL/TLS handshake..." );
  459. fflush( stdout );
  460. while( ( ret = ssl_handshake( &ssl ) ) != 0 )
  461. {
  462. if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
  463. {
  464. printf( " failed\n ! ssl_handshake returned -0x%x\n\n", -ret );
  465. goto exit;
  466. }
  467. }
  468. printf( " ok\n [ Ciphersuite is %s ]\n",
  469. ssl_get_ciphersuite( &ssl ) );
  470. /*
  471. * 5. Verify the server certificate
  472. */
  473. printf( " . Verifying peer X.509 certificate..." );
  474. if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
  475. {
  476. printf( " failed\n" );
  477. if( ( ret & BADCERT_EXPIRED ) != 0 )
  478. printf( " ! server certificate has expired\n" );
  479. if( ( ret & BADCERT_REVOKED ) != 0 )
  480. printf( " ! server certificate has been revoked\n" );
  481. if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
  482. printf( " ! CN mismatch (expected CN=%s)\n", opt.server_name );
  483. if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
  484. printf( " ! self-signed or not signed by a trusted CA\n" );
  485. printf( "\n" );
  486. }
  487. else
  488. printf( " ok\n" );
  489. printf( " . Peer certificate information ...\n" );
  490. x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ",
  491. ssl_get_peer_cert( &ssl ) );
  492. printf( "%s\n", buf );
  493. /*
  494. * 6. Write the GET request
  495. */
  496. printf( " > Write to server:" );
  497. fflush( stdout );
  498. len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );
  499. while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
  500. {
  501. if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
  502. {
  503. printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret );
  504. goto exit;
  505. }
  506. }
  507. len = ret;
  508. printf( " %d bytes written\n\n%s", len, (char *) buf );
  509. /*
  510. * 7. Read the HTTP response
  511. */
  512. printf( " < Read from server:" );
  513. fflush( stdout );
  514. do
  515. {
  516. len = sizeof( buf ) - 1;
  517. memset( buf, 0, sizeof( buf ) );
  518. ret = ssl_read( &ssl, buf, len );
  519. if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
  520. continue;
  521. if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
  522. break;
  523. if( ret < 0 )
  524. {
  525. printf( "failed\n ! ssl_read returned -0x%x\n\n", -ret );
  526. break;
  527. }
  528. if( ret == 0 )
  529. {
  530. printf("\n\nEOF\n\n");
  531. break;
  532. }
  533. len = ret;
  534. printf( " %d bytes read\n\n%s", len, (char *) buf );
  535. }
  536. while( 1 );
  537. ssl_close_notify( &ssl );
  538. exit:
  539. #ifdef POLARSSL_ERROR_C
  540. if( ret != 0 )
  541. {
  542. char error_buf[100];
  543. error_strerror( ret, error_buf, 100 );
  544. printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
  545. }
  546. #endif
  547. if( server_fd )
  548. net_close( server_fd );
  549. x509_free( &clicert );
  550. x509_free( &cacert );
  551. rsa_free( &rsa );
  552. ssl_free( &ssl );
  553. memset( &ssl, 0, sizeof( ssl ) );
  554. #if defined(_WIN32)
  555. printf( " + Press Enter to exit this program.\n" );
  556. fflush( stdout ); getchar();
  557. #endif
  558. return( ret );
  559. }
  560. #endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_SSL_TLS_C &&
  561. POLARSSL_SSL_CLI_C && POLARSSL_NET_C && POLARSSL_RSA_C &&
  562. POLARSSL_CTR_DRBG_C */