ssl_mail_client.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /*
  2. * SSL client for SMTP servers
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. *
  7. * This file is provided under the Apache License 2.0, or the
  8. * GNU General Public License v2.0 or later.
  9. *
  10. * **********
  11. * Apache License 2.0:
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  14. * not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  21. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *
  25. * **********
  26. *
  27. * **********
  28. * GNU General Public License v2.0 or later:
  29. *
  30. * This program is free software; you can redistribute it and/or modify
  31. * it under the terms of the GNU General Public License as published by
  32. * the Free Software Foundation; either version 2 of the License, or
  33. * (at your option) any later version.
  34. *
  35. * This program is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  38. * GNU General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU General Public License along
  41. * with this program; if not, write to the Free Software Foundation, Inc.,
  42. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  43. *
  44. * **********
  45. */
  46. /* Enable definition of gethostname() even when compiling with -std=c99. Must
  47. * be set before config.h, which pulls in glibc's features.h indirectly.
  48. * Harmless on other platforms. */
  49. #define _POSIX_C_SOURCE 200112L
  50. #if defined(__NetBSD__)
  51. #define _XOPEN_SOURCE 600
  52. #endif
  53. #if !defined(MBEDTLS_CONFIG_FILE)
  54. #include "mbedtls/config.h"
  55. #else
  56. #include MBEDTLS_CONFIG_FILE
  57. #endif
  58. #if defined(MBEDTLS_PLATFORM_C)
  59. #include "mbedtls/platform.h"
  60. #else
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #define mbedtls_time time
  64. #define mbedtls_time_t time_t
  65. #define mbedtls_fprintf fprintf
  66. #define mbedtls_printf printf
  67. #define mbedtls_exit exit
  68. #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
  69. #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
  70. #endif /* MBEDTLS_PLATFORM_C */
  71. #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
  72. !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
  73. !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
  74. !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
  75. !defined(MBEDTLS_FS_IO)
  76. int main( void )
  77. {
  78. mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
  79. "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
  80. "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
  81. "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
  82. "not defined.\n");
  83. mbedtls_exit( 0 );
  84. }
  85. #else
  86. #include "mbedtls/base64.h"
  87. #include "mbedtls/error.h"
  88. #include "mbedtls/net_sockets.h"
  89. #include "mbedtls/ssl.h"
  90. #include "mbedtls/entropy.h"
  91. #include "mbedtls/ctr_drbg.h"
  92. #include "mbedtls/certs.h"
  93. #include "mbedtls/x509.h"
  94. #include <stdlib.h>
  95. #include <string.h>
  96. #if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32)
  97. #include <unistd.h>
  98. #else
  99. #include <io.h>
  100. #endif
  101. #if defined(_WIN32) || defined(_WIN32_WCE)
  102. #include <winsock2.h>
  103. #include <windows.h>
  104. #if defined(_MSC_VER)
  105. #if defined(_WIN32_WCE)
  106. #pragma comment( lib, "ws2.lib" )
  107. #else
  108. #pragma comment( lib, "ws2_32.lib" )
  109. #endif
  110. #endif /* _MSC_VER */
  111. #endif
  112. #define DFL_SERVER_NAME "localhost"
  113. #define DFL_SERVER_PORT "465"
  114. #define DFL_USER_NAME "user"
  115. #define DFL_USER_PWD "password"
  116. #define DFL_MAIL_FROM ""
  117. #define DFL_MAIL_TO ""
  118. #define DFL_DEBUG_LEVEL 0
  119. #define DFL_CA_FILE ""
  120. #define DFL_CRT_FILE ""
  121. #define DFL_KEY_FILE ""
  122. #define DFL_FORCE_CIPHER 0
  123. #define DFL_MODE 0
  124. #define DFL_AUTHENTICATION 0
  125. #define MODE_SSL_TLS 0
  126. #define MODE_STARTTLS 0
  127. #if defined(MBEDTLS_BASE64_C)
  128. #define USAGE_AUTH \
  129. " authentication=%%d default: 0 (disabled)\n" \
  130. " user_name=%%s default: \"" DFL_USER_NAME "\"\n" \
  131. " user_pwd=%%s default: \"" DFL_USER_PWD "\"\n"
  132. #else
  133. #define USAGE_AUTH \
  134. " authentication options disabled. (Require MBEDTLS_BASE64_C)\n"
  135. #endif /* MBEDTLS_BASE64_C */
  136. #if defined(MBEDTLS_FS_IO)
  137. #define USAGE_IO \
  138. " ca_file=%%s default: \"\" (pre-loaded)\n" \
  139. " crt_file=%%s default: \"\" (pre-loaded)\n" \
  140. " key_file=%%s default: \"\" (pre-loaded)\n"
  141. #else
  142. #define USAGE_IO \
  143. " No file operations available (MBEDTLS_FS_IO not defined)\n"
  144. #endif /* MBEDTLS_FS_IO */
  145. #define USAGE \
  146. "\n usage: ssl_mail_client param=<>...\n" \
  147. "\n acceptable parameters:\n" \
  148. " server_name=%%s default: " DFL_SERVER_NAME "\n" \
  149. " server_port=%%d default: " DFL_SERVER_PORT "\n" \
  150. " debug_level=%%d default: 0 (disabled)\n" \
  151. " mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \
  152. USAGE_AUTH \
  153. " mail_from=%%s default: \"\"\n" \
  154. " mail_to=%%s default: \"\"\n" \
  155. USAGE_IO \
  156. " force_ciphersuite=<name> default: all enabled\n" \
  157. " acceptable ciphersuite names:\n"
  158. /*
  159. * global options
  160. */
  161. struct options
  162. {
  163. const char *server_name; /* hostname of the server (client only) */
  164. const char *server_port; /* port on which the ssl service runs */
  165. int debug_level; /* level of debugging */
  166. int authentication; /* if authentication is required */
  167. int mode; /* SSL/TLS (0) or STARTTLS (1) */
  168. const char *user_name; /* username to use for authentication */
  169. const char *user_pwd; /* password to use for authentication */
  170. const char *mail_from; /* E-Mail address to use as sender */
  171. const char *mail_to; /* E-Mail address to use as recipient */
  172. const char *ca_file; /* the file with the CA certificate(s) */
  173. const char *crt_file; /* the file with the client certificate */
  174. const char *key_file; /* the file with the client key */
  175. int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
  176. } opt;
  177. static void my_debug( void *ctx, int level,
  178. const char *file, int line,
  179. const char *str )
  180. {
  181. ((void) level);
  182. mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
  183. fflush( (FILE *) ctx );
  184. }
  185. static int do_handshake( mbedtls_ssl_context *ssl )
  186. {
  187. int ret;
  188. uint32_t flags;
  189. unsigned char buf[1024];
  190. memset(buf, 0, 1024);
  191. /*
  192. * 4. Handshake
  193. */
  194. mbedtls_printf( " . Performing the SSL/TLS handshake..." );
  195. fflush( stdout );
  196. while( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
  197. {
  198. if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
  199. {
  200. #if defined(MBEDTLS_ERROR_C)
  201. mbedtls_strerror( ret, (char *) buf, 1024 );
  202. #endif
  203. mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d: %s\n\n", ret, buf );
  204. return( -1 );
  205. }
  206. }
  207. mbedtls_printf( " ok\n [ Ciphersuite is %s ]\n",
  208. mbedtls_ssl_get_ciphersuite( ssl ) );
  209. /*
  210. * 5. Verify the server certificate
  211. */
  212. mbedtls_printf( " . Verifying peer X.509 certificate..." );
  213. /* In real life, we probably want to bail out when ret != 0 */
  214. if( ( flags = mbedtls_ssl_get_verify_result( ssl ) ) != 0 )
  215. {
  216. char vrfy_buf[512];
  217. mbedtls_printf( " failed\n" );
  218. mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
  219. mbedtls_printf( "%s\n", vrfy_buf );
  220. }
  221. else
  222. mbedtls_printf( " ok\n" );
  223. mbedtls_printf( " . Peer certificate information ...\n" );
  224. mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
  225. mbedtls_ssl_get_peer_cert( ssl ) );
  226. mbedtls_printf( "%s\n", buf );
  227. return( 0 );
  228. }
  229. static int write_ssl_data( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
  230. {
  231. int ret;
  232. mbedtls_printf("\n%s", buf);
  233. while( len && ( ret = mbedtls_ssl_write( ssl, buf, len ) ) <= 0 )
  234. {
  235. if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
  236. {
  237. mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
  238. return -1;
  239. }
  240. }
  241. return( 0 );
  242. }
  243. static int write_ssl_and_get_response( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
  244. {
  245. int ret;
  246. unsigned char data[128];
  247. char code[4];
  248. size_t i, idx = 0;
  249. mbedtls_printf("\n%s", buf);
  250. while( len && ( ret = mbedtls_ssl_write( ssl, buf, len ) ) <= 0 )
  251. {
  252. if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
  253. {
  254. mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
  255. return -1;
  256. }
  257. }
  258. do
  259. {
  260. len = sizeof( data ) - 1;
  261. memset( data, 0, sizeof( data ) );
  262. ret = mbedtls_ssl_read( ssl, data, len );
  263. if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
  264. continue;
  265. if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
  266. return -1;
  267. if( ret <= 0 )
  268. {
  269. mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret );
  270. return -1;
  271. }
  272. mbedtls_printf("\n%s", data);
  273. len = ret;
  274. for( i = 0; i < len; i++ )
  275. {
  276. if( data[i] != '\n' )
  277. {
  278. if( idx < 4 )
  279. code[ idx++ ] = data[i];
  280. continue;
  281. }
  282. if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
  283. {
  284. code[3] = '\0';
  285. return atoi( code );
  286. }
  287. idx = 0;
  288. }
  289. }
  290. while( 1 );
  291. }
  292. static int write_and_get_response( mbedtls_net_context *sock_fd, unsigned char *buf, size_t len )
  293. {
  294. int ret;
  295. unsigned char data[128];
  296. char code[4];
  297. size_t i, idx = 0;
  298. mbedtls_printf("\n%s", buf);
  299. if( len && ( ret = mbedtls_net_send( sock_fd, buf, len ) ) <= 0 )
  300. {
  301. mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
  302. return -1;
  303. }
  304. do
  305. {
  306. len = sizeof( data ) - 1;
  307. memset( data, 0, sizeof( data ) );
  308. ret = mbedtls_net_recv( sock_fd, data, len );
  309. if( ret <= 0 )
  310. {
  311. mbedtls_printf( "failed\n ! mbedtls_net_recv returned %d\n\n", ret );
  312. return -1;
  313. }
  314. data[len] = '\0';
  315. mbedtls_printf("\n%s", data);
  316. len = ret;
  317. for( i = 0; i < len; i++ )
  318. {
  319. if( data[i] != '\n' )
  320. {
  321. if( idx < 4 )
  322. code[ idx++ ] = data[i];
  323. continue;
  324. }
  325. if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
  326. {
  327. code[3] = '\0';
  328. return atoi( code );
  329. }
  330. idx = 0;
  331. }
  332. }
  333. while( 1 );
  334. }
  335. int main( int argc, char *argv[] )
  336. {
  337. int ret = 1, len;
  338. int exit_code = MBEDTLS_EXIT_FAILURE;
  339. mbedtls_net_context server_fd;
  340. #if defined(MBEDTLS_BASE64_C)
  341. unsigned char base[1024];
  342. /* buf is used as the destination buffer for printing base with the format:
  343. * "%s\r\n". Hence, the size of buf should be at least the size of base
  344. * plus 2 bytes for the \r and \n characters.
  345. */
  346. unsigned char buf[sizeof( base ) + 2];
  347. #else
  348. unsigned char buf[1024];
  349. #endif
  350. char hostname[32];
  351. const char *pers = "ssl_mail_client";
  352. mbedtls_entropy_context entropy;
  353. mbedtls_ctr_drbg_context ctr_drbg;
  354. mbedtls_ssl_context ssl;
  355. mbedtls_ssl_config conf;
  356. mbedtls_x509_crt cacert;
  357. mbedtls_x509_crt clicert;
  358. mbedtls_pk_context pkey;
  359. int i;
  360. size_t n;
  361. char *p, *q;
  362. const int *list;
  363. /*
  364. * Make sure memory references are valid in case we exit early.
  365. */
  366. mbedtls_net_init( &server_fd );
  367. mbedtls_ssl_init( &ssl );
  368. mbedtls_ssl_config_init( &conf );
  369. memset( &buf, 0, sizeof( buf ) );
  370. mbedtls_x509_crt_init( &cacert );
  371. mbedtls_x509_crt_init( &clicert );
  372. mbedtls_pk_init( &pkey );
  373. mbedtls_ctr_drbg_init( &ctr_drbg );
  374. if( argc == 0 )
  375. {
  376. usage:
  377. mbedtls_printf( USAGE );
  378. list = mbedtls_ssl_list_ciphersuites();
  379. while( *list )
  380. {
  381. mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) );
  382. list++;
  383. }
  384. mbedtls_printf("\n");
  385. goto exit;
  386. }
  387. opt.server_name = DFL_SERVER_NAME;
  388. opt.server_port = DFL_SERVER_PORT;
  389. opt.debug_level = DFL_DEBUG_LEVEL;
  390. opt.authentication = DFL_AUTHENTICATION;
  391. opt.mode = DFL_MODE;
  392. opt.user_name = DFL_USER_NAME;
  393. opt.user_pwd = DFL_USER_PWD;
  394. opt.mail_from = DFL_MAIL_FROM;
  395. opt.mail_to = DFL_MAIL_TO;
  396. opt.ca_file = DFL_CA_FILE;
  397. opt.crt_file = DFL_CRT_FILE;
  398. opt.key_file = DFL_KEY_FILE;
  399. opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
  400. for( i = 1; i < argc; i++ )
  401. {
  402. p = argv[i];
  403. if( ( q = strchr( p, '=' ) ) == NULL )
  404. goto usage;
  405. *q++ = '\0';
  406. if( strcmp( p, "server_name" ) == 0 )
  407. opt.server_name = q;
  408. else if( strcmp( p, "server_port" ) == 0 )
  409. opt.server_port = q;
  410. else if( strcmp( p, "debug_level" ) == 0 )
  411. {
  412. opt.debug_level = atoi( q );
  413. if( opt.debug_level < 0 || opt.debug_level > 65535 )
  414. goto usage;
  415. }
  416. else if( strcmp( p, "authentication" ) == 0 )
  417. {
  418. opt.authentication = atoi( q );
  419. if( opt.authentication < 0 || opt.authentication > 1 )
  420. goto usage;
  421. }
  422. else if( strcmp( p, "mode" ) == 0 )
  423. {
  424. opt.mode = atoi( q );
  425. if( opt.mode < 0 || opt.mode > 1 )
  426. goto usage;
  427. }
  428. else if( strcmp( p, "user_name" ) == 0 )
  429. opt.user_name = q;
  430. else if( strcmp( p, "user_pwd" ) == 0 )
  431. opt.user_pwd = q;
  432. else if( strcmp( p, "mail_from" ) == 0 )
  433. opt.mail_from = q;
  434. else if( strcmp( p, "mail_to" ) == 0 )
  435. opt.mail_to = q;
  436. else if( strcmp( p, "ca_file" ) == 0 )
  437. opt.ca_file = q;
  438. else if( strcmp( p, "crt_file" ) == 0 )
  439. opt.crt_file = q;
  440. else if( strcmp( p, "key_file" ) == 0 )
  441. opt.key_file = q;
  442. else if( strcmp( p, "force_ciphersuite" ) == 0 )
  443. {
  444. opt.force_ciphersuite[0] = -1;
  445. opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q );
  446. if( opt.force_ciphersuite[0] <= 0 )
  447. goto usage;
  448. opt.force_ciphersuite[1] = 0;
  449. }
  450. else
  451. goto usage;
  452. }
  453. /*
  454. * 0. Initialize the RNG and the session data
  455. */
  456. mbedtls_printf( "\n . Seeding the random number generator..." );
  457. fflush( stdout );
  458. mbedtls_entropy_init( &entropy );
  459. if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
  460. (const unsigned char *) pers,
  461. strlen( pers ) ) ) != 0 )
  462. {
  463. mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
  464. goto exit;
  465. }
  466. mbedtls_printf( " ok\n" );
  467. /*
  468. * 1.1. Load the trusted CA
  469. */
  470. mbedtls_printf( " . Loading the CA root certificate ..." );
  471. fflush( stdout );
  472. #if defined(MBEDTLS_FS_IO)
  473. if( strlen( opt.ca_file ) )
  474. ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file );
  475. else
  476. #endif
  477. #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C)
  478. ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
  479. mbedtls_test_cas_pem_len );
  480. #else
  481. {
  482. mbedtls_printf("MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined.");
  483. goto exit;
  484. }
  485. #endif
  486. if( ret < 0 )
  487. {
  488. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret );
  489. goto exit;
  490. }
  491. mbedtls_printf( " ok (%d skipped)\n", ret );
  492. /*
  493. * 1.2. Load own certificate and private key
  494. *
  495. * (can be skipped if client authentication is not required)
  496. */
  497. mbedtls_printf( " . Loading the client cert. and key..." );
  498. fflush( stdout );
  499. #if defined(MBEDTLS_FS_IO)
  500. if( strlen( opt.crt_file ) )
  501. ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file );
  502. else
  503. #endif
  504. #if defined(MBEDTLS_CERTS_C)
  505. ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
  506. mbedtls_test_cli_crt_len );
  507. #else
  508. {
  509. mbedtls_printf("MBEDTLS_CERTS_C not defined.");
  510. goto exit;
  511. }
  512. #endif
  513. if( ret != 0 )
  514. {
  515. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret );
  516. goto exit;
  517. }
  518. #if defined(MBEDTLS_FS_IO)
  519. if( strlen( opt.key_file ) )
  520. ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" );
  521. else
  522. #endif
  523. #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C)
  524. ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key,
  525. mbedtls_test_cli_key_len, NULL, 0 );
  526. #else
  527. {
  528. mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined.");
  529. goto exit;
  530. }
  531. #endif
  532. if( ret != 0 )
  533. {
  534. mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret );
  535. goto exit;
  536. }
  537. mbedtls_printf( " ok\n" );
  538. /*
  539. * 2. Start the connection
  540. */
  541. mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name,
  542. opt.server_port );
  543. fflush( stdout );
  544. if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name,
  545. opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
  546. {
  547. mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
  548. goto exit;
  549. }
  550. mbedtls_printf( " ok\n" );
  551. /*
  552. * 3. Setup stuff
  553. */
  554. mbedtls_printf( " . Setting up the SSL/TLS structure..." );
  555. fflush( stdout );
  556. if( ( ret = mbedtls_ssl_config_defaults( &conf,
  557. MBEDTLS_SSL_IS_CLIENT,
  558. MBEDTLS_SSL_TRANSPORT_STREAM,
  559. MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
  560. {
  561. mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
  562. goto exit;
  563. }
  564. /* OPTIONAL is not optimal for security,
  565. * but makes interop easier in this simplified example */
  566. mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
  567. mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
  568. mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
  569. if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
  570. mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite );
  571. mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
  572. if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 )
  573. {
  574. mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
  575. goto exit;
  576. }
  577. if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
  578. {
  579. mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
  580. goto exit;
  581. }
  582. if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
  583. {
  584. mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
  585. goto exit;
  586. }
  587. mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
  588. mbedtls_printf( " ok\n" );
  589. if( opt.mode == MODE_SSL_TLS )
  590. {
  591. if( do_handshake( &ssl ) != 0 )
  592. goto exit;
  593. mbedtls_printf( " > Get header from server:" );
  594. fflush( stdout );
  595. ret = write_ssl_and_get_response( &ssl, buf, 0 );
  596. if( ret < 200 || ret > 299 )
  597. {
  598. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  599. goto exit;
  600. }
  601. mbedtls_printf(" ok\n" );
  602. mbedtls_printf( " > Write EHLO to server:" );
  603. fflush( stdout );
  604. gethostname( hostname, 32 );
  605. len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
  606. ret = write_ssl_and_get_response( &ssl, buf, len );
  607. if( ret < 200 || ret > 299 )
  608. {
  609. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  610. goto exit;
  611. }
  612. }
  613. else
  614. {
  615. mbedtls_printf( " > Get header from server:" );
  616. fflush( stdout );
  617. ret = write_and_get_response( &server_fd, buf, 0 );
  618. if( ret < 200 || ret > 299 )
  619. {
  620. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  621. goto exit;
  622. }
  623. mbedtls_printf(" ok\n" );
  624. mbedtls_printf( " > Write EHLO to server:" );
  625. fflush( stdout );
  626. gethostname( hostname, 32 );
  627. len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
  628. ret = write_and_get_response( &server_fd, buf, len );
  629. if( ret < 200 || ret > 299 )
  630. {
  631. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  632. goto exit;
  633. }
  634. mbedtls_printf(" ok\n" );
  635. mbedtls_printf( " > Write STARTTLS to server:" );
  636. fflush( stdout );
  637. gethostname( hostname, 32 );
  638. len = sprintf( (char *) buf, "STARTTLS\r\n" );
  639. ret = write_and_get_response( &server_fd, buf, len );
  640. if( ret < 200 || ret > 299 )
  641. {
  642. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  643. goto exit;
  644. }
  645. mbedtls_printf(" ok\n" );
  646. if( do_handshake( &ssl ) != 0 )
  647. goto exit;
  648. }
  649. #if defined(MBEDTLS_BASE64_C)
  650. if( opt.authentication )
  651. {
  652. mbedtls_printf( " > Write AUTH LOGIN to server:" );
  653. fflush( stdout );
  654. len = sprintf( (char *) buf, "AUTH LOGIN\r\n" );
  655. ret = write_ssl_and_get_response( &ssl, buf, len );
  656. if( ret < 200 || ret > 399 )
  657. {
  658. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  659. goto exit;
  660. }
  661. mbedtls_printf(" ok\n" );
  662. mbedtls_printf( " > Write username to server: %s", opt.user_name );
  663. fflush( stdout );
  664. ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name,
  665. strlen( opt.user_name ) );
  666. if( ret != 0 ) {
  667. mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret );
  668. goto exit;
  669. }
  670. len = sprintf( (char *) buf, "%s\r\n", base );
  671. ret = write_ssl_and_get_response( &ssl, buf, len );
  672. if( ret < 300 || ret > 399 )
  673. {
  674. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  675. goto exit;
  676. }
  677. mbedtls_printf(" ok\n" );
  678. mbedtls_printf( " > Write password to server: %s", opt.user_pwd );
  679. fflush( stdout );
  680. ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd,
  681. strlen( opt.user_pwd ) );
  682. if( ret != 0 ) {
  683. mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret );
  684. goto exit;
  685. }
  686. len = sprintf( (char *) buf, "%s\r\n", base );
  687. ret = write_ssl_and_get_response( &ssl, buf, len );
  688. if( ret < 200 || ret > 399 )
  689. {
  690. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  691. goto exit;
  692. }
  693. mbedtls_printf(" ok\n" );
  694. }
  695. #endif
  696. mbedtls_printf( " > Write MAIL FROM to server:" );
  697. fflush( stdout );
  698. len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from );
  699. ret = write_ssl_and_get_response( &ssl, buf, len );
  700. if( ret < 200 || ret > 299 )
  701. {
  702. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  703. goto exit;
  704. }
  705. mbedtls_printf(" ok\n" );
  706. mbedtls_printf( " > Write RCPT TO to server:" );
  707. fflush( stdout );
  708. len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to );
  709. ret = write_ssl_and_get_response( &ssl, buf, len );
  710. if( ret < 200 || ret > 299 )
  711. {
  712. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  713. goto exit;
  714. }
  715. mbedtls_printf(" ok\n" );
  716. mbedtls_printf( " > Write DATA to server:" );
  717. fflush( stdout );
  718. len = sprintf( (char *) buf, "DATA\r\n" );
  719. ret = write_ssl_and_get_response( &ssl, buf, len );
  720. if( ret < 300 || ret > 399 )
  721. {
  722. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  723. goto exit;
  724. }
  725. mbedtls_printf(" ok\n" );
  726. mbedtls_printf( " > Write content to server:" );
  727. fflush( stdout );
  728. len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n"
  729. "This is a simple test mail from the "
  730. "mbed TLS mail client example.\r\n"
  731. "\r\n"
  732. "Enjoy!", opt.mail_from );
  733. ret = write_ssl_data( &ssl, buf, len );
  734. len = sprintf( (char *) buf, "\r\n.\r\n");
  735. ret = write_ssl_and_get_response( &ssl, buf, len );
  736. if( ret < 200 || ret > 299 )
  737. {
  738. mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
  739. goto exit;
  740. }
  741. mbedtls_printf(" ok\n" );
  742. mbedtls_ssl_close_notify( &ssl );
  743. exit_code = MBEDTLS_EXIT_SUCCESS;
  744. exit:
  745. mbedtls_net_free( &server_fd );
  746. mbedtls_x509_crt_free( &clicert );
  747. mbedtls_x509_crt_free( &cacert );
  748. mbedtls_pk_free( &pkey );
  749. mbedtls_ssl_free( &ssl );
  750. mbedtls_ssl_config_free( &conf );
  751. mbedtls_ctr_drbg_free( &ctr_drbg );
  752. mbedtls_entropy_free( &entropy );
  753. #if defined(_WIN32)
  754. mbedtls_printf( " + Press Enter to exit this program.\n" );
  755. fflush( stdout ); getchar();
  756. #endif
  757. mbedtls_exit( exit_code );
  758. }
  759. #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
  760. MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C **
  761. MBEDTLS_CTR_DRBG_C */