blob: a3e9f2b98606b0620617aa44866d9c764c3d1764 [file] [log] [blame]
Paul Bakker1496d382011-05-23 12:07:29 +00001/*
2 * SSL client for SMTP servers
3 *
Paul Bakker3c5ef712013-06-25 16:37:45 +02004 * Copyright (C) 2006-2012, Brainspark B.V.
Paul Bakker1496d382011-05-23 12:07:29 +00005 *
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
Manuel Pégourié-Gonnardabd6e022013-09-20 13:30:43 +020026#include "polarssl/config.h"
Paul Bakker1496d382011-05-23 12:07:29 +000027
28#include <string.h>
29#include <stdlib.h>
30#include <stdio.h>
Paul Bakkerfdda7852013-11-30 15:15:31 +010031
32#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32)
Paul Bakker1496d382011-05-23 12:07:29 +000033#include <unistd.h>
Paul Bakkerfdda7852013-11-30 15:15:31 +010034#else
35#include <io.h>
36#define read _read
37#define write _write
38#endif
Paul Bakker1496d382011-05-23 12:07:29 +000039
Paul Bakker5a835222011-10-12 09:19:31 +000040#if defined(_WIN32) || defined(_WIN32_WCE)
41
42#include <winsock2.h>
43#include <windows.h>
44
45#if defined(_WIN32_WCE)
46#pragma comment( lib, "ws2.lib" )
47#else
48#pragma comment( lib, "ws2_32.lib" )
49#endif
50#endif
51
Paul Bakker1496d382011-05-23 12:07:29 +000052#include "polarssl/base64.h"
53#include "polarssl/error.h"
54#include "polarssl/net.h"
55#include "polarssl/ssl.h"
Paul Bakker508ad5a2011-12-04 17:09:26 +000056#include "polarssl/entropy.h"
57#include "polarssl/ctr_drbg.h"
Paul Bakker1496d382011-05-23 12:07:29 +000058#include "polarssl/certs.h"
59#include "polarssl/x509.h"
60
Paul Bakker9a97c5d2013-09-15 17:07:33 +020061#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \
62 !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
63 !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \
Paul Bakker36713e82013-09-17 13:25:29 +020064 !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_CRT_PARSE_C)
Paul Bakker9a97c5d2013-09-15 17:07:33 +020065int main( int argc, char *argv[] )
66{
67 ((void) argc);
68 ((void) argv);
69
70 printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
71 "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
72 "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
Paul Bakker36713e82013-09-17 13:25:29 +020073 "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C "
Paul Bakker9a97c5d2013-09-15 17:07:33 +020074 "not defined.\n");
75 return( 0 );
76}
77#else
78
Paul Bakker1496d382011-05-23 12:07:29 +000079#define DFL_SERVER_NAME "localhost"
80#define DFL_SERVER_PORT 465
81#define DFL_USER_NAME "user"
82#define DFL_USER_PWD "password"
83#define DFL_MAIL_FROM ""
84#define DFL_MAIL_TO ""
85#define DFL_DEBUG_LEVEL 0
Paul Bakker5690efc2011-05-26 13:16:06 +000086#define DFL_CA_FILE ""
Paul Bakker1496d382011-05-23 12:07:29 +000087#define DFL_CRT_FILE ""
88#define DFL_KEY_FILE ""
89#define DFL_FORCE_CIPHER 0
90#define DFL_MODE 0
91#define DFL_AUTHENTICATION 0
92
93#define MODE_SSL_TLS 0
94#define MODE_STARTTLS 0
95
96/*
97 * global options
98 */
99struct options
100{
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200101 const char *server_name; /* hostname of the server (client only) */
Paul Bakker1496d382011-05-23 12:07:29 +0000102 int server_port; /* port on which the ssl service runs */
103 int debug_level; /* level of debugging */
104 int authentication; /* if authentication is required */
105 int mode; /* SSL/TLS (0) or STARTTLS (1) */
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200106 const char *user_name; /* username to use for authentication */
107 const char *user_pwd; /* password to use for authentication */
108 const char *mail_from; /* E-Mail address to use as sender */
109 const char *mail_to; /* E-Mail address to use as recipient */
110 const char *ca_file; /* the file with the CA certificate(s) */
111 const char *crt_file; /* the file with the client certificate */
112 const char *key_file; /* the file with the client key */
Paul Bakker1496d382011-05-23 12:07:29 +0000113 int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
114} opt;
115
Paul Bakker3c5ef712013-06-25 16:37:45 +0200116static void my_debug( void *ctx, int level, const char *str )
Paul Bakker1496d382011-05-23 12:07:29 +0000117{
118 if( level < opt.debug_level )
119 {
120 fprintf( (FILE *) ctx, "%s", str );
121 fflush( (FILE *) ctx );
122 }
123}
124
Paul Bakker3c5ef712013-06-25 16:37:45 +0200125static int do_handshake( ssl_context *ssl, struct options *opt )
Paul Bakker1496d382011-05-23 12:07:29 +0000126{
127 int ret;
128 unsigned char buf[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000129 memset(buf, 0, 1024);
Paul Bakker1496d382011-05-23 12:07:29 +0000130
131 /*
132 * 4. Handshake
133 */
134 printf( " . Performing the SSL/TLS handshake..." );
135 fflush( stdout );
136
137 while( ( ret = ssl_handshake( ssl ) ) != 0 )
138 {
139 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
140 {
Paul Bakker5690efc2011-05-26 13:16:06 +0000141#if defined(POLARSSL_ERROR_C)
Paul Bakker03a8a792013-06-30 12:18:08 +0200142 polarssl_strerror( ret, (char *) buf, 1024 );
Paul Bakker5690efc2011-05-26 13:16:06 +0000143#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000144 printf( " failed\n ! ssl_handshake returned %d: %s\n\n", ret, buf );
145 return( -1 );
146 }
147 }
148
149 printf( " ok\n [ Ciphersuite is %s ]\n",
150 ssl_get_ciphersuite( ssl ) );
151
152 /*
153 * 5. Verify the server certificate
154 */
155 printf( " . Verifying peer X.509 certificate..." );
156
157 if( ( ret = ssl_get_verify_result( ssl ) ) != 0 )
158 {
159 printf( " failed\n" );
160
161 if( ( ret & BADCERT_EXPIRED ) != 0 )
162 printf( " ! server certificate has expired\n" );
163
164 if( ( ret & BADCERT_REVOKED ) != 0 )
165 printf( " ! server certificate has been revoked\n" );
166
167 if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
168 printf( " ! CN mismatch (expected CN=%s)\n", opt->server_name );
169
170 if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
171 printf( " ! self-signed or not signed by a trusted CA\n" );
172
173 printf( "\n" );
174 }
175 else
176 printf( " ok\n" );
177
178 printf( " . Peer certificate information ...\n" );
Paul Bakkerddf26b42013-09-18 13:46:23 +0200179 x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
180 ssl_get_peer_cert( ssl ) );
Paul Bakker1496d382011-05-23 12:07:29 +0000181 printf( "%s\n", buf );
182
183 return( 0 );
184}
185
Paul Bakker3c5ef712013-06-25 16:37:45 +0200186static int write_ssl_data( ssl_context *ssl, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000187{
188 int ret;
189
190 printf("\n%s", buf);
191 while( len && ( ret = ssl_write( ssl, buf, len ) ) <= 0 )
192 {
193 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
194 {
195 printf( " failed\n ! ssl_write returned %d\n\n", ret );
196 return -1;
197 }
198 }
199
200 return( 0 );
201}
202
Paul Bakker3c5ef712013-06-25 16:37:45 +0200203static int write_ssl_and_get_response( ssl_context *ssl, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000204{
205 int ret;
206 unsigned char data[128];
207 char code[4];
208 size_t i, idx = 0;
209
210 printf("\n%s", buf);
211 while( len && ( ret = ssl_write( ssl, buf, len ) ) <= 0 )
212 {
213 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
214 {
215 printf( " failed\n ! ssl_write returned %d\n\n", ret );
216 return -1;
217 }
218 }
219
220 do
221 {
222 len = sizeof( data ) - 1;
223 memset( data, 0, sizeof( data ) );
224 ret = ssl_read( ssl, data, len );
225
226 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
227 continue;
228
229 if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
230 return -1;
231
232 if( ret <= 0 )
233 {
234 printf( "failed\n ! ssl_read returned %d\n\n", ret );
235 return -1;
236 }
237
238 printf("\n%s", data);
239 len = ret;
240 for( i = 0; i < len; i++ )
241 {
242 if( data[i] != '\n' )
243 {
244 if( idx < 4 )
245 code[ idx++ ] = data[i];
246 continue;
247 }
248
249 if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
250 {
251 code[3] = '\0';
252 return atoi( code );
253 }
Paul Bakker3c5ef712013-06-25 16:37:45 +0200254
Paul Bakker1496d382011-05-23 12:07:29 +0000255 idx = 0;
256 }
257 }
258 while( 1 );
259}
260
Paul Bakker3c5ef712013-06-25 16:37:45 +0200261static int write_and_get_response( int sock_fd, unsigned char *buf, size_t len )
Paul Bakker1496d382011-05-23 12:07:29 +0000262{
263 int ret;
264 unsigned char data[128];
265 char code[4];
266 size_t i, idx = 0;
267
268 printf("\n%s", buf);
269 if( len && ( ret = write( sock_fd, buf, len ) ) <= 0 )
270 {
271 printf( " failed\n ! ssl_write returned %d\n\n", ret );
272 return -1;
273 }
274
275 do
276 {
277 len = sizeof( data ) - 1;
278 memset( data, 0, sizeof( data ) );
279 ret = read( sock_fd, data, len );
280
281 if( ret <= 0 )
282 {
283 printf( "failed\n ! read returned %d\n\n", ret );
284 return -1;
285 }
286
287 printf("\n%s", data);
288 len = ret;
289 for( i = 0; i < len; i++ )
290 {
291 if( data[i] != '\n' )
292 {
293 if( idx < 4 )
294 code[ idx++ ] = data[i];
295 continue;
296 }
297
298 if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
299 {
300 code[3] = '\0';
301 return atoi( code );
302 }
303
304 idx = 0;
305 }
306 }
307 while( 1 );
308}
309
Paul Bakker5690efc2011-05-26 13:16:06 +0000310#if defined(POLARSSL_BASE64_C)
311#define USAGE_AUTH \
312 " authentication=%%d default: 0 (disabled)\n" \
313 " user_name=%%s default: \"user\"\n" \
314 " user_pwd=%%s default: \"password\"\n"
315#else
316#define USAGE_AUTH \
317 " authentication options disabled. (Require POLARSSL_BASE64_C)\n"
318#endif /* POLARSSL_BASE64_C */
319
320#if defined(POLARSSL_FS_IO)
321#define USAGE_IO \
322 " ca_file=%%s default: \"\" (pre-loaded)\n" \
323 " crt_file=%%s default: \"\" (pre-loaded)\n" \
324 " key_file=%%s default: \"\" (pre-loaded)\n"
325#else
326#define USAGE_IO \
327 " No file operations available (POLARSSL_FS_IO not defined)\n"
328#endif /* POLARSSL_FS_IO */
329
Paul Bakker1496d382011-05-23 12:07:29 +0000330#define USAGE \
331 "\n usage: ssl_mail_client param=<>...\n" \
332 "\n acceptable parameters:\n" \
333 " server_name=%%s default: localhost\n" \
334 " server_port=%%d default: 4433\n" \
335 " debug_level=%%d default: 0 (disabled)\n" \
Paul Bakker1496d382011-05-23 12:07:29 +0000336 " mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \
Paul Bakker5690efc2011-05-26 13:16:06 +0000337 USAGE_AUTH \
Paul Bakker1496d382011-05-23 12:07:29 +0000338 " mail_from=%%s default: \"\"\n" \
339 " mail_to=%%s default: \"\"\n" \
Paul Bakker5690efc2011-05-26 13:16:06 +0000340 USAGE_IO \
Paul Bakker1496d382011-05-23 12:07:29 +0000341 " force_ciphersuite=<name> default: all enabled\n"\
342 " acceptable ciphersuite names:\n"
343
344int main( int argc, char *argv[] )
345{
346 int ret = 0, len, server_fd;
347 unsigned char buf[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000348#if defined(POLARSSL_BASE64_C)
Paul Bakker1496d382011-05-23 12:07:29 +0000349 unsigned char base[1024];
Paul Bakker5690efc2011-05-26 13:16:06 +0000350#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000351 char hostname[32];
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200352 const char *pers = "ssl_mail_client";
Paul Bakker508ad5a2011-12-04 17:09:26 +0000353
354 entropy_context entropy;
355 ctr_drbg_context ctr_drbg;
Paul Bakker1496d382011-05-23 12:07:29 +0000356 ssl_context ssl;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200357 x509_crt cacert;
358 x509_crt clicert;
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200359 pk_context pkey;
Paul Bakker1496d382011-05-23 12:07:29 +0000360 int i;
Paul Bakker819370c2012-09-28 07:04:41 +0000361 size_t n;
Paul Bakker1496d382011-05-23 12:07:29 +0000362 char *p, *q;
363 const int *list;
364
365 /*
Manuel Pégourié-Gonnard3bd2aae2013-09-20 13:10:13 +0200366 * Make sure memory references are valid in case we exit early.
Paul Bakker1496d382011-05-23 12:07:29 +0000367 */
368 server_fd = 0;
Manuel Pégourié-Gonnard3bd2aae2013-09-20 13:10:13 +0200369 memset( &ssl, 0, sizeof( ssl_context ) );
Paul Bakker369d2eb2013-09-18 11:58:25 +0200370 x509_crt_init( &cacert );
371 x509_crt_init( &clicert );
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200372 pk_init( &pkey );
Paul Bakker1496d382011-05-23 12:07:29 +0000373
374 if( argc == 0 )
375 {
376 usage:
377 printf( USAGE );
378
379 list = ssl_list_ciphersuites();
380 while( *list )
381 {
382 printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
383 list++;
384 }
385 printf("\n");
386 goto exit;
387 }
388
389 opt.server_name = DFL_SERVER_NAME;
390 opt.server_port = DFL_SERVER_PORT;
391 opt.debug_level = DFL_DEBUG_LEVEL;
392 opt.authentication = DFL_AUTHENTICATION;
393 opt.mode = DFL_MODE;
394 opt.user_name = DFL_USER_NAME;
395 opt.user_pwd = DFL_USER_PWD;
396 opt.mail_from = DFL_MAIL_FROM;
397 opt.mail_to = DFL_MAIL_TO;
Paul Bakker5690efc2011-05-26 13:16:06 +0000398 opt.ca_file = DFL_CA_FILE;
Paul Bakker1496d382011-05-23 12:07:29 +0000399 opt.crt_file = DFL_CRT_FILE;
400 opt.key_file = DFL_KEY_FILE;
401 opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
402
403 for( i = 1; i < argc; i++ )
404 {
Paul Bakker1496d382011-05-23 12:07:29 +0000405 p = argv[i];
406 if( ( q = strchr( p, '=' ) ) == NULL )
407 goto usage;
408 *q++ = '\0';
409
410 if( strcmp( p, "server_name" ) == 0 )
411 opt.server_name = q;
412 else if( strcmp( p, "server_port" ) == 0 )
413 {
414 opt.server_port = atoi( q );
415 if( opt.server_port < 1 || opt.server_port > 65535 )
416 goto usage;
417 }
418 else if( strcmp( p, "debug_level" ) == 0 )
419 {
420 opt.debug_level = atoi( q );
421 if( opt.debug_level < 0 || opt.debug_level > 65535 )
422 goto usage;
423 }
424 else if( strcmp( p, "authentication" ) == 0 )
425 {
426 opt.authentication = atoi( q );
427 if( opt.authentication < 0 || opt.authentication > 1 )
428 goto usage;
429 }
430 else if( strcmp( p, "mode" ) == 0 )
431 {
432 opt.mode = atoi( q );
433 if( opt.mode < 0 || opt.mode > 1 )
434 goto usage;
435 }
436 else if( strcmp( p, "user_name" ) == 0 )
437 opt.user_name = q;
438 else if( strcmp( p, "user_pwd" ) == 0 )
439 opt.user_pwd = q;
440 else if( strcmp( p, "mail_from" ) == 0 )
441 opt.mail_from = q;
442 else if( strcmp( p, "mail_to" ) == 0 )
443 opt.mail_to = q;
Paul Bakker5690efc2011-05-26 13:16:06 +0000444 else if( strcmp( p, "ca_file" ) == 0 )
445 opt.ca_file = q;
Paul Bakker1496d382011-05-23 12:07:29 +0000446 else if( strcmp( p, "crt_file" ) == 0 )
447 opt.crt_file = q;
448 else if( strcmp( p, "key_file" ) == 0 )
449 opt.key_file = q;
450 else if( strcmp( p, "force_ciphersuite" ) == 0 )
451 {
452 opt.force_ciphersuite[0] = -1;
453
454 opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
455
456 if( opt.force_ciphersuite[0] <= 0 )
457 goto usage;
458
459 opt.force_ciphersuite[1] = 0;
460 }
461 else
462 goto usage;
463 }
464
465 /*
466 * 0. Initialize the RNG and the session data
467 */
Paul Bakker508ad5a2011-12-04 17:09:26 +0000468 printf( "\n . Seeding the random number generator..." );
469 fflush( stdout );
470
471 entropy_init( &entropy );
472 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200473 (const unsigned char *) pers,
474 strlen( pers ) ) ) != 0 )
Paul Bakker508ad5a2011-12-04 17:09:26 +0000475 {
476 printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
477 goto exit;
478 }
479
480 printf( " ok\n" );
Paul Bakker1496d382011-05-23 12:07:29 +0000481
482 /*
483 * 1.1. Load the trusted CA
484 */
Paul Bakker508ad5a2011-12-04 17:09:26 +0000485 printf( " . Loading the CA root certificate ..." );
Paul Bakker1496d382011-05-23 12:07:29 +0000486 fflush( stdout );
487
Paul Bakker5690efc2011-05-26 13:16:06 +0000488#if defined(POLARSSL_FS_IO)
489 if( strlen( opt.ca_file ) )
Paul Bakkerddf26b42013-09-18 13:46:23 +0200490 ret = x509_crt_parse_file( &cacert, opt.ca_file );
Paul Bakker5690efc2011-05-26 13:16:06 +0000491 else
492#endif
493#if defined(POLARSSL_CERTS_C)
Manuel Pégourié-Gonnard641de712013-09-25 13:23:33 +0200494 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_list,
495 strlen( test_ca_list ) );
Paul Bakker5690efc2011-05-26 13:16:06 +0000496#else
497 {
498 ret = 1;
499 printf("POLARSSL_CERTS_C not defined.");
500 }
501#endif
Paul Bakker42488232012-05-16 08:21:05 +0000502 if( ret < 0 )
Paul Bakker1496d382011-05-23 12:07:29 +0000503 {
Paul Bakkerddf26b42013-09-18 13:46:23 +0200504 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000505 goto exit;
506 }
507
Paul Bakker42488232012-05-16 08:21:05 +0000508 printf( " ok (%d skipped)\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000509
510 /*
511 * 1.2. Load own certificate and private key
512 *
513 * (can be skipped if client authentication is not required)
514 */
515 printf( " . Loading the client cert. and key..." );
516 fflush( stdout );
517
Paul Bakker5690efc2011-05-26 13:16:06 +0000518#if defined(POLARSSL_FS_IO)
Paul Bakker1496d382011-05-23 12:07:29 +0000519 if( strlen( opt.crt_file ) )
Paul Bakkerddf26b42013-09-18 13:46:23 +0200520 ret = x509_crt_parse_file( &clicert, opt.crt_file );
521 else
Paul Bakker5690efc2011-05-26 13:16:06 +0000522#endif
523#if defined(POLARSSL_CERTS_C)
Paul Bakkerddf26b42013-09-18 13:46:23 +0200524 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
525 strlen( test_cli_crt ) );
Paul Bakker5690efc2011-05-26 13:16:06 +0000526#else
527 {
Paul Bakker69e095c2011-12-10 21:55:01 +0000528 ret = -1;
Paul Bakker5690efc2011-05-26 13:16:06 +0000529 printf("POLARSSL_CERTS_C not defined.");
530 }
531#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000532 if( ret != 0 )
533 {
Paul Bakkerddf26b42013-09-18 13:46:23 +0200534 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000535 goto exit;
536 }
537
Paul Bakker5690efc2011-05-26 13:16:06 +0000538#if defined(POLARSSL_FS_IO)
Paul Bakker1496d382011-05-23 12:07:29 +0000539 if( strlen( opt.key_file ) )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200540 ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
Paul Bakker1496d382011-05-23 12:07:29 +0000541 else
Paul Bakker5690efc2011-05-26 13:16:06 +0000542#endif
543#if defined(POLARSSL_CERTS_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200544 ret = pk_parse_key( &pkey, (const unsigned char *) test_cli_key,
Paul Bakker1496d382011-05-23 12:07:29 +0000545 strlen( test_cli_key ), NULL, 0 );
Paul Bakker5690efc2011-05-26 13:16:06 +0000546#else
547 {
Paul Bakker69e095c2011-12-10 21:55:01 +0000548 ret = -1;
Paul Bakker5690efc2011-05-26 13:16:06 +0000549 printf("POLARSSL_CERTS_C not defined.");
550 }
551#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000552 if( ret != 0 )
553 {
Paul Bakker1a7550a2013-09-15 13:01:22 +0200554 printf( " failed\n ! pk_parse_key returned %d\n\n", ret );
Paul Bakker1496d382011-05-23 12:07:29 +0000555 goto exit;
556 }
557
558 printf( " ok\n" );
559
560 /*
561 * 2. Start the connection
562 */
563 printf( " . Connecting to tcp/%s/%-4d...", opt.server_name,
564 opt.server_port );
565 fflush( stdout );
566
567 if( ( ret = net_connect( &server_fd, opt.server_name,
568 opt.server_port ) ) != 0 )
569 {
570 printf( " failed\n ! net_connect returned %d\n\n", ret );
571 goto exit;
572 }
573
574 printf( " ok\n" );
575
576 /*
577 * 3. Setup stuff
578 */
579 printf( " . Setting up the SSL/TLS structure..." );
580 fflush( stdout );
581
Paul Bakker1496d382011-05-23 12:07:29 +0000582 if( ( ret = ssl_init( &ssl ) ) != 0 )
583 {
584 printf( " failed\n ! ssl_init returned %d\n\n", ret );
585 goto exit;
586 }
587
588 printf( " ok\n" );
589
590 ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
591 ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );
592
Paul Bakker508ad5a2011-12-04 17:09:26 +0000593 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
Paul Bakker1496d382011-05-23 12:07:29 +0000594 ssl_set_dbg( &ssl, my_debug, stdout );
595 ssl_set_bio( &ssl, net_recv, &server_fd,
596 net_send, &server_fd );
597
Paul Bakker645ce3a2012-10-31 12:32:41 +0000598 if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
Paul Bakker1496d382011-05-23 12:07:29 +0000599 ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
600
Paul Bakker1496d382011-05-23 12:07:29 +0000601 ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200602 ssl_set_own_cert( &ssl, &clicert, &pkey );
Paul Bakker1496d382011-05-23 12:07:29 +0000603
Paul Bakker0be444a2013-08-27 21:55:01 +0200604#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
Paul Bakker1496d382011-05-23 12:07:29 +0000605 ssl_set_hostname( &ssl, opt.server_name );
Paul Bakker0be444a2013-08-27 21:55:01 +0200606#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000607
608 if( opt.mode == MODE_SSL_TLS )
609 {
610 if( do_handshake( &ssl, &opt ) != 0 )
611 goto exit;
612
613 printf( " > Get header from server:" );
614 fflush( stdout );
615
616 ret = write_ssl_and_get_response( &ssl, buf, 0 );
617 if( ret < 200 || ret > 299 )
618 {
619 printf( " failed\n ! server responded with %d\n\n", ret );
620 goto exit;
621 }
622
623 printf(" ok\n" );
624
625 printf( " > Write EHLO to server:" );
626 fflush( stdout );
627
628 gethostname( hostname, 32 );
629 len = sprintf( (char *) buf, "EHLO %s\n", hostname );
630 ret = write_ssl_and_get_response( &ssl, buf, len );
631 if( ret < 200 || ret > 299 )
632 {
633 printf( " failed\n ! server responded with %d\n\n", ret );
634 goto exit;
635 }
636 }
637 else
638 {
639 printf( " > Get header from server:" );
640 fflush( stdout );
641
642 ret = write_and_get_response( server_fd, buf, 0 );
643 if( ret < 200 || ret > 299 )
644 {
645 printf( " failed\n ! server responded with %d\n\n", ret );
646 goto exit;
647 }
648
649 printf(" ok\n" );
650
651 printf( " > Write EHLO to server:" );
652 fflush( stdout );
653
654 gethostname( hostname, 32 );
655 len = sprintf( (char *) buf, "EHLO %s\n", hostname );
656 ret = write_and_get_response( server_fd, buf, len );
657 if( ret < 200 || ret > 299 )
658 {
659 printf( " failed\n ! server responded with %d\n\n", ret );
660 goto exit;
661 }
662
663 printf(" ok\n" );
664
665 printf( " > Write STARTTLS to server:" );
666 fflush( stdout );
667
668 gethostname( hostname, 32 );
669 len = sprintf( (char *) buf, "STARTTLS\n" );
670 ret = write_and_get_response( server_fd, buf, len );
671 if( ret < 200 || ret > 299 )
672 {
673 printf( " failed\n ! server responded with %d\n\n", ret );
674 goto exit;
675 }
676
677 printf(" ok\n" );
678
679 if( do_handshake( &ssl, &opt ) != 0 )
680 goto exit;
681 }
682
Paul Bakker5690efc2011-05-26 13:16:06 +0000683#if defined(POLARSSL_BASE64_C)
Paul Bakker1496d382011-05-23 12:07:29 +0000684 if( opt.authentication )
685 {
686 printf( " > Write AUTH LOGIN to server:" );
687 fflush( stdout );
688
689 len = sprintf( (char *) buf, "AUTH LOGIN\n" );
690 ret = write_ssl_and_get_response( &ssl, buf, len );
691 if( ret < 200 || ret > 399 )
692 {
693 printf( " failed\n ! server responded with %d\n\n", ret );
694 goto exit;
695 }
696
697 printf(" ok\n" );
698
699 printf( " > Write username to server: %s", opt.user_name );
700 fflush( stdout );
701
702 n = sizeof( buf );
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200703 len = base64_encode( base, &n, (const unsigned char *) opt.user_name,
704 strlen( opt.user_name ) );
Paul Bakker1496d382011-05-23 12:07:29 +0000705 len = sprintf( (char *) buf, "%s\n", base );
706 ret = write_ssl_and_get_response( &ssl, buf, len );
707 if( ret < 300 || ret > 399 )
708 {
709 printf( " failed\n ! server responded with %d\n\n", ret );
710 goto exit;
711 }
712
713 printf(" ok\n" );
714
715 printf( " > Write password to server: %s", opt.user_pwd );
716 fflush( stdout );
717
Paul Bakkeref3f8c72013-06-24 13:01:08 +0200718 len = base64_encode( base, &n, (const unsigned char *) opt.user_pwd,
719 strlen( opt.user_pwd ) );
Paul Bakker1496d382011-05-23 12:07:29 +0000720 len = sprintf( (char *) buf, "%s\n", base );
721 ret = write_ssl_and_get_response( &ssl, buf, len );
722 if( ret < 200 || ret > 399 )
723 {
724 printf( " failed\n ! server responded with %d\n\n", ret );
725 goto exit;
726 }
727
728 printf(" ok\n" );
729 }
Paul Bakker5690efc2011-05-26 13:16:06 +0000730#endif
Paul Bakker1496d382011-05-23 12:07:29 +0000731
732 printf( " > Write MAIL FROM to server:" );
733 fflush( stdout );
734
735 len = sprintf( (char *) buf, "MAIL FROM:<%s>\n", opt.mail_from );
736 ret = write_ssl_and_get_response( &ssl, buf, len );
737 if( ret < 200 || ret > 299 )
738 {
739 printf( " failed\n ! server responded with %d\n\n", ret );
740 goto exit;
741 }
742
743 printf(" ok\n" );
744
745 printf( " > Write RCPT TO to server:" );
746 fflush( stdout );
747
748 len = sprintf( (char *) buf, "RCPT TO:<%s>\n", opt.mail_to );
749 ret = write_ssl_and_get_response( &ssl, buf, len );
750 if( ret < 200 || ret > 299 )
751 {
752 printf( " failed\n ! server responded with %d\n\n", ret );
753 goto exit;
754 }
755
756 printf(" ok\n" );
757
758 printf( " > Write DATA to server:" );
759 fflush( stdout );
760
761 len = sprintf( (char *) buf, "DATA\n" );
762 ret = write_ssl_and_get_response( &ssl, buf, len );
763 if( ret < 300 || ret > 399 )
764 {
765 printf( " failed\n ! server responded with %d\n\n", ret );
766 goto exit;
767 }
768
769 printf(" ok\n" );
770
771 printf( " > Write content to server:" );
772 fflush( stdout );
773
774 len = sprintf( (char *) buf, "From: %s\nSubject: PolarSSL Test mail\n\n"
775 "This is a simple test mail from the "
776 "PolarSSL mail client example.\n"
777 "\n"
778 "Enjoy!", opt.mail_from );
779 ret = write_ssl_data( &ssl, buf, len );
780
781 len = sprintf( (char *) buf, "\r\n.\r\n");
782 ret = write_ssl_and_get_response( &ssl, buf, len );
783 if( ret < 200 || ret > 299 )
784 {
785 printf( " failed\n ! server responded with %d\n\n", ret );
786 goto exit;
787 }
788
789 printf(" ok\n" );
790
791 ssl_close_notify( &ssl );
792
793exit:
794
795 if( server_fd )
796 net_close( server_fd );
Paul Bakker36713e82013-09-17 13:25:29 +0200797 x509_crt_free( &clicert );
798 x509_crt_free( &cacert );
Manuel Pégourié-Gonnardac755232013-08-19 14:10:16 +0200799 pk_free( &pkey );
Paul Bakker1496d382011-05-23 12:07:29 +0000800 ssl_free( &ssl );
Paul Bakker1ffefac2013-09-28 15:23:03 +0200801 entropy_free( &entropy );
Paul Bakker1496d382011-05-23 12:07:29 +0000802
Paul Bakkercce9d772011-11-18 14:26:47 +0000803#if defined(_WIN32)
Paul Bakker1496d382011-05-23 12:07:29 +0000804 printf( " + Press Enter to exit this program.\n" );
805 fflush( stdout ); getchar();
806#endif
807
808 return( ret );
809}
Paul Bakker508ad5a2011-12-04 17:09:26 +0000810#endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_SSL_TLS_C &&
811 POLARSSL_SSL_CLI_C && POLARSSL_NET_C && POLARSSL_RSA_C **
812 POLARSSL_CTR_DRBG_C */