blob: a148171d94646cf29162afa83cecc699034a68f7 [file] [log] [blame]
Paul Bakker1496d382011-05-23 12:07:29 +00001/*
2 * SSL client for SMTP servers
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2012, ARM Limited, All Rights Reserved
Paul Bakker1496d382011-05-23 12:07:29 +00005 *
Manuel Pégourié-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakker1496d382011-05-23 12:07:29 +00007 *
Paul Bakker1496d382011-05-23 12:07:29 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020023#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnardabd6e022013-09-20 13:30:43 +020024#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020025#else
26#include POLARSSL_CONFIG_FILE
27#endif
Paul Bakker1496d382011-05-23 12:07:29 +000028
Rich Evansf90016a2015-01-19 14:26:37 +000029#if defined(POLARSSL_PLATFORM_C)
30#include "polarssl/platform.h"
31#else
Rich Evans18b78c72015-02-11 14:06:19 +000032#include <stdio.h>
Rich Evansf90016a2015-01-19 14:26:37 +000033#define polarssl_fprintf fprintf
Rich Evans18b78c72015-02-11 14:06:19 +000034#define polarssl_printf printf
Rich Evansf90016a2015-01-19 14:26:37 +000035#endif
36
Rich Evans18b78c72015-02-11 14:06:19 +000037#if defined(POLARSSL_BIGNUM_C) && defined(POLARSSL_ENTROPY_C) && \
38 defined(POLARSSL_SSL_TLS_C) && defined(POLARSSL_SSL_CLI_C) && \
39 defined(POLARSSL_NET_C) && defined(POLARSSL_RSA_C) && \
40 defined(POLARSSL_CTR_DRBG_C) && defined(POLARSSL_X509_CRT_PARSE_C) && \
41 defined(POLARSSL_FS_IO)
42#include "polarssl/base64.h"
43#include "polarssl/error.h"
44#include "polarssl/net.h"
45#include "polarssl/ssl.h"
46#include "polarssl/entropy.h"
47#include "polarssl/ctr_drbg.h"
48#include "polarssl/certs.h"
49#include "polarssl/x509.h"
50
Paul Bakker1496d382011-05-23 12:07:29 +000051#include <stdio.h>
Rich Evans18b78c72015-02-11 14:06:19 +000052#include <stdlib.h>
53#include <string.h>
54#endif
Paul Bakkerfdda7852013-11-30 15:15:31 +010055
56#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32)
Paul Bakker1496d382011-05-23 12:07:29 +000057#include <unistd.h>
Paul Bakkerfdda7852013-11-30 15:15:31 +010058#else
59#include <io.h>
60#define read _read
61#define write _write
62#endif
Paul Bakker1496d382011-05-23 12:07:29 +000063
Paul Bakker5a835222011-10-12 09:19:31 +000064#if defined(_WIN32) || defined(_WIN32_WCE)
Paul Bakker5a835222011-10-12 09:19:31 +000065#include <winsock2.h>
66#include <windows.h>
67
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010068#if defined(_MSC_VER)
Paul Bakker5a835222011-10-12 09:19:31 +000069#if defined(_WIN32_WCE)
70#pragma comment( lib, "ws2.lib" )
71#else
72#pragma comment( lib, "ws2_32.lib" )
73#endif
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010074#endif /* _MSC_VER */
Paul Bakker5a835222011-10-12 09:19:31 +000075#endif
76
Paul Bakker1496d382011-05-23 12:07:29 +000077#define DFL_SERVER_NAME "localhost"
78#define DFL_SERVER_PORT 465
79#define DFL_USER_NAME "user"
80#define DFL_USER_PWD "password"
81#define DFL_MAIL_FROM ""
82#define DFL_MAIL_TO ""
83#define DFL_DEBUG_LEVEL 0
Paul Bakker5690efc2011-05-26 13:16:06 +000084#define DFL_CA_FILE ""
Paul Bakker1496d382011-05-23 12:07:29 +000085#define DFL_CRT_FILE ""
86#define DFL_KEY_FILE ""
87#define DFL_FORCE_CIPHER 0
88#define DFL_MODE 0
89#define DFL_AUTHENTICATION 0
90
91#define MODE_SSL_TLS 0
92#define MODE_STARTTLS 0
93
Rich Evans18b78c72015-02-11 14:06:19 +000094#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \
95 !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
96 !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \
97 !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
98 !defined(POLARSSL_FS_IO)
99int main( int argc, char *argv[] )
100{
101 ((void) argc);
102 ((void) argv);
103
104 polarssl_printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
105 "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
106 "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
107 "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C "
108 "not defined.\n");
109 return( 0 );
110}
111#else
Paul Bakker1496d382011-05-23 12:07:29 +0000112/*
113 * global options
114 */
115struct options
116{
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200117 const char *server_name; /* hostname of the server (client only) */
Paul Bakker1496d382011-05-23 12:07:29 +0000118 int server_port; /* port on which the ssl service runs */
119 int debug_level; /* level of debugging */
120 int authentication; /* if authentication is required */
121 int mode; /* SSL/TLS (0) or STARTTLS (1) */
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200122 const char *user_name; /* username to use for authentication */
123 const char *user_pwd; /* password to use for authentication */
124 const char *mail_from; /* E-Mail address to use as sender */
125 const char *mail_to; /* E-Mail address to use as recipient */
126 const char *ca_file; /* the file with the CA certificate(s) */
127 const char *crt_file; /* the file with the client certificate */
128 const char *key_file; /* the file with the client key */
Paul Bakker1496d382011-05-23 12:07:29 +0000129 int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
130} opt;
131
Paul Bakker3c5ef712013-06-25 16:37:45 +0200132static void my_debug( void *ctx, int level, const char *str )
Paul Bakker1496d382011-05-23 12:07:29 +0000133{
134 if( level < opt.debug_level )
135 {
Rich Evansf90016a2015-01-19 14:26:37 +0000136 polarssl_fprintf( (FILE *) ctx, "%s", str );
Paul Bakker1496d382011-05-23 12:07:29 +0000137 fflush( (FILE *) ctx );
138 }
139}
140
Paul Bakker3c5ef712013-06-25 16:37:45 +0200141static int do_handshake( ssl_context *ssl, struct options *opt )
Paul Bakker1496d382011-05-23 12:07:29 +0000142{
143 int ret;
144 unsigned char buf[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000145 memset(buf, 0, 1024);
Paul Bakker1496d382011-05-23 12:07:29 +0000146
147 /*
148 * 4. Handshake
149 */
Rich Evansf90016a2015-01-19 14:26:37 +0000150 polarssl_printf( " . Performing the SSL/TLS handshake..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000151 fflush( stdout );
152
153 while( ( ret = ssl_handshake( ssl ) ) != 0 )
154 {
155 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
156 {
Paul Bakker5690efc2011-05-26 13:16:06 +0000157#if defined(POLARSSL_ERROR_C)
Paul Bakker03a8a792013-06-30 12:18:08 +0200158 polarssl_strerror( ret, (char *) buf, 1024 );
Paul Bakker5690efc2011-05-26 13:16:06 +0000159#endif
Rich Evansf90016a2015-01-19 14:26:37 +0000160 polarssl_printf( " failed\n ! ssl_handshake returned %d: %s\n\n", ret, buf );
Paul Bakker1496d382011-05-23 12:07:29 +0000161 return( -1 );
162 }
163 }
164
Rich Evansf90016a2015-01-19 14:26:37 +0000165 polarssl_printf( " ok\n [ Ciphersuite is %s ]\n",
Paul Bakker1496d382011-05-23 12:07:29 +0000166 ssl_get_ciphersuite( ssl ) );
167
168 /*
169 * 5. Verify the server certificate
170 */
Rich Evansf90016a2015-01-19 14:26:37 +0000171 polarssl_printf( " . Verifying peer X.509 certificate..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000172
Manuel Pégourié-Gonnardfcf2fc22014-03-11 11:10:27 +0100173 /* In real life, we may want to bail out when ret != 0 */
Paul Bakker1496d382011-05-23 12:07:29 +0000174 if( ( ret = ssl_get_verify_result( ssl ) ) != 0 )
175 {
Rich Evansf90016a2015-01-19 14:26:37 +0000176 polarssl_printf( " failed\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000177
178 if( ( ret & BADCERT_EXPIRED ) != 0 )
Rich Evansf90016a2015-01-19 14:26:37 +0000179 polarssl_printf( " ! server certificate has expired\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000180
181 if( ( ret & BADCERT_REVOKED ) != 0 )
Rich Evansf90016a2015-01-19 14:26:37 +0000182 polarssl_printf( " ! server certificate has been revoked\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000183
184 if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
Rich Evansf90016a2015-01-19 14:26:37 +0000185 polarssl_printf( " ! CN mismatch (expected CN=%s)\n", opt->server_name );
Paul Bakker1496d382011-05-23 12:07:29 +0000186
187 if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
Rich Evansf90016a2015-01-19 14:26:37 +0000188 polarssl_printf( " ! self-signed or not signed by a trusted CA\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000189
Rich Evansf90016a2015-01-19 14:26:37 +0000190 polarssl_printf( "\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000191 }
192 else
Rich Evansf90016a2015-01-19 14:26:37 +0000193 polarssl_printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000194
Rich Evansf90016a2015-01-19 14:26:37 +0000195 polarssl_printf( " . Peer certificate information ...\n" );
Paul Bakkerddf26b42013-09-18 13:46:23 +0200196 x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
197 ssl_get_peer_cert( ssl ) );
Rich Evansf90016a2015-01-19 14:26:37 +0000198 polarssl_printf( "%s\n", buf );
Paul Bakker1496d382011-05-23 12:07:29 +0000199
200 return( 0 );
201}
202
Paul Bakker3c5ef712013-06-25 16:37:45 +0200203static int write_ssl_data( ssl_context *ssl, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000204{
205 int ret;
206
Rich Evansf90016a2015-01-19 14:26:37 +0000207 polarssl_printf("\n%s", buf);
Paul Bakker1496d382011-05-23 12:07:29 +0000208 while( len && ( ret = ssl_write( ssl, buf, len ) ) <= 0 )
209 {
210 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
211 {
Rich Evansf90016a2015-01-19 14:26:37 +0000212 polarssl_printf( " failed\n ! ssl_write returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000213 return -1;
214 }
215 }
216
217 return( 0 );
218}
219
Paul Bakker3c5ef712013-06-25 16:37:45 +0200220static int write_ssl_and_get_response( ssl_context *ssl, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000221{
222 int ret;
223 unsigned char data[128];
224 char code[4];
225 size_t i, idx = 0;
226
Rich Evansf90016a2015-01-19 14:26:37 +0000227 polarssl_printf("\n%s", buf);
Paul Bakker1496d382011-05-23 12:07:29 +0000228 while( len && ( ret = ssl_write( ssl, buf, len ) ) <= 0 )
229 {
230 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
231 {
Rich Evansf90016a2015-01-19 14:26:37 +0000232 polarssl_printf( " failed\n ! ssl_write returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000233 return -1;
234 }
235 }
236
237 do
238 {
239 len = sizeof( data ) - 1;
240 memset( data, 0, sizeof( data ) );
241 ret = ssl_read( ssl, data, len );
242
243 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
244 continue;
245
246 if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
247 return -1;
248
249 if( ret <= 0 )
250 {
Rich Evansf90016a2015-01-19 14:26:37 +0000251 polarssl_printf( "failed\n ! ssl_read returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000252 return -1;
253 }
254
Rich Evansf90016a2015-01-19 14:26:37 +0000255 polarssl_printf("\n%s", data);
Paul Bakker1496d382011-05-23 12:07:29 +0000256 len = ret;
257 for( i = 0; i < len; i++ )
258 {
259 if( data[i] != '\n' )
260 {
261 if( idx < 4 )
262 code[ idx++ ] = data[i];
263 continue;
264 }
265
266 if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
267 {
268 code[3] = '\0';
269 return atoi( code );
270 }
Paul Bakker3c5ef712013-06-25 16:37:45 +0200271
Paul Bakker1496d382011-05-23 12:07:29 +0000272 idx = 0;
273 }
274 }
275 while( 1 );
276}
277
Paul Bakker3c5ef712013-06-25 16:37:45 +0200278static int write_and_get_response( int sock_fd, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000279{
280 int ret;
281 unsigned char data[128];
282 char code[4];
283 size_t i, idx = 0;
284
Rich Evansf90016a2015-01-19 14:26:37 +0000285 polarssl_printf("\n%s", buf);
Paul Bakker1496d382011-05-23 12:07:29 +0000286 if( len && ( ret = write( sock_fd, buf, len ) ) <= 0 )
287 {
Rich Evansf90016a2015-01-19 14:26:37 +0000288 polarssl_printf( " failed\n ! ssl_write returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000289 return -1;
290 }
291
292 do
293 {
294 len = sizeof( data ) - 1;
295 memset( data, 0, sizeof( data ) );
296 ret = read( sock_fd, data, len );
297
298 if( ret <= 0 )
299 {
Rich Evansf90016a2015-01-19 14:26:37 +0000300 polarssl_printf( "failed\n ! read returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000301 return -1;
302 }
303
Paul Bakkerdf71dd12014-04-17 16:03:48 +0200304 data[len] = '\0';
Rich Evansf90016a2015-01-19 14:26:37 +0000305 polarssl_printf("\n%s", data);
Paul Bakker1496d382011-05-23 12:07:29 +0000306 len = ret;
307 for( i = 0; i < len; i++ )
308 {
309 if( data[i] != '\n' )
310 {
311 if( idx < 4 )
312 code[ idx++ ] = data[i];
313 continue;
314 }
315
316 if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
317 {
318 code[3] = '\0';
319 return atoi( code );
320 }
321
322 idx = 0;
323 }
324 }
325 while( 1 );
326}
327
Paul Bakker5690efc2011-05-26 13:16:06 +0000328#if defined(POLARSSL_BASE64_C)
329#define USAGE_AUTH \
330 " authentication=%%d default: 0 (disabled)\n" \
331 " user_name=%%s default: \"user\"\n" \
332 " user_pwd=%%s default: \"password\"\n"
333#else
334#define USAGE_AUTH \
335 " authentication options disabled. (Require POLARSSL_BASE64_C)\n"
336#endif /* POLARSSL_BASE64_C */
337
338#if defined(POLARSSL_FS_IO)
339#define USAGE_IO \
340 " ca_file=%%s default: \"\" (pre-loaded)\n" \
341 " crt_file=%%s default: \"\" (pre-loaded)\n" \
342 " key_file=%%s default: \"\" (pre-loaded)\n"
343#else
344#define USAGE_IO \
345 " No file operations available (POLARSSL_FS_IO not defined)\n"
346#endif /* POLARSSL_FS_IO */
347
Paul Bakker1496d382011-05-23 12:07:29 +0000348#define USAGE \
349 "\n usage: ssl_mail_client param=<>...\n" \
350 "\n acceptable parameters:\n" \
351 " server_name=%%s default: localhost\n" \
352 " server_port=%%d default: 4433\n" \
353 " debug_level=%%d default: 0 (disabled)\n" \
Paul Bakker1496d382011-05-23 12:07:29 +0000354 " mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \
Paul Bakker5690efc2011-05-26 13:16:06 +0000355 USAGE_AUTH \
Paul Bakker1496d382011-05-23 12:07:29 +0000356 " mail_from=%%s default: \"\"\n" \
357 " mail_to=%%s default: \"\"\n" \
Paul Bakker5690efc2011-05-26 13:16:06 +0000358 USAGE_IO \
Paul Bakker1496d382011-05-23 12:07:29 +0000359 " force_ciphersuite=<name> default: all enabled\n"\
360 " acceptable ciphersuite names:\n"
361
362int main( int argc, char *argv[] )
363{
364 int ret = 0, len, server_fd;
Paul Bakker09c9dd82014-08-18 11:06:56 +0200365 unsigned char buf[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000366#if defined(POLARSSL_BASE64_C)
Paul Bakker1496d382011-05-23 12:07:29 +0000367 unsigned char base[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000368#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000369 char hostname[32];
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200370 const char *pers = "ssl_mail_client";
Paul Bakker508ad5a2011-12-04 17:09:26 +0000371
372 entropy_context entropy;
373 ctr_drbg_context ctr_drbg;
Paul Bakker1496d382011-05-23 12:07:29 +0000374 ssl_context ssl;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200375 x509_crt cacert;
376 x509_crt clicert;
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200377 pk_context pkey;
Paul Bakker1496d382011-05-23 12:07:29 +0000378 int i;
Paul Bakker819370c2012-09-28 07:04:41 +0000379 size_t n;
Paul Bakker1496d382011-05-23 12:07:29 +0000380 char *p, *q;
381 const int *list;
382
383 /*
Manuel Pégourié-Gonnard3bd2aae2013-09-20 13:10:13 +0200384 * Make sure memory references are valid in case we exit early.
Paul Bakker1496d382011-05-23 12:07:29 +0000385 */
386 server_fd = 0;
Manuel Pégourié-Gonnard3bd2aae2013-09-20 13:10:13 +0200387 memset( &ssl, 0, sizeof( ssl_context ) );
Paul Bakker333fdec2014-08-04 12:12:09 +0200388 memset( &buf, 0, sizeof( buf ) );
Paul Bakker369d2eb2013-09-18 11:58:25 +0200389 x509_crt_init( &cacert );
390 x509_crt_init( &clicert );
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200391 pk_init( &pkey );
Paul Bakker1496d382011-05-23 12:07:29 +0000392
393 if( argc == 0 )
394 {
395 usage:
Rich Evansf90016a2015-01-19 14:26:37 +0000396 polarssl_printf( USAGE );
Paul Bakker1496d382011-05-23 12:07:29 +0000397
398 list = ssl_list_ciphersuites();
399 while( *list )
400 {
Rich Evansf90016a2015-01-19 14:26:37 +0000401 polarssl_printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
Paul Bakker1496d382011-05-23 12:07:29 +0000402 list++;
403 }
Rich Evansf90016a2015-01-19 14:26:37 +0000404 polarssl_printf("\n");
Paul Bakker1496d382011-05-23 12:07:29 +0000405 goto exit;
406 }
407
408 opt.server_name = DFL_SERVER_NAME;
409 opt.server_port = DFL_SERVER_PORT;
410 opt.debug_level = DFL_DEBUG_LEVEL;
411 opt.authentication = DFL_AUTHENTICATION;
412 opt.mode = DFL_MODE;
413 opt.user_name = DFL_USER_NAME;
414 opt.user_pwd = DFL_USER_PWD;
415 opt.mail_from = DFL_MAIL_FROM;
416 opt.mail_to = DFL_MAIL_TO;
Paul Bakker5690efc2011-05-26 13:16:06 +0000417 opt.ca_file = DFL_CA_FILE;
Paul Bakker1496d382011-05-23 12:07:29 +0000418 opt.crt_file = DFL_CRT_FILE;
419 opt.key_file = DFL_KEY_FILE;
420 opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
421
422 for( i = 1; i < argc; i++ )
423 {
Paul Bakker1496d382011-05-23 12:07:29 +0000424 p = argv[i];
425 if( ( q = strchr( p, '=' ) ) == NULL )
426 goto usage;
427 *q++ = '\0';
428
429 if( strcmp( p, "server_name" ) == 0 )
430 opt.server_name = q;
431 else if( strcmp( p, "server_port" ) == 0 )
432 {
433 opt.server_port = atoi( q );
434 if( opt.server_port < 1 || opt.server_port > 65535 )
435 goto usage;
436 }
437 else if( strcmp( p, "debug_level" ) == 0 )
438 {
439 opt.debug_level = atoi( q );
440 if( opt.debug_level < 0 || opt.debug_level > 65535 )
441 goto usage;
442 }
443 else if( strcmp( p, "authentication" ) == 0 )
444 {
445 opt.authentication = atoi( q );
446 if( opt.authentication < 0 || opt.authentication > 1 )
447 goto usage;
448 }
449 else if( strcmp( p, "mode" ) == 0 )
450 {
451 opt.mode = atoi( q );
452 if( opt.mode < 0 || opt.mode > 1 )
453 goto usage;
454 }
455 else if( strcmp( p, "user_name" ) == 0 )
456 opt.user_name = q;
457 else if( strcmp( p, "user_pwd" ) == 0 )
458 opt.user_pwd = q;
459 else if( strcmp( p, "mail_from" ) == 0 )
460 opt.mail_from = q;
461 else if( strcmp( p, "mail_to" ) == 0 )
462 opt.mail_to = q;
Paul Bakker5690efc2011-05-26 13:16:06 +0000463 else if( strcmp( p, "ca_file" ) == 0 )
464 opt.ca_file = q;
Paul Bakker1496d382011-05-23 12:07:29 +0000465 else if( strcmp( p, "crt_file" ) == 0 )
466 opt.crt_file = q;
467 else if( strcmp( p, "key_file" ) == 0 )
468 opt.key_file = q;
469 else if( strcmp( p, "force_ciphersuite" ) == 0 )
470 {
471 opt.force_ciphersuite[0] = -1;
472
473 opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
474
475 if( opt.force_ciphersuite[0] <= 0 )
476 goto usage;
477
478 opt.force_ciphersuite[1] = 0;
479 }
480 else
481 goto usage;
482 }
483
484 /*
485 * 0. Initialize the RNG and the session data
486 */
Rich Evansf90016a2015-01-19 14:26:37 +0000487 polarssl_printf( "\n . Seeding the random number generator..." );
Paul Bakker508ad5a2011-12-04 17:09:26 +0000488 fflush( stdout );
489
490 entropy_init( &entropy );
491 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200492 (const unsigned char *) pers,
493 strlen( pers ) ) ) != 0 )
Paul Bakker508ad5a2011-12-04 17:09:26 +0000494 {
Rich Evansf90016a2015-01-19 14:26:37 +0000495 polarssl_printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
Paul Bakker508ad5a2011-12-04 17:09:26 +0000496 goto exit;
497 }
498
Rich Evansf90016a2015-01-19 14:26:37 +0000499 polarssl_printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000500
501 /*
502 * 1.1. Load the trusted CA
503 */
Rich Evansf90016a2015-01-19 14:26:37 +0000504 polarssl_printf( " . Loading the CA root certificate ..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000505 fflush( stdout );
506
Paul Bakker5690efc2011-05-26 13:16:06 +0000507#if defined(POLARSSL_FS_IO)
508 if( strlen( opt.ca_file ) )
Paul Bakkerddf26b42013-09-18 13:46:23 +0200509 ret = x509_crt_parse_file( &cacert, opt.ca_file );
Paul Bakker5690efc2011-05-26 13:16:06 +0000510 else
511#endif
512#if defined(POLARSSL_CERTS_C)
Manuel Pégourié-Gonnard641de712013-09-25 13:23:33 +0200513 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_list,
514 strlen( test_ca_list ) );
Paul Bakker5690efc2011-05-26 13:16:06 +0000515#else
516 {
517 ret = 1;
Rich Evansf90016a2015-01-19 14:26:37 +0000518 polarssl_printf("POLARSSL_CERTS_C not defined.");
Paul Bakker5690efc2011-05-26 13:16:06 +0000519 }
520#endif
Paul Bakker42488232012-05-16 08:21:05 +0000521 if( ret < 0 )
Paul Bakker1496d382011-05-23 12:07:29 +0000522 {
Rich Evansf90016a2015-01-19 14:26:37 +0000523 polarssl_printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000524 goto exit;
525 }
526
Rich Evansf90016a2015-01-19 14:26:37 +0000527 polarssl_printf( " ok (%d skipped)\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000528
529 /*
530 * 1.2. Load own certificate and private key
531 *
532 * (can be skipped if client authentication is not required)
533 */
Rich Evansf90016a2015-01-19 14:26:37 +0000534 polarssl_printf( " . Loading the client cert. and key..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000535 fflush( stdout );
536
Paul Bakker5690efc2011-05-26 13:16:06 +0000537#if defined(POLARSSL_FS_IO)
Paul Bakker1496d382011-05-23 12:07:29 +0000538 if( strlen( opt.crt_file ) )
Paul Bakkerddf26b42013-09-18 13:46:23 +0200539 ret = x509_crt_parse_file( &clicert, opt.crt_file );
540 else
Paul Bakker5690efc2011-05-26 13:16:06 +0000541#endif
542#if defined(POLARSSL_CERTS_C)
Paul Bakkerddf26b42013-09-18 13:46:23 +0200543 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
544 strlen( test_cli_crt ) );
Paul Bakker5690efc2011-05-26 13:16:06 +0000545#else
546 {
Paul Bakker69e095c2011-12-10 21:55:01 +0000547 ret = -1;
Rich Evansf90016a2015-01-19 14:26:37 +0000548 polarssl_printf("POLARSSL_CERTS_C not defined.");
Paul Bakker5690efc2011-05-26 13:16:06 +0000549 }
550#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000551 if( ret != 0 )
552 {
Rich Evansf90016a2015-01-19 14:26:37 +0000553 polarssl_printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000554 goto exit;
555 }
556
Paul Bakker5690efc2011-05-26 13:16:06 +0000557#if defined(POLARSSL_FS_IO)
Paul Bakker1496d382011-05-23 12:07:29 +0000558 if( strlen( opt.key_file ) )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200559 ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
Paul Bakker1496d382011-05-23 12:07:29 +0000560 else
Paul Bakker5690efc2011-05-26 13:16:06 +0000561#endif
562#if defined(POLARSSL_CERTS_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200563 ret = pk_parse_key( &pkey, (const unsigned char *) test_cli_key,
Paul Bakker1496d382011-05-23 12:07:29 +0000564 strlen( test_cli_key ), NULL, 0 );
Paul Bakker5690efc2011-05-26 13:16:06 +0000565#else
566 {
Paul Bakker69e095c2011-12-10 21:55:01 +0000567 ret = -1;
Rich Evansf90016a2015-01-19 14:26:37 +0000568 polarssl_printf("POLARSSL_CERTS_C not defined.");
Paul Bakker5690efc2011-05-26 13:16:06 +0000569 }
570#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000571 if( ret != 0 )
572 {
Rich Evansf90016a2015-01-19 14:26:37 +0000573 polarssl_printf( " failed\n ! pk_parse_key returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000574 goto exit;
575 }
576
Rich Evansf90016a2015-01-19 14:26:37 +0000577 polarssl_printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000578
579 /*
580 * 2. Start the connection
581 */
Rich Evansf90016a2015-01-19 14:26:37 +0000582 polarssl_printf( " . Connecting to tcp/%s/%-4d...", opt.server_name,
Paul Bakker1496d382011-05-23 12:07:29 +0000583 opt.server_port );
584 fflush( stdout );
585
586 if( ( ret = net_connect( &server_fd, opt.server_name,
587 opt.server_port ) ) != 0 )
588 {
Rich Evansf90016a2015-01-19 14:26:37 +0000589 polarssl_printf( " failed\n ! net_connect returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000590 goto exit;
591 }
592
Rich Evansf90016a2015-01-19 14:26:37 +0000593 polarssl_printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000594
595 /*
596 * 3. Setup stuff
597 */
Rich Evansf90016a2015-01-19 14:26:37 +0000598 polarssl_printf( " . Setting up the SSL/TLS structure..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000599 fflush( stdout );
600
Paul Bakker1496d382011-05-23 12:07:29 +0000601 if( ( ret = ssl_init( &ssl ) ) != 0 )
602 {
Rich Evansf90016a2015-01-19 14:26:37 +0000603 polarssl_printf( " failed\n ! ssl_init returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000604 goto exit;
605 }
606
Rich Evansf90016a2015-01-19 14:26:37 +0000607 polarssl_printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000608
609 ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
Manuel Pégourié-Gonnardfcf2fc22014-03-11 11:10:27 +0100610 /* OPTIONAL is not optimal for security,
611 * but makes interop easier in this simplified example */
Paul Bakker1496d382011-05-23 12:07:29 +0000612 ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );
613
Manuel Pégourié-Gonnard448ea502015-01-12 11:40:14 +0100614 /* SSLv3 is deprecated, set minimum to TLS 1.0 */
615 ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1 );
Manuel Pégourié-Gonnardfa065812015-01-12 14:05:33 +0100616 /* RC4 is deprecated, disable it */
617 ssl_set_arc4_support( &ssl, SSL_ARC4_DISABLED );
Manuel Pégourié-Gonnard448ea502015-01-12 11:40:14 +0100618
Paul Bakker508ad5a2011-12-04 17:09:26 +0000619 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
Paul Bakker1496d382011-05-23 12:07:29 +0000620 ssl_set_dbg( &ssl, my_debug, stdout );
621 ssl_set_bio( &ssl, net_recv, &server_fd,
622 net_send, &server_fd );
623
Paul Bakker645ce3a2012-10-31 12:32:41 +0000624 if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
Paul Bakker1496d382011-05-23 12:07:29 +0000625 ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
626
Paul Bakker1496d382011-05-23 12:07:29 +0000627 ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
Manuel Pégourié-Gonnardc5fd3912014-07-08 14:05:52 +0200628 if( ( ret = ssl_set_own_cert( &ssl, &clicert, &pkey ) ) != 0 )
629 {
Rich Evansf90016a2015-01-19 14:26:37 +0000630 polarssl_printf( " failed\n ! ssl_set_own_cert returned %d\n\n", ret );
Manuel Pégourié-Gonnardc5fd3912014-07-08 14:05:52 +0200631 goto exit;
632 }
Paul Bakker1496d382011-05-23 12:07:29 +0000633
Paul Bakker0be444a2013-08-27 21:55:01 +0200634#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
Manuel Pégourié-Gonnardc5fd3912014-07-08 14:05:52 +0200635 if( ( ret = ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
636 {
Rich Evansf90016a2015-01-19 14:26:37 +0000637 polarssl_printf( " failed\n ! ssl_set_hostname returned %d\n\n", ret );
Manuel Pégourié-Gonnardc5fd3912014-07-08 14:05:52 +0200638 goto exit;
639 }
Paul Bakker0be444a2013-08-27 21:55:01 +0200640#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000641
642 if( opt.mode == MODE_SSL_TLS )
643 {
644 if( do_handshake( &ssl, &opt ) != 0 )
645 goto exit;
646
Rich Evansf90016a2015-01-19 14:26:37 +0000647 polarssl_printf( " > Get header from server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000648 fflush( stdout );
649
650 ret = write_ssl_and_get_response( &ssl, buf, 0 );
651 if( ret < 200 || ret > 299 )
652 {
Rich Evansf90016a2015-01-19 14:26:37 +0000653 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000654 goto exit;
655 }
656
Rich Evansf90016a2015-01-19 14:26:37 +0000657 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000658
Rich Evansf90016a2015-01-19 14:26:37 +0000659 polarssl_printf( " > Write EHLO to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000660 fflush( stdout );
661
662 gethostname( hostname, 32 );
Paul Bakkerd75ba402014-01-24 16:11:17 +0100663 len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
Paul Bakker1496d382011-05-23 12:07:29 +0000664 ret = write_ssl_and_get_response( &ssl, buf, len );
665 if( ret < 200 || ret > 299 )
666 {
Rich Evansf90016a2015-01-19 14:26:37 +0000667 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000668 goto exit;
669 }
670 }
671 else
672 {
Rich Evansf90016a2015-01-19 14:26:37 +0000673 polarssl_printf( " > Get header from server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000674 fflush( stdout );
675
676 ret = write_and_get_response( server_fd, buf, 0 );
677 if( ret < 200 || ret > 299 )
678 {
Rich Evansf90016a2015-01-19 14:26:37 +0000679 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000680 goto exit;
681 }
682
Rich Evansf90016a2015-01-19 14:26:37 +0000683 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000684
Rich Evansf90016a2015-01-19 14:26:37 +0000685 polarssl_printf( " > Write EHLO to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000686 fflush( stdout );
687
688 gethostname( hostname, 32 );
Paul Bakkerd75ba402014-01-24 16:11:17 +0100689 len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
Paul Bakker1496d382011-05-23 12:07:29 +0000690 ret = write_and_get_response( server_fd, buf, len );
691 if( ret < 200 || ret > 299 )
692 {
Rich Evansf90016a2015-01-19 14:26:37 +0000693 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000694 goto exit;
695 }
696
Rich Evansf90016a2015-01-19 14:26:37 +0000697 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000698
Rich Evansf90016a2015-01-19 14:26:37 +0000699 polarssl_printf( " > Write STARTTLS to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000700 fflush( stdout );
701
702 gethostname( hostname, 32 );
Paul Bakkerd75ba402014-01-24 16:11:17 +0100703 len = sprintf( (char *) buf, "STARTTLS\r\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000704 ret = write_and_get_response( server_fd, buf, len );
705 if( ret < 200 || ret > 299 )
706 {
Rich Evansf90016a2015-01-19 14:26:37 +0000707 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000708 goto exit;
709 }
710
Rich Evansf90016a2015-01-19 14:26:37 +0000711 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000712
713 if( do_handshake( &ssl, &opt ) != 0 )
714 goto exit;
715 }
716
Paul Bakker5690efc2011-05-26 13:16:06 +0000717#if defined(POLARSSL_BASE64_C)
Paul Bakker1496d382011-05-23 12:07:29 +0000718 if( opt.authentication )
719 {
Rich Evansf90016a2015-01-19 14:26:37 +0000720 polarssl_printf( " > Write AUTH LOGIN to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000721 fflush( stdout );
722
Paul Bakkerd75ba402014-01-24 16:11:17 +0100723 len = sprintf( (char *) buf, "AUTH LOGIN\r\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000724 ret = write_ssl_and_get_response( &ssl, buf, len );
725 if( ret < 200 || ret > 399 )
726 {
Rich Evansf90016a2015-01-19 14:26:37 +0000727 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000728 goto exit;
729 }
730
Rich Evansf90016a2015-01-19 14:26:37 +0000731 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000732
Rich Evansf90016a2015-01-19 14:26:37 +0000733 polarssl_printf( " > Write username to server: %s", opt.user_name );
Paul Bakker1496d382011-05-23 12:07:29 +0000734 fflush( stdout );
735
736 n = sizeof( buf );
Alfred Klomp7c034242014-07-14 22:11:13 +0200737 ret = base64_encode( base, &n, (const unsigned char *) opt.user_name,
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200738 strlen( opt.user_name ) );
Alfred Klomp7c034242014-07-14 22:11:13 +0200739
740 if( ret != 0 ) {
Rich Evansf90016a2015-01-19 14:26:37 +0000741 polarssl_printf( " failed\n ! base64_encode returned %d\n\n", ret );
Alfred Klomp7c034242014-07-14 22:11:13 +0200742 goto exit;
743 }
Paul Bakkerd75ba402014-01-24 16:11:17 +0100744 len = sprintf( (char *) buf, "%s\r\n", base );
Paul Bakker1496d382011-05-23 12:07:29 +0000745 ret = write_ssl_and_get_response( &ssl, buf, len );
746 if( ret < 300 || ret > 399 )
747 {
Rich Evansf90016a2015-01-19 14:26:37 +0000748 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000749 goto exit;
750 }
751
Rich Evansf90016a2015-01-19 14:26:37 +0000752 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000753
Rich Evansf90016a2015-01-19 14:26:37 +0000754 polarssl_printf( " > Write password to server: %s", opt.user_pwd );
Paul Bakker1496d382011-05-23 12:07:29 +0000755 fflush( stdout );
756
Alfred Klomp7c034242014-07-14 22:11:13 +0200757 ret = base64_encode( base, &n, (const unsigned char *) opt.user_pwd,
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200758 strlen( opt.user_pwd ) );
Alfred Klomp7c034242014-07-14 22:11:13 +0200759
760 if( ret != 0 ) {
Rich Evansf90016a2015-01-19 14:26:37 +0000761 polarssl_printf( " failed\n ! base64_encode returned %d\n\n", ret );
Alfred Klomp7c034242014-07-14 22:11:13 +0200762 goto exit;
763 }
Paul Bakkerd75ba402014-01-24 16:11:17 +0100764 len = sprintf( (char *) buf, "%s\r\n", base );
Paul Bakker1496d382011-05-23 12:07:29 +0000765 ret = write_ssl_and_get_response( &ssl, buf, len );
766 if( ret < 200 || ret > 399 )
767 {
Rich Evansf90016a2015-01-19 14:26:37 +0000768 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000769 goto exit;
770 }
771
Rich Evansf90016a2015-01-19 14:26:37 +0000772 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000773 }
Paul Bakker5690efc2011-05-26 13:16:06 +0000774#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000775
Rich Evansf90016a2015-01-19 14:26:37 +0000776 polarssl_printf( " > Write MAIL FROM to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000777 fflush( stdout );
778
Paul Bakkerd75ba402014-01-24 16:11:17 +0100779 len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from );
Paul Bakker1496d382011-05-23 12:07:29 +0000780 ret = write_ssl_and_get_response( &ssl, buf, len );
781 if( ret < 200 || ret > 299 )
782 {
Rich Evansf90016a2015-01-19 14:26:37 +0000783 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000784 goto exit;
785 }
786
Rich Evansf90016a2015-01-19 14:26:37 +0000787 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000788
Rich Evansf90016a2015-01-19 14:26:37 +0000789 polarssl_printf( " > Write RCPT TO to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000790 fflush( stdout );
791
Paul Bakkerd75ba402014-01-24 16:11:17 +0100792 len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to );
Paul Bakker1496d382011-05-23 12:07:29 +0000793 ret = write_ssl_and_get_response( &ssl, buf, len );
794 if( ret < 200 || ret > 299 )
795 {
Rich Evansf90016a2015-01-19 14:26:37 +0000796 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000797 goto exit;
798 }
799
Rich Evansf90016a2015-01-19 14:26:37 +0000800 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000801
Rich Evansf90016a2015-01-19 14:26:37 +0000802 polarssl_printf( " > Write DATA to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000803 fflush( stdout );
804
Paul Bakkerd75ba402014-01-24 16:11:17 +0100805 len = sprintf( (char *) buf, "DATA\r\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000806 ret = write_ssl_and_get_response( &ssl, buf, len );
807 if( ret < 300 || ret > 399 )
808 {
Rich Evansf90016a2015-01-19 14:26:37 +0000809 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000810 goto exit;
811 }
812
Rich Evansf90016a2015-01-19 14:26:37 +0000813 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000814
Rich Evansf90016a2015-01-19 14:26:37 +0000815 polarssl_printf( " > Write content to server:" );
Paul Bakker1496d382011-05-23 12:07:29 +0000816 fflush( stdout );
817
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +0000818 len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n"
Paul Bakker1496d382011-05-23 12:07:29 +0000819 "This is a simple test mail from the "
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +0000820 "mbed TLS mail client example.\r\n"
Paul Bakkerd75ba402014-01-24 16:11:17 +0100821 "\r\n"
Paul Bakker1496d382011-05-23 12:07:29 +0000822 "Enjoy!", opt.mail_from );
823 ret = write_ssl_data( &ssl, buf, len );
824
825 len = sprintf( (char *) buf, "\r\n.\r\n");
826 ret = write_ssl_and_get_response( &ssl, buf, len );
827 if( ret < 200 || ret > 299 )
828 {
Rich Evansf90016a2015-01-19 14:26:37 +0000829 polarssl_printf( " failed\n ! server responded with %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000830 goto exit;
831 }
832
Rich Evansf90016a2015-01-19 14:26:37 +0000833 polarssl_printf(" ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000834
835 ssl_close_notify( &ssl );
836
837exit:
838
839 if( server_fd )
840 net_close( server_fd );
Paul Bakker36713e82013-09-17 13:25:29 +0200841 x509_crt_free( &clicert );
842 x509_crt_free( &cacert );
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200843 pk_free( &pkey );
Paul Bakker1496d382011-05-23 12:07:29 +0000844 ssl_free( &ssl );
Paul Bakkera317a982014-06-18 16:44:11 +0200845 ctr_drbg_free( &ctr_drbg );
Paul Bakker1ffefac2013-09-28 15:23:03 +0200846 entropy_free( &entropy );
Paul Bakker1496d382011-05-23 12:07:29 +0000847
Paul Bakkercce9d772011-11-18 14:26:47 +0000848#if defined(_WIN32)
Rich Evansf90016a2015-01-19 14:26:37 +0000849 polarssl_printf( " + Press Enter to exit this program.\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000850 fflush( stdout ); getchar();
851#endif
852
853 return( ret );
854}
Paul Bakker508ad5a2011-12-04 17:09:26 +0000855#endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_SSL_TLS_C &&
856 POLARSSL_SSL_CLI_C && POLARSSL_NET_C && POLARSSL_RSA_C **
857 POLARSSL_CTR_DRBG_C */