openssl3.2 - 官方demo学习 - server-conf.c

文章目录

    • [openssl3.2 - 官方demo学习 - server-conf.c](#openssl3.2 - 官方demo学习 - server-conf.c)
    • 概述
    • 笔记
    • END

openssl3.2 - 官方demo学习 - server-conf.c

概述

建立TLS服务器, 参数从配置文件中来.通过SSL_CONF_CTX_set_flags()来决定读那些TLS参数

遍历配置文件, 通过SSL_CONF_cmd()来读取预期的配置项.

如果不是TLS直接用的参数(e.g. BIO), 自己从配置文件Item中赋值到变量.

笔记

c 复制代码
/*!
\file server-conf.c
\brief 建立TLS服务器, 参数从配置文件中来.通过SSL_CONF_CTX_set_flags()来决定读那些TLS参数
        遍历配置文件, 通过SSL_CONF_cmd()来读取预期的配置项. 
        如果不是TLS直接用的参数(e.g. BIO), 自己从配置文件Item中赋值到变量.
*/

/*
 * Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

/*
 * A minimal program to serve an SSL connection. It uses blocking. It uses
 * the SSL_CONF API with a configuration file. cc -I../../include saccept.c
 * -L../.. -lssl -lcrypto -ldl
 */

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>

#include "my_openSSL_lib.h"

int main(int argc, char *argv[])
{
    char *psz_port = "*:4433";
    BIO *bio_in = NULL;
    BIO *bio_ssl, *bio_tmp;
    SSL_CTX *ctx_ssl;
    SSL_CONF_CTX *ctx_ssl_cfg = NULL;
    CONF *conf = NULL;
    STACK_OF(CONF_VALUE) *sk_of_conf_value = NULL;
    CONF_VALUE *conf_value;
    long errline = -1;
    char buf[512];
    int ret = EXIT_FAILURE, i;
    int iCfgItemCnt = 0;

    ctx_ssl = SSL_CTX_new(TLS_server_method());

    conf = NCONF_new(NULL);

    if (NCONF_load(conf, "accept.cnf", &errline) <= 0) {
        if (errline <= 0)
            fprintf(stderr, "Error processing config file\n");
        else
            fprintf(stderr, "Error on line %ld\n", errline);
        goto err;
    }

    sk_of_conf_value = NCONF_get_section(conf, "default");

    if (sk_of_conf_value == NULL) {
        fprintf(stderr, "Error retrieving default section\n");
        goto err;
    }

    ctx_ssl_cfg = SSL_CONF_CTX_new();

    // 如果需要SSL_CONF_cmd处理的配置项, 先设置标志, 告诉 SSL_CONF_cmd需要从配置文件中读什么预想的配置项名称
    SSL_CONF_CTX_set_flags(ctx_ssl_cfg, SSL_CONF_FLAG_SERVER);
    SSL_CONF_CTX_set_flags(ctx_ssl_cfg, SSL_CONF_FLAG_CERTIFICATE);
    SSL_CONF_CTX_set_flags(ctx_ssl_cfg, SSL_CONF_FLAG_FILE);
    SSL_CONF_CTX_set_ssl_ctx(ctx_ssl_cfg, ctx_ssl);

    iCfgItemCnt = sk_CONF_VALUE_num(sk_of_conf_value);
    for (i = 0; i < iCfgItemCnt; i++) {
        int rv;
        conf_value = sk_CONF_VALUE_value(sk_of_conf_value, i);
        rv = SSL_CONF_cmd(ctx_ssl_cfg, conf_value->name, conf_value->value);
        if (rv > 0)
        {
            /*! 如果是SSL配置项中指定的配置, 就会处理为true */
            continue;
        }
            
        /*! 如果是非法的配置项名称, 就会报错 */
        if (rv != -2) {
            fprintf(stderr, "Error processing %s = %s\n",
                    conf_value->name, conf_value->value);
            ERR_print_errors_fp(stderr);
            goto err;
        }

        /*! 如果是合法的配置名称, 又不是SSL配置中需要的项目, 需要自己单独处理 */
        if (strcmp(conf_value->name, "Port") == 0) {
            psz_port = conf_value->value;
        } else {
            fprintf(stderr, "Unknown configuration option %s\n", conf_value->name);
            /*! 如果不是预想的配置名称, 需要继续遍历(多行时, 预想的配置项可能没写在第一行), 而不是报错退出 */
            // goto err;
        }
    }

    if (!SSL_CONF_CTX_finish(ctx_ssl_cfg)) {
        fprintf(stderr, "Finish error\n");
        ERR_print_errors_fp(stderr);
        goto err;
    }

    /* Setup server side SSL bio */
    bio_ssl = BIO_new_ssl(ctx_ssl, 0);

    if ((bio_in = BIO_new_accept(psz_port)) == NULL)
        goto err;

    /*
     * This means that when a new connection is accepted on 'in', The ssl_bio
     * will be 'duplicated' and have the new socket BIO push into it.
     * Basically it means the SSL BIO will be automatically setup
     */
    BIO_set_accept_bios(bio_in, bio_ssl);

 again:
    /*
     * The first call will setup the accept socket, and the second will get a
     * socket.  In this loop, the first actual accept will occur in the
     * BIO_read() function.
     */

    if (BIO_do_accept(bio_in) <= 0)
        goto err;

    for (;;) {
        i = BIO_read(bio_in, buf, 512); /*! 阻塞等待客户端来连接 */
        if (i == 0) {
            /*
             * If we have finished, remove the underlying BIO stack so the
             * next time we call any function for this BIO, it will attempt
             * to do an accept
             */
            printf("Done\n");
            bio_tmp = BIO_pop(bio_in);
            BIO_free_all(bio_tmp);
            goto again;
        }
        if (i < 0) {
            if (BIO_should_retry(bio_in))
                continue;
            goto err;
        }
        fwrite(buf, 1, i, stdout);
        fflush(stdout);
    }

    ret = EXIT_SUCCESS;
 err:
    if (ret != EXIT_SUCCESS)
        ERR_print_errors_fp(stderr);
    BIO_free(bio_in);
    return ret;
}

END

相关推荐
Lazy Dave15 天前
gmssl私钥文件格式
网络安全·ssl·openssl
沉在嵌入式的鱼1 个月前
RK3588移植Openssl库
linux·rk3588·openssl
黑屋里的马1 个月前
ssl相关命令生成证书
服务器·网络·ssl·openssl·gmssl
fangeqin2 个月前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
API开发2 个月前
苹果芯片macOS安装版Homebrew(亲测) ,一键安装node、python、vscode等,比绿色软件还干净、无污染
vscode·python·docker·nodejs·openssl·brew·homebrew
码农不惑2 个月前
Rust使用tokio(二)HTTPS相关
https·rust·web·openssl
liulilittle2 个月前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法并通过OPENSSL加密验证算法正确性。
linux·服务器·c++·算法·安全·加密·openssl
liulilittle2 个月前
OpenSSL 的 AES-NI 支持机制
linux·运维·服务器·算法·加密·openssl·解密
liulilittle2 个月前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法。
linux·服务器·c++·算法·安全·加密·openssl
花花少年2 个月前
Ubuntu系统下交叉编译openssl
openssl·交叉编译