IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 使用mbedtls库实现ftps协议 -> 正文阅读

[网络协议]使用mbedtls库实现ftps协议

ftp的隐式加密、显式加密、不加密这三种方式有一些区别。
ftp协议可以直接抓包查看,没啥好说的。
ftps抓包无法查看加密的那一部分,因为这个原因,调试显式加密时坑惨了我。

FTP隐式加密流程:

  1. 与服务器信令端口建立TCP连接
  2. TCP连接成功后,直接进行ssl握手
  3. 握手成功后,使用USER/PASS指令进行登录。

涉及数据端口的指令流程,如LIST指令:
使用被动模式:

  1. 发送PASV指令后,得到服务器的数据端口,
  2. 进行数据端口的TCP连接,(注意: 这时还不能进行数据端口的SSL握手)
  3. 发送LIST指令,收到 150 accept data connection
  4. 进行数据端口的SSL握手
  5. 接收数据

FTP显式加密流程:

  1. 与服务器信令端口建立TCP连接
  2. TCP连接成功后,使用AUTH 指令进行加密协商。
  3. 收到 234 的响应码,说明服务器支持显式加密
  4. 进行信令端口的SSL握手
  5. 握手成功后,使用USER/PASS指令进行登录。
  6. 使用PBSZ /PROT指令进行数据端口的加密协商(不进行协商,无法进行数据传输)

涉及数据端口的指令流程,与隐式加密相同,区别在于:在发送LIST等涉及数据端口的指令前,一定要先发送PBSZ/PROT指令进行数据端口的加密等级协商,否则服务器可能断开连接。

下面两个例子都是使用MBEDTLS库的例子改的

隐式加密示例:

/*
 *  SSL client demonstration program
 *
 *  Copyright The Mbed TLS Contributors
 *  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.
 */

#include "mbedtls/build_info.h"
#include <string.h>

#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
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */

#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_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");
    mbedtls_exit(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 "test/certs.h"

#include <string.h>

#define SERVER_PORT "990"
#define SERVER_NAME "110.78.86.97"
#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);
}

typedef enum
{
    USER = 1,
    PASS,
    LIST,
    TYPE,
    PASV,
    WAIT_DATA_CONNECT,
    WAIT_HANDSHAKE,
    IDLE

} state;

state ftp_state = IDLE;

char data_port[10] = {0};

int nb_fds = 100;
int do_connect(mbedtls_net_context *server_fd)
{
    int ret = 0;
    // uint32_t flags;
    /*
     * 1. Start the connection
     */
    mbedtls_printf("  . Connecting to tcp/%s/%s...", SERVER_NAME, data_port);
    fflush(stdout);

    if ((ret = mbedtls_net_connect(server_fd, SERVER_NAME,
                                   data_port, MBEDTLS_NET_PROTO_TCP)) != 0)
    {
        mbedtls_printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
        goto exit;
    }
    if (ret == 0)
    {
        if (nb_fds < server_fd->fd)
            nb_fds = server_fd->fd;
        ++nb_fds;
    }

    mbedtls_printf(" ok\n");

exit:
    return ret;
}

int do_handshake(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg)
{

    int ret = 0;
    uint32_t flags;

    /*
     * 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_OPTIONAL);
    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;
    }

    mbedtls_ssl_set_bio(ssl, server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

    /*
     * 4. Handshake
     */
    mbedtls_printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    while ((ret = mbedtls_ssl_handshake(ssl)) != 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int)-ret);
            goto exit;
        }
    }

    mbedtls_printf(" ok\n");

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf("  . Verifying peer X.509 certificate...");

    /* In real life, we probably want to bail out when ret != 0 */
    if ((flags = mbedtls_ssl_get_verify_result(ssl)) != 0)
    {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
        char vrfy_buf[512];
#endif

        mbedtls_printf(" failed\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
        mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

        mbedtls_printf("%s\n", vrfy_buf);
#endif
    }
    else
        mbedtls_printf(" ok\n");

    return 0;
exit:

    return -1;
}

state parse_buf(char *buf, int len)
{
    // mbedtls_printf( " parse:%d\n",ftp_state);
    if (strstr(buf, "331 "))
    {
        ftp_state = PASS;
        goto exit;
    }

    if (strstr(buf, "226 ") && ftp_state == IDLE)
    {
        ftp_state = TYPE;
        mbedtls_printf(" change state to pasv \n");
        goto exit;
    }

    if (strstr(buf, "230 ") && ftp_state == PASS)
    {
        ftp_state = TYPE;
        goto exit;
    }

    if (strstr(buf, "200 ") && ftp_state == TYPE)
    {
        ftp_state = PASV;
        mbedtls_printf(" change state to pasv \n");
        goto exit;
    }

    if (ftp_state == LIST)
    {
        ftp_state = WAIT_HANDSHAKE;
        goto exit;
    }

    if (strstr(buf, "227 "))
    {
        char *p = NULL;
        if (p = strstr(buf, "110.78.86.97"))
        {
            char *q = p + 13;
            printf("%s", q);

            int first = 0, second = 0;
            sscanf(q, "%d,%d)", &first, &second);

            printf("%d %d\n", first, second);

            int port = 0;
            port = first * 256 + second;

            sprintf(data_port, "%d", port);

            printf("%d %s\n", port, data_port);
        }

        ftp_state = LIST;
        goto exit;
    }

    // ftp_state = IDLE;

exit:

    // mbedtls_printf( " %s %d end\n",buf,ftp_state);
    return ftp_state;
}

static void _free(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_entropy_context *entropy)
{
    mbedtls_ssl_close_notify(ssl);
    printf("  . Closing the connection...");

    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);
}

static void _init(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_entropy_context *entropy)
{
    const char *pers = "ssl_client1";
    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_entropy_init(entropy);
    int ret = 0;
    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;
    }
exit:
    return;
}

static int write_ssl_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
{
    int ret;

    mbedtls_printf("\n%s", buf);
    while (len && (ret = mbedtls_ssl_write(ssl, buf, len)) <= 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
            return -1;
        }
    }

    return (0);
}

int main(void)
{
    int ret = 1, len;
    int exit_code = MBEDTLS_EXIT_FAILURE;
    mbedtls_net_context server_fd;
    mbedtls_net_context data_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;

    mbedtls_entropy_context entropy_1;
    mbedtls_ctr_drbg_context ctr_drbg_1;
    mbedtls_ssl_context ssl_1;
    mbedtls_ssl_config conf_1;
    mbedtls_x509_crt cacert_1;

#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", (unsigned int)-ret);
        goto exit;
    }

    ret = mbedtls_x509_crt_parse(&cacert_1, (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", (unsigned int)-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_OPTIONAL);
    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;
    }

    mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

    /*
     * 4. Handshake
     */
    mbedtls_printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    while ((ret = mbedtls_ssl_handshake(&ssl)) != 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int)-ret);
            goto exit;
        }
    }

    mbedtls_printf(" ok\n");

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf("  . Verifying peer X.509 certificate...");

    /* In real life, we probably want to bail out when ret != 0 */
    if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
    {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
        char vrfy_buf[512];
#endif

        mbedtls_printf(" failed\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
        mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

        mbedtls_printf("%s\n", vrfy_buf);
#endif
    }
    else
        mbedtls_printf(" ok\n");

    /*
     * 3. Write the GET request
     */
    mbedtls_printf("  > Write to server:");
    fflush(stdout);

    /*
     * 7. Read the HTTP response
     */
    mbedtls_printf("  < Read from server:");
    fflush(stdout);

    int first = 0;
    mbedtls_ssl_write(&ssl, "USER admin\r\n", 12);

    struct timeval tm;
    struct timeval *tm_ptr = NULL;

    fd_set read_fds;
    // fd_set write_fds;

    int max_wait = 2000;
    tm.tv_sec = max_wait / 1000;
    tm.tv_usec = (max_wait % 1000) * 1000;
    tm_ptr = &tm;

    if (nb_fds < server_fd.fd)
        nb_fds = server_fd.fd;
    if (nb_fds < data_fd.fd)
        nb_fds = data_fd.fd;
    ++nb_fds;
    int ok = 0;
    while (1)
    {

        FD_ZERO(&read_fds);

        if (server_fd.fd > 0)
        {
            FD_SET(server_fd.fd, &read_fds);
        }
        if (data_fd.fd > 0)
        {
            FD_SET(data_fd.fd, &read_fds);
        }

        if ((ret = select(nb_fds, &read_fds, NULL, NULL, tm_ptr)) < 0)
        {
            perror("select");
            goto exit;
        }

        if (FD_ISSET(server_fd.fd, &read_fds))
        {
            printf("=====%d ", nb_fds);
            len = sizeof(buf) - 1;
            memset(buf, 0, sizeof(buf));
            mbedtls_net_set_nonblock(&ssl);
            ret = mbedtls_ssl_read(&ssl, buf, len);
            if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
                continue;

            if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
                break;

            if (ret < 0)
            {
                mbedtls_printf("failed\n  ! mbedtls_ssl_read returned %d\n\n", ret);
                break;
            }

            if (ret == 0)
            {
                mbedtls_printf("\n\nEOF\n\n");
                break;
            }

            len = ret;
            mbedtls_printf(" %d bytes read\n\n%s", len, (char *)buf);

            switch (parse_buf(buf, len))
            {
            case PASS:
                mbedtls_ssl_write(&ssl, "PASS admin\r\n", 12);
                break;
            case TYPE:
                mbedtls_ssl_write(&ssl, "TYPE A\r\n", 8);
                break;
            case PASV:
                mbedtls_printf(" in pasv\n");
                mbedtls_ssl_write(&ssl, "PASV\r\n", 6);
                break;
            case LIST:
                _init(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                do_connect(&data_fd);
                mbedtls_ssl_write(&ssl, "NLST .\r\n", 8);
                
                if (do_handshake(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1) == 0)
                {
                    mbedtls_printf("success data handshake\n ");
                    mbedtls_printf("data_fd.fd is : %d\n ", data_fd.fd);
                }

                break;
            case WAIT_HANDSHAKE:
                break;
            default:
                break;
            }
        }


            if (data_fd.fd!=-1 && FD_ISSET(data_fd.fd, &read_fds))
            {

                char buf1[1024] = {0};
                mbedtls_net_set_nonblock(&ssl_1);
                int ret1 = mbedtls_ssl_read(&ssl_1, buf1, 1023);
                if (ret1 > 0)
                {
                    printf("recv:\n%s\n", buf1);
                }
                else if (ret1 == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
                {
                    printf("ret1 < 0 :%d\n", ret1);
                    _free(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                    mbedtls_net_set_nonblock(&ssl);
                    ftp_state = IDLE;
                }
                else if (ret1 == 0)
                {
                    printf("ret1 = 0 :%d\n", ret1);
                    _free(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                    mbedtls_net_set_nonblock(&ssl);
                    ftp_state = IDLE;
                }
            }
        
    }


    mbedtls_ssl_close_notify(&ssl);

    exit_code = MBEDTLS_EXIT_SUCCESS;

exit:

#ifdef MBEDTLS_ERROR_C
    if (exit_code != MBEDTLS_EXIT_SUCCESS)
    {
        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

    mbedtls_exit(exit_code);
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && \
          MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&        \
          MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C */

显式加密示例:

/*
 *  SSL client demonstration program
 *
 *  Copyright The Mbed TLS Contributors
 *  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.
 */

#include "mbedtls/build_info.h"
#include <string.h>

#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
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */

#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_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");
    mbedtls_exit(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 "test/certs.h"

#include <string.h>

#define SERVER_PORT "21"
#define SERVER_NAME "121.75.13.180"
#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);
}

typedef enum
{
    USER = 1,
    PASS,
    LIST,
    TYPE,
    PASV,
    WAIT_DATA_CONNECT,
    WAIT_HANDSHAKE,
    CTRL_HANDSHAKE,
    PBSZ,
    PROT,
    IDLE

} state;

state ftp_state = IDLE;

char data_port[10] = {0};

int nb_fds = 100;
int do_connect(mbedtls_net_context *server_fd)
{
    int ret = 0;
    // uint32_t flags;
    /*
     * 1. Start the connection
     */
    mbedtls_printf("  . Connecting to tcp/%s/%s...", SERVER_NAME, data_port);
    fflush(stdout);

    if ((ret = mbedtls_net_connect(server_fd, SERVER_NAME,
                                   data_port, MBEDTLS_NET_PROTO_TCP)) != 0)
    {
        mbedtls_printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
        goto exit;
    }
    if (ret == 0)
    {
        if (nb_fds < server_fd->fd)
            nb_fds = server_fd->fd;
        ++nb_fds;
    }

    mbedtls_printf(" ok\n");

exit:
    return ret;
}

int do_handshake(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg)
{

    int ret = 0;
    uint32_t flags;

    /*
     * 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_OPTIONAL);
    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;
    }

    mbedtls_ssl_set_bio(ssl, server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

    /*
     * 4. Handshake
     */
    mbedtls_printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    while ((ret = mbedtls_ssl_handshake(ssl)) != 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int)-ret);
            goto exit;
        }
    }

    mbedtls_printf(" ok\n");

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf("  . Verifying peer X.509 certificate...");

    /* In real life, we probably want to bail out when ret != 0 */
    if ((flags = mbedtls_ssl_get_verify_result(ssl)) != 0)
    {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
        char vrfy_buf[512];
#endif

        mbedtls_printf(" failed\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
        mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

        mbedtls_printf("%s\n", vrfy_buf);
#endif
    }
    else
        mbedtls_printf(" ok\n");

    return 0;
exit:

    return -1;
}

state parse_buf(char *buf, int len)
{
    // mbedtls_printf( " parse:%d\n",ftp_state);
    if (strstr(buf, "331 "))
    {
        ftp_state = PASS;
        goto exit;
    }

    if (strstr(buf, "234 "))
    {
        ftp_state = CTRL_HANDSHAKE;
        mbedtls_printf(" change state to CTRL_HANDSHAKE; \n");
        goto exit;
    }

    if (strstr(buf, "226 ") && ftp_state == IDLE)
    {
        ftp_state = TYPE;
        mbedtls_printf(" change state to pasv \n");
        goto exit;
    }

    if (strstr(buf, "230 ") && ftp_state == PASS)
    {
        // ftp_state=TYPE;
        // ftp_state=PBSZ;
        ftp_state = PROT; //没有这个会报7200的错误
        goto exit;
    }

    if (strstr(buf, "200 ") && ftp_state == TYPE)
    {
        ftp_state = PASV;
        mbedtls_printf(" change state to pasv \n");
        goto exit;
    }

    if (strstr(buf, "200 ") && ftp_state == PBSZ)
    {
        ftp_state = PROT;
        mbedtls_printf(" change state to pbsz \n");
        goto exit;
    }

    if (strstr(buf, "200 ") && ftp_state == PROT)
    {
        ftp_state = TYPE;
        mbedtls_printf(" change state to prot \n");
        goto exit;
    }

    if (ftp_state == LIST)
    {
        ftp_state = WAIT_HANDSHAKE;
        goto exit;
    }

    if (strstr(buf, "227 "))
    {
        char *p = NULL;
        if (p = strstr(buf, "121.75.13.180"))
        {
            char *q = p + 14;
            printf("%s", q);

            int first = 0, second = 0;
            sscanf(q, "%d,%d)", &first, &second);

            printf("%d %d\n", first, second);

            int port = 0;
            port = first * 256 + second;

            sprintf(data_port, "%d", port);

            printf("%d %s\n", port, data_port);
        }

        ftp_state = LIST;
        goto exit;
    }

    // ftp_state = IDLE;

exit:

    // mbedtls_printf( " %s %d end\n",buf,ftp_state);
    return ftp_state;
}

static void _free(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_entropy_context *entropy)
{
    mbedtls_ssl_close_notify(ssl);
    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);
}

static void _init(mbedtls_net_context *server_fd, mbedtls_ssl_context *ssl, mbedtls_ssl_config *conf, mbedtls_x509_crt *cacert, mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_entropy_context *entropy)
{
    const char *pers = "ssl_client1";
    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_entropy_init(entropy);
    int ret = 0;
    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;
    }
exit:
    return;
}

static int write_ssl_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
{
    int ret;

    mbedtls_printf("\n%s", buf);
    while (len && (ret = mbedtls_ssl_write(ssl, buf, len)) <= 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
            return -1;
        }
    }

    return (0);
}

static int do_handshake_(mbedtls_ssl_context *ssl)
{
    int ret;
    uint32_t flags;
    unsigned char buf[1024];
    memset(buf, 0, 1024);

    /*
     * 4. Handshake
     */
    mbedtls_printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    while ((ret = mbedtls_ssl_handshake(ssl)) != 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
#if defined(MBEDTLS_ERROR_C)
            mbedtls_strerror(ret, (char *)buf, 1024);
#endif
            mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned %d: %s\n\n", ret, buf);
            return (-1);
        }
    }

    mbedtls_printf(" ok\n    [ Ciphersuite is %s ]\n",
                   mbedtls_ssl_get_ciphersuite(ssl));

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf("  . Verifying peer X.509 certificate...");

    /* In real life, we probably want to bail out when ret != 0 */
    if ((flags = mbedtls_ssl_get_verify_result(ssl)) != 0)
    {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
        char vrfy_buf[512];
#endif

        mbedtls_printf(" failed\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
        mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

        mbedtls_printf("%s\n", vrfy_buf);
#endif
    }
    else
        mbedtls_printf(" ok\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
    mbedtls_printf("  . Peer certificate information    ...\n");
    mbedtls_x509_crt_info((char *)buf, sizeof(buf) - 1, "      ",
                          mbedtls_ssl_get_peer_cert(ssl));
    mbedtls_printf("%s\n", buf);
#endif

    return (0);
}

int main(void)
{
    int ret = 1, len;
    int exit_code = MBEDTLS_EXIT_FAILURE;
    mbedtls_net_context server_fd;
    mbedtls_net_context data_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;

    mbedtls_entropy_context entropy_1;
    mbedtls_ctr_drbg_context ctr_drbg_1;
    mbedtls_ssl_context ssl_1;
    mbedtls_ssl_config conf_1;
    mbedtls_x509_crt cacert_1;

#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", (unsigned int)-ret);
        goto exit;
    }

    ret = mbedtls_x509_crt_parse(&cacert_1, (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", (unsigned int)-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_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
    mbedtls_ssl_conf_max_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

    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_OPTIONAL);
    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;
    }

    mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

    /*
     * 4. Handshake
     */
    mbedtls_printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    mbedtls_printf(" ok\n");

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf("  . Verifying peer X.509 certificate...");

    /* In real life, we probably want to bail out when ret != 0 */
    if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
    {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
        char vrfy_buf[512];
#endif

        mbedtls_printf(" failed\n");

#if !defined(MBEDTLS_X509_REMOVE_INFO)
        mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

        mbedtls_printf("%s\n", vrfy_buf);
#endif
    }
    else
        mbedtls_printf(" ok\n");

    /*
     * 3. Write the GET request
     */
    mbedtls_printf("  > Write to server:");
    fflush(stdout);


    /*
     * 7. Read the HTTP response
     */
    mbedtls_printf("  < Read from server:");
    fflush(stdout);

    int first = 0;
    // mbedtls_ssl_write( &ssl, "USER admin\r\n", 12);
    // mbedtls_net_send( &server_fd, "AUTH TLS\r\n",10 );
    mbedtls_net_send(&server_fd, "AUTH TLS\r\n", 10);

    struct timeval tm;
    struct timeval *tm_ptr = NULL;

    fd_set read_fds;
    // fd_set write_fds;

    int max_wait = 2000;
    tm.tv_sec = max_wait / 1000;
    tm.tv_usec = (max_wait % 1000) * 1000;
    tm_ptr = &tm;

    int encrypt = 0;
    if (nb_fds < server_fd.fd)
        nb_fds = server_fd.fd;
    if (nb_fds < data_fd.fd)
        nb_fds = data_fd.fd;
    ++nb_fds;
    int ok = 0;
    while (1)
    {

        FD_ZERO(&read_fds);
        if (server_fd.fd > 0)
        {
            FD_SET(server_fd.fd, &read_fds);
        }

        if(data_fd.fd > 0)
        {
            FD_SET( data_fd.fd, &read_fds );
        }

        if ((ret = select(nb_fds, &read_fds, NULL, NULL, tm_ptr)) < 0)
        {
            perror("select");
            goto exit;
        }


        if (data_fd.fd != -1 && FD_ISSET(data_fd.fd, &read_fds))
        {

            char buf1[1024] = {0};
            mbedtls_net_set_nonblock(&ssl_1);
            int ret1 = mbedtls_ssl_read(&ssl_1, buf1, 1023);
            if (ret1 > 0)
            {
                printf("recv:\n%s\n", buf1);
            }
            else if (ret1 == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
            {
                printf("ret1 < 0 :%d\n", ret1);
                _free(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                mbedtls_net_set_nonblock(&ssl);
                ftp_state = IDLE;
            }
            else if (ret1 == 0)
            {
                printf("ret1 = 0 :%d\n", ret1);
                _free(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                mbedtls_net_set_nonblock(&ssl);
                ftp_state = IDLE;
            }
        }



        if (FD_ISSET(server_fd.fd, &read_fds))
        {
            printf("=====%d ", nb_fds);
            len = sizeof(buf) - 1;
            memset(buf, 0, sizeof(buf));
            mbedtls_net_set_nonblock(&ssl);
            if (encrypt == 0)
            {
                ret = mbedtls_net_recv(&server_fd, buf, len);
            }
            else
            {
                ret = mbedtls_ssl_read(&ssl, buf, len);
            }

            if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
                continue;

            if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
                break;

            if (ret < 0)
            {
                mbedtls_printf("failed\n  ! mbedtls_ssl_read returned %d\n\n", ret);
                break;
            }

            if (ret == 0)
            {
                mbedtls_printf("\n\nEOF\n\n");
                break;
            }

            len = ret;
            mbedtls_printf(" %d bytes read\n\n%s", len, (char *)buf);

            switch (parse_buf(buf, len))
            {
            case CTRL_HANDSHAKE:
                do_handshake_(&ssl);
                if (write_ssl_data(&ssl, "USER root\r\n", 11) == 0)
                    mbedtls_printf("write success\n");
                ftp_state = USER;
                encrypt = 1;
                break;
            case PASS:
                mbedtls_ssl_write(&ssl, "PASS admin12345.\r\n", 18);
                break;
            case TYPE:
                mbedtls_ssl_write(&ssl, "TYPE A\r\n", 8);
                break;
            case PBSZ:
                mbedtls_ssl_write(&ssl, "PBSZ 0\r\n", 8);
                break;
            case PROT:
                mbedtls_ssl_write(&ssl, "PROT P\r\n", 8);
                break;
            case PASV:
                mbedtls_printf(" in pasv\n");
                mbedtls_ssl_write(&ssl, "PASV\r\n", 6);
                break;
            case LIST:
                mbedtls_net_set_nonblock(&ssl_1);
                _init(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1, &entropy_1);
                do_connect(&data_fd);
                mbedtls_printf(" in list\n");

                if (write_ssl_data(&ssl, "LIST .\r\n", 8) != 0)
                {
                    mbedtls_printf("write fail\n ");
                }
                break;
            case WAIT_HANDSHAKE:
                if (do_handshake(&data_fd, &ssl_1, &conf_1, &cacert_1, &ctr_drbg_1) == 0)
                {
                    mbedtls_printf("success data handshake\n ");
                }
                break;
            default:
                break;
            }
        }
    }

    mbedtls_ssl_close_notify(&ssl);

    exit_code = MBEDTLS_EXIT_SUCCESS;

exit:

#ifdef MBEDTLS_ERROR_C
    if (exit_code != MBEDTLS_EXIT_SUCCESS)
    {
        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

    mbedtls_exit(exit_code);
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && \
          MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&        \
          MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C */

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:15:44  更:2022-01-30 19:17:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:36:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码