文章目录
- 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中赋值到变量.
笔记
/*!
\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");elsefprintf(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;
}