]> granicus.if.org Git - libevent/commitdiff
simple https client example using mbedtls
authorJesse Fang <boycht@gmail.com>
Mon, 13 Jan 2020 15:08:26 +0000 (23:08 +0800)
committerAzat Khuzhin <azat@libevent.org>
Wed, 22 Jul 2020 19:52:58 +0000 (22:52 +0300)
Based on mbedtls's source code programs/ssl/ssl_client1.c

sample/ssl_client1.c [new file with mode: 0644]

diff --git a/sample/ssl_client1.c b/sample/ssl_client1.c
new file mode 100644 (file)
index 0000000..af8019c
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *  SSL client demonstration program
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_time       time 
+#define mbedtls_time_t     time_t
+#define mbedtls_fprintf    fprintf
+#define mbedtls_printf     printf
+#endif
+
+#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
+    !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
+    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) ||         \
+    !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \
+    !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C)
+int main( void )
+{
+    mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
+           "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
+           "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
+           "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
+           "not defined.\n");
+    return( 0 );
+}
+#else
+
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/error.h"
+#include "mbedtls/certs.h"
+
+#include <string.h>
+
+#include <event2/event.h>
+#include <event2/bufferevent.h>
+#include <event2/bufferevent_ssl.h>
+#include <event2/util.h>
+
+#define SERVER_PORT "443"
+#define SERVER_NAME "amazon.com"
+#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
+
+#define DEBUG_LEVEL 1
+
+static void my_debug( void *ctx, int level,
+                      const char *file, int line,
+                      const char *str )
+{
+    ((void) level);
+
+    mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
+    fflush(  (FILE *) ctx  );
+}
+
+void writecb(struct bufferevent *bev, void *arg)
+{
+        fprintf(stderr, "writecb\n");
+}
+
+void readcb(struct bufferevent *bev, void *arg)
+{
+       char buf[1000] = {};
+       size_t r = 0;
+       int i;
+       for (i=0; i<10; ++i)
+{
+       r = bufferevent_read(bev, buf, 800);
+               fprintf(stderr, "readcb %d\n\n", r);
+               if (r > 1) {
+                       fwrite(buf, 1, r, stdout);
+                       fwrite("\n", 1, r, stdout);
+                       fflush(stdout);
+               }
+       }
+}
+
+void eventcb(struct bufferevent *bev, short what, void *arg)
+{
+       fprintf(stderr, "\n---------------eventcb %d\n", what);
+       if (what & BEV_EVENT_CONNECTED) {
+               const char headers[] =
+                       "GET / HTTP/1.1\r\n"
+                       "HOST: " SERVER_NAME "\r\n"
+                       "User-Agent: curl/7.65.1\r\n"
+                       "Connection: Keep-Alive\r\n"
+                       "\r\n";
+               bufferevent_write(bev, headers, sizeof(headers) - 1); // without ending '\0'
+               //bufferevent_disable(bev, EV_WRITE);
+               fprintf(stderr, "write request completely\n");
+       } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
+               fprintf(stderr, "closed\n");
+               bufferevent_free(bev);
+       }
+}
+
+
+
+int main( void )
+{
+    int ret, len;
+    mbedtls_net_context server_fd;
+    uint32_t flags;
+    unsigned char buf[1024];
+    const char *pers = "ssl_client1";
+
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+    mbedtls_ssl_context ssl;
+    mbedtls_ssl_config conf;
+    mbedtls_x509_crt cacert;
+
+    struct event *ev_sigterm;
+    struct event_base  *evbase;
+    struct evdns_base *evdns;
+
+#ifdef WIN32
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int err;
+
+    /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
+    wVersionRequested = MAKEWORD(2, 2);
+
+    err = WSAStartup(wVersionRequested, &wsaData);
+#endif
+
+
+#if defined(MBEDTLS_DEBUG_C)
+    mbedtls_debug_set_threshold( DEBUG_LEVEL );
+#endif
+
+    /*
+     * 0. Initialize the RNG and the session data
+     */
+    mbedtls_net_init( &server_fd );
+    mbedtls_ssl_init( &ssl );
+    mbedtls_ssl_config_init( &conf );
+    mbedtls_x509_crt_init( &cacert );
+    mbedtls_ctr_drbg_init( &ctr_drbg );
+
+    mbedtls_printf( "\n  . Seeding the random number generator..." );
+    fflush( stdout );
+
+    mbedtls_entropy_init( &entropy );
+    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
+                               (const unsigned char *) pers,
+                               strlen( pers ) ) ) != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
+        goto exit;
+    }
+
+    mbedtls_printf( " ok\n" );
+
+    /*
+     * 0. Initialize certificates
+     */
+    mbedtls_printf( "  . Loading the CA root certificate ..." );
+    fflush( stdout );
+
+    ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
+                          mbedtls_test_cas_pem_len );
+    if( ret < 0 )
+    {
+        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
+        goto exit;
+    }
+
+    mbedtls_printf( " ok (%d skipped)\n", ret );
+
+    /*
+     * 1. Start the connection
+     */
+    mbedtls_printf( "  . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT );
+    fflush( stdout );
+
+    if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
+                                         SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_net_connect returned %d\n\n", ret );
+        goto exit;
+    }
+
+    mbedtls_printf( " ok\n" );
+
+    /*
+     * 2. Setup stuff
+     */
+    mbedtls_printf( "  . Setting up the SSL/TLS structure..." );
+    fflush( stdout );
+
+    if( ( ret = mbedtls_ssl_config_defaults( &conf,
+                    MBEDTLS_SSL_IS_CLIENT,
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
+        goto exit;
+    }
+
+    mbedtls_printf( " ok\n" );
+
+    /* OPTIONAL is not optimal for security,
+     * but makes interop easier in this simplified example */
+    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
+    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
+    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
+    mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
+
+    if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
+        goto exit;
+    }
+    fflush( stdout );
+
+    //mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+
+    event_enable_debug_mode();
+    evbase = event_base_new();
+    evdns = evdns_base_new(evbase, 1);
+    evdns_base_set_option(evdns, "randomize-case:", "0");
+
+    evutil_make_socket_nonblocking(server_fd.fd);
+
+
+#if 1
+struct bufferevent *bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE);
+struct bufferevent *bevf = bufferevent_mbedtls_filter_new(
+       evbase, bev, &ssl, 
+       BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
+       bev = bevf;
+#else
+
+struct bufferevent *bev = bufferevent_mbedtls_socket_new(
+       evbase, server_fd.fd, &ssl, 
+       BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
+#endif
+    bufferevent_setcb(bev, readcb, NULL, eventcb, NULL);
+
+    bufferevent_enable(bev, EV_READ);
+
+
+    event_base_loop(evbase, 0);
+    event_base_free(evbase);
+
+
+
+exit:
+
+#ifdef MBEDTLS_ERROR_C
+    if( ret != 0 )
+    {
+        char error_buf[100];
+        mbedtls_strerror( ret, error_buf, 100 );
+        mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf );
+    }
+#endif
+
+    mbedtls_net_free( &server_fd );
+
+    mbedtls_x509_crt_free( &cacert );
+    mbedtls_ssl_free( &ssl );
+    mbedtls_ssl_config_free( &conf );
+    mbedtls_ctr_drbg_free( &ctr_drbg );
+    mbedtls_entropy_free( &entropy );
+
+#if defined(_WIN32)
+    mbedtls_printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
+#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
+          MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
+          MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C &&
+          MBEDTLS_X509_CRT_PARSE_C */