网站产品链接怎么做的浙江seo推广
文章目录
- openssl3.2 - exp - 内存操作(建立,写入,读取)配置
- 概述
- 笔记
- 调试细节
- 运行效果
- 测试工程实现
- main.cpp
- CMyOsslConfig.h
- CMyOsslConfig.cpp
- END
openssl3.2 - exp - 内存操作(建立,写入,读取)配置
概述
我的应用的配置文件是落地加密的, 无法直接用openssl配置接口载入读取.
应用先将加密的配置文件解密(openssl官方给的demo工程中有对文件的加解密例子).
从明文buffer中载入配置, 然后就可以用openssl的配置接口(BIO为入参)读取配置项的值.
做了实验, 用了1天搞定了. 封装了一个配置类. 可以在内存中建立配置, 写入配置, 读取配置.
在内存中建立配置,写入配置在服务端用.
客户端只用在内存中读取配置的接口.
笔记
调试细节
- NCONF_load_bio()执行后, 会将输入的BIO内容清掉.
- BIO_read()执行后, 如果后续不是要继续读取, 需要将数据读指针位置复原 BIO_seek(bio, 0)
- 如无必要, 不要调用BIO_seek(). 查了openssl实现, 官方用法全部是BIO_seek(bio, 0).
- 官方配置操作接口, 只有读取的接口. 因为官方用法, 都是用户自己手工编辑配置文件, openssl只需要读配置. 如果需要写配置内容, 需要自己封装(write buffer => BIO => CONF). 如果想自己确认写入BIO的内容是否正确, 可以将BIO写到文件来确认.
运行效果
[cpt_info] win_ver = win10
[cpt_info] ram = 32GB
[cfg_info] sec_cnt = 2
free mem_hook map, g_mem_hook_map.size() = 0, no openssl API call memory leak
测试工程实现
main.cpp
/*!
* \file main.cpp
*/#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>#include <openssl/conf.h> // for CONF#include "CMyOsslConfig.h"#include <stdlib.h>
#include <stdio.h>
#include <assert.h>#include "CMemHookRec.h"void my_openssl_app();int main(int argc, char** argv)
{setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞mem_hook();my_openssl_app();mem_unhook();/*! run result[cpt_info] win_ver = win10[cpt_info] ram = 32GB[cfg_info] sec_cnt = 2free mem_hook map, g_mem_hook_map.size() = 0, no openssl API call memory leak*/return 0;
}void my_openssl_app()
{CONF* conf = NULL;STACK_OF(CONF_VALUE)* sk_of_conf_value = NULL;CONF_VALUE* conf_value = NULL;CMyOsslConfig _cfg;bool b_rc = false;const char* pszVal = NULL;do {// case - wirte new config to BIO/CONFb_rc = _cfg.init(); // !!assert(b_rc);_cfg.add_config_section("cpt_info");_cfg.add_config_item_after_section("win_ver", "win10");_cfg.add_config_item_after_section("ram", "32GB");_cfg.add_config_section("cfg_info");_cfg.add_config_item_after_section("sec_cnt", "2");// 如果要将_cfg中的BIO中的东西写入文件测试(方便人工观察配置文件是否写错?), 必须要在_cfg.updateConfig()之前, 否则BIO中的东西被NCONF_load_bio()载入后清掉了// _cfg.to_file("test.cfg"); // only for test// when add config content, need update(bio to CONF)_cfg.updateConfig(); // !!// 经过_cfg.updateConfig()后, _cfg中的BIO就空了, 如果要更新配置, 就需要重新写BIO// get cofig value from CONF* inside on CMyOsslConfigpszVal = _cfg.get_conf_item_value("cpt_info", "win_ver");if (NULL != pszVal){printf("[cpt_info] win_ver = %s\n", pszVal);}pszVal = _cfg.get_conf_item_value("cpt_info", "ram");if (NULL != pszVal){printf("[cpt_info] ram = %s\n", pszVal);}pszVal = _cfg.get_conf_item_value("cfg_info", "sec_cnt");if (NULL != pszVal){printf("[cfg_info] sec_cnt = %s\n", pszVal);}} while (false);
}
CMyOsslConfig.h
//! \file CMyOsslConfig.h#ifndef __CMYOSSLCONFIG_H__
#define __CMYOSSLCONFIG_H__#include <openssl/bio.h>
#include <openssl/conf.h> // for CONFclass CMyOsslConfig
{
public:CMyOsslConfig();virtual ~CMyOsslConfig();bool init();bool add_config_section(const char* pszIn);bool add_config_item_after_section(const char* pszItemName, const char* pszItemContent);bool updateConfig();BIO* get_bio();char* get_conf_item_value(const char* group, const char* name);bool to_file(const char* psz_file_pathname); // for test onlyprivate:bool append_to_bio(uint8_t* pBuf, int lenBuf);size_t bio_get_length(BIO* bio);bool bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf);private:BIO* m_bio;CONF* m_conf;
};#endif // #ifndef __CMYOSSLCONFIG_H__
CMyOsslConfig.cpp
//! \file CMyOsslConfig.cpp#include "CMyOsslConfig.h"
#include <string.h>
#include <openssl/err.h>
#include <cassert>CMyOsslConfig::CMyOsslConfig():m_bio(NULL),m_conf(NULL)
{}CMyOsslConfig::~CMyOsslConfig()
{if (NULL != m_bio){BIO_free(m_bio);m_bio = NULL;}if (NULL != m_conf){NCONF_free(m_conf);m_conf = NULL;}
}bool CMyOsslConfig::init()
{bool b_rc = false;do {if (NULL == m_bio){m_bio = BIO_new(BIO_s_mem());if (NULL == m_bio){break;}}if (NULL == m_conf){m_conf = NCONF_new_ex(OSSL_LIB_CTX_get0_global_default(), NULL);if (NULL == m_conf){break;}}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::add_config_section(const char* pszIn)
{bool b_rc = false;char szBuf[1024];int len = 0;do {if (NULL == pszIn){break;}len = strlen(pszIn);if (len > (sizeof(szBuf) - 0x10)){break;}sprintf(szBuf, "[ %s ]\n", pszIn);if (NULL == m_bio){break;}if (!append_to_bio((uint8_t*)szBuf, strlen(szBuf))){break;}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::add_config_item_after_section(const char* pszItemName, const char* pszItemContent)
{bool b_rc = false;char szBuf[1024];int len = 0;do {if ((NULL == pszItemName) || (NULL == pszItemContent)){break;}len = (strlen(pszItemName) + strlen(pszItemContent));if (len > (sizeof(szBuf) - 0x10)){break;}sprintf(szBuf, "%s = %s\n", pszItemName, pszItemContent);if (NULL == m_bio){break;}if (!append_to_bio((uint8_t*)szBuf, strlen(szBuf))){break;}b_rc = true;} while (false);return b_rc;
}bool CMyOsslConfig::append_to_bio(uint8_t* pBuf, int lenBuf)
{bool b_rc = false;int len = 0;size_t szLen = 0;int bio_len_before = 0;int bio_len_after = 0;do {if ((NULL == pBuf) || (lenBuf <= 0)){break;}if (NULL == m_bio){break;}// szLen = bio_get_length(m_bio);// BIO_seek(m_bio, szLen);bio_len_before = bio_get_length(m_bio);len = BIO_write(m_bio, pBuf, lenBuf);bio_len_after = bio_get_length(m_bio);if (len != lenBuf){break;}if (len != (bio_len_after - bio_len_before)){break;}b_rc = true;} while (false);return b_rc;}BIO* CMyOsslConfig::get_bio()
{if (NULL != m_bio){// BIO_seek(m_bio, 0);}return m_bio;
}size_t CMyOsslConfig::bio_get_length(BIO* bio)
{size_t bio_length = 0;do {if (NULL == bio){break;}// BIO_seek(bio, 0);bio_length = BIO_ctrl_pending(bio);} while (false);return bio_length;
}bool CMyOsslConfig::updateConfig()
{bool b_rc = false;int i_rc = 0;long lineSn = 0;int len1 = 0;int len2 = 0;do {if ((NULL == m_bio) || (NULL == m_conf)){break;}// BIO_seek(m_bio, 0);// len1 = this->bio_get_length(m_bio);i_rc = NCONF_load_bio(m_conf, m_bio, &lineSn);// len2 = this->bio_get_length(m_bio);// m_bio有东西有数据长度, 但是经过NCONF_load_bio()后, m_conf里面有东西了, 但是m_bio的东西没了// 所以, 经过NCONF_load_bio后(), 就得当m_bio是空的来处理.// 如果是向m_bio中写东西, 然后写配置.// 如果要更新m_bio中的配置内容, 就必须重新写.if (i_rc <= 0){break;}b_rc = true;} while (false);return b_rc;
}char* CMyOsslConfig::get_conf_item_value(const char* group, const char* name)
{char* res = NULL;int i_rc = 0;do {if (NULL == m_conf){break;}res = NCONF_get_string(m_conf, group, name);if (NULL == res){ERR_pop_to_mark();}else {ERR_clear_last_mark();}} while (false);return res;
}bool CMyOsslConfig::to_file(const char* psz_file_pathname)
{bool b_rc = false;FILE* pf = NULL;uint8_t* pBuf = NULL;int len = 0;size_t sz_rc = 0;do {if (NULL == psz_file_pathname){break;}pf = fopen(psz_file_pathname, "wb");if (NULL == pf){break;}if (!bio_to_buf(get_bio(), pBuf, len)){break;}if ((NULL == pBuf) || (len <= 0)){break;}sz_rc = fwrite(pBuf, sizeof(char), len, pf);assert(sz_rc == len);b_rc = true;} while (false);if (NULL != pf){fclose(pf);pf = NULL;}if (NULL != pBuf){OPENSSL_free(pBuf);pBuf = NULL;}return b_rc;
}bool CMyOsslConfig::bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf)
{bool b_rc = false;int i_rc = 0;do {if (NULL == bio){break;}lenBuf = bio_get_length(bio);pBuf = (uint8_t*)OPENSSL_malloc(lenBuf + 1);if (NULL == pBuf){break;}pBuf[lenBuf] = '\0';i_rc = BIO_read(bio, pBuf, lenBuf);BIO_seek(bio, 0); // ! 读完了, 将数据读指针恢复.b_rc = (i_rc == lenBuf);} while (false);return b_rc;
}