微信导航网站怎么做,前端菜鸟教程,任家房网站建设,合肥有没有做网站的单位文章目录 openssl3.2 - exp - 内存操作(建立,写入,读取)配置概述笔记调试细节运行效果测试工程实现main.cppCMyOsslConfig.hCMyOsslConfig.cppEND openssl3.2 - exp - 内存操作(建立,写入,读取)配置
概述
我的应用的配置文件是落地加密的, 无法直接用openssl配置接口载入读取… 文章目录 openssl3.2 - exp - 内存操作(建立,写入,读取)配置概述笔记调试细节运行效果测试工程实现main.cppCMyOsslConfig.hCMyOsslConfig.cppEND 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.hvoid 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 cassertCMyOsslConfig::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;
}END