OpenSSL之配置文件用法

OpenSSL之配置文件用法,第1张

OpenSSL配置文件采用linux风格,其文件格式由分组字段名、属性名、属性值三部分组成。

如下面的例子:

其中,属性值还支持变量替换,如该例的属性:

log = $path/log

其值最终会被替换为./module_a/log

本文假设你已经安装好了OpenSSL,并且持有一份1.1.1的源码。

配置文件相关的头文件为conf.h、源文件实现在crypto/conf目录中。

这个结构定义了单个配置项的数据结构。主要字段含义:

section —— 表示一个配置段的名称。

name —— 表示在该配置段下的属性名称。

value —— 表示对应属性的值。

这个结构定义了配置抽象方法集合。主要字段含义:

name —— 配置方法名称。

create —— 根据配置抽象方法,创建一个配置项结构,返回其指针。

init —— 初使化配置。

destroy —— 释放所有配置。

destroy_data —— 仅释放所有配置项数据,不释放配置本身。

load_bio —— 以BIO的方式加载配置。

dump —— 打印配置项到BIO中。

is_number —— 判断指定字符是否数字。

to_int —— 将字符转换为数字。

load —— 从文件(重新)加载所有配置。

这个结构定义了配置存储数据结构。主要字段含义:

meth —— 抽象方法集合。

meth_data —— 附加的内存数据,暂时还没有明确用途。

data —— 配置项哈希表。

在1.1.1中,大多数的数据结构已经不再向使用者开放,从封装的角度来看,这是更合理的。如果你在头文件中找不到结构定义,不妨去源码中搜一搜。

CONF *NCONF_new(CONF_METHOD *meth)

指定一个抽象方法集合,创建配置存储结构。

成功返回有效指针,失败返回NULL。

如果meth传入NULL,表示使用默认的抽象方法。

void NCONF_free(CONF *conf)

释放配置存储。

int NCONF_load(CONF *conf, const char *file, long *eline)

从指定文件加载配置,eline表示出错时输出的行号。

成功返回1,失败返回0。

int NCONF_load_bio(CONF *conf, BIO *bp, long *eline)

从BIO加载配置,eline表示出错时输出的行号。

成功返回1,失败返回0。

int NCONF_load_fp(CONF *conf, FILE *fp, long *eline)

NCONF_load_bio()的FILE版本。

char *NCONF_get_string(const CONF *conf, const char *group, const char *name)

从配置中,获取指定分组下的属性值。

成功返回C风格字符串,失败返回NULL。

若group传NULL,表示取全局属性。

int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, long *result)

从配置中,获取指定分组下的数字属性值,数字值输出到result中。

成功返回1,失败返回0。

若group传NULL,表示取全局属性。

STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section)

返回指定分组下的配置项堆栈集合。section不能为NULL。

成功返回有效堆栈指针,失败返回NULL。

下面这个例子演示了使用配置API进行基本的文件 *** 作。

test.cnf文件内容:

user = root

[module_a]

path = ./module_a

log = $path/log

filecount = 10

输出:

global user:[root]

module_a::path:[./module_a]

module_a::log:[./module_a/log]

ret:[1] module_a::filecount:[10]

下面这个例子演示了使用BIO读取配置文件,并且遍历指定的分组。

输出:

section:[module_a] name:[path] value:[./module_a]

section:[module_a] name:[log] value:[./module_a/log]

section:[module_a] name:[filecount] value:[10]

用户在使用内存时,容易犯的错误就是内存泄露。当用户调用内存分配和释放函数时,查找内存泄露比较麻烦。OpenSSL提供了内置的内存分配/释放函数。如果用户完全调用OpenSSL的内存分配和释放函数,可以方便的找到内存泄露点。OpenSSL分配内存时,在其内部维护一个内存分配哈希表,用于存放已经分配但未释放的内存信息。当用户申请内存分配时,在哈希表中添加此项信息,内存释放时删除该信息。当用户通过OpenSSL函数查找内存泄露点时,只需查询该哈希表即可。用户通过OpenSSL回调函数还能处理那些泄露的内存。

本文假设你已经安装好了OpenSSL,并且持有一份1.1.1的源码。

内存相关的头文件为crypto.h、源文件在crypto目录中,文件名模式为mem*.c。

这个结构定义了内存块的分配信息。主要字段含义:

addr —— 分配的内存地址。

num —— 分配的内存大小。

file —— 分配内存的文件名。

file —— 分配内存的行号。

threadid —— 分配内存的线程ID。

在1.1.1中,大多数的数据结构已经不再向使用者开放,从封装的角度来看,这是更合理的。如果你在头文件中找不到结构定义,不妨去源码中搜一搜。

int CRYPTO_set_mem_functions(

void ( m) (size_t, const char *, int),

void ( r) (void *, size_t, const char , int),

void ( f) (void *, const char , int))

成功返回1,失败返回0。

void CRYPTO_get_mem_functions(

void ( m) (size_t, const char , int),

void ( r) (void , size_t, const char , int),

void ( f) (void *, const char *, int))

这两个函数用于设置和读取与内存分配和释放相关的三个函数,这三个函数默认分别为:

static void ( malloc_impl)(size_t, const char *, int) = CRYPTO_malloc

static void ( realloc_impl)(void *, size_t, const char , int) = CRYPTO_realloc

static void ( free_impl)(void *, const char *, int) = CRYPTO_free

这两个函数只允许在内存分配前即初使化时调用。

int CRYPTO_set_mem_debug(int flag)

设置是否开启内存调试。取值1或0,1表示打开。

成功返回1,失败返回0。

只允许在内存分配前即初使化时调用。

void *CRYPTO_malloc(size_t num, const char *file, int line)

void *CRYPTO_zalloc(size_t num, const char *file, int line)

void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line)

CRYPTO_free(void *ptr, const char *file, int line)

这几个函数用于分配和释放内存。

是否记录内存与CRYPTO_set_mem_debug()的开关有关。

int CRYPTO_mem_ctrl(int mode)

这个函数用于设置是否开启内存记录模式,参数取值为:

# define CRYPTO_MEM_CHECK_OFF 0x0

# define CRYPTO_MEM_CHECK_ON 0x1

返回旧模式。

注:我没有在头文件中看到像老版函数CRYPTO_is_mem_check_on()一样可以查询当前开关状态的用法,但是通过查看源码,发现可以对CRYPTO_mem_ctrl()传递一个不存在的类型(比如-1)使其返回当前状态。

int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u), void *u)

遍历记录的内存,用于打印内存泄露信息。

返回是否有内存汇露。分别取值1和0。

int CRYPTO_mem_leaks(BIO *bio)

打印内存泄露信息,输出到BIO中。

返回是否有内存汇露。分别取值1和0。

int CRYPTO_mem_leaks_fp(FILE *)

CRYPTO_mem_leaks()的FILE版本。

由于OpenSSL内部涉及地数据结构众多,如果采用原始的内存 *** 作函数,因为涉及到文件名和行号会比较麻烦。因此,OpenSSL定义了一组宏进行包装,方便使用者进行调用。定义如下:

下面这个例子演示了使用OpenSSl内存分配API进行 *** 作。同时还用到了placement new()的用法,演示如何在openssl的内存分配串上创建c++对象。

如果在编译过程中出现下面这个错误:

testmem.cpp:40:42: 错误:‘CRYPTO_mem_leaks_cb’在此作用域中尚未声明

CRYPTO_mem_leaks_cb(memleak_cb, "aaa")

解决办法是开启debug调试编译,命令如下:

./config --prefix=/usr/local/openssl enable-crypto-mdebug enable-crypto-mdebug-backtrace

输出:

old switch:0

@SNode::SNode name:[abc] age:[18]

@SNode::~SNode name:[abc] age:[0]

leak info:[[02:21:40] 1 file=testmem.cpp, line=46, thread=140607514695488, number=36, address=0x204f090

]

##>./testmem() [0x4044e3]

##>./testmem(CRYPTO_malloc+0xa3) [0x4035e3]

##>./testmem() [0x40329c]

##>/lib64/libc.so.6(__libc_start_main+0xf5) [0x7fe1bbb77555]

##>./testmem() [0x4030f3]

leak info:[36 bytes leaked in 1 chunks

]


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11493426.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存