在学习安全传输平台项目总结了笔记,并分享出来。
10-安全传输平台项目-第08天(密钥协商设计与实现--存数据库-mfc项目创建)
一、复习
1、数据库-SQL语句、事务、游标回顾
2、数据库-访问API、查询语句API、非查询语句API
3、数据库-base64编码
二、安全传输平台项目——密钥协商设计与实现--存数据库-MFC项目创建
1、密钥协商存数据库
icdbapi.h和keymng_dbop.h放入inc目录下;keymng_dbop.c放入src目录下。
>vi keymngserverop.c
1)增加头文件icdbapi.h和keymng_dbop.h;
2)MngServer_InitInfo函数增加-初始化数据库连接池IC_DBApi_PoolInit函数;
3)MngServer_Agree函数增加-写数据库KeyMngsvr_DBOp_WriteSecKey函数;
4)MngServer_Agree函数增加-获取一条数据库连接池中的连接IC_DBApi_ConnGet函数;
5)MngServer_Agree函数增加-从数据库中获取 seckeyid的 KeyMngsvr_DBOp_GenKeyID函数;
6)MngServer_Agree函数增加-开启事务的 IC_DBApi_BeginTran函数和关闭事务的iIC_DBApi_Rollback函数;
7)MngServer_Agree函数增加-释放数据库连接到连接池IC_DBApi_ConnFree函数;
#include <stdio.h>#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "keymngserverop.h"
#include "keymng_msg.h"
#include "keymnglog.h"
#include "keymng_shmop.h"
#include "icdbapi.h"
#include "keymng_dbop.h"
//static int seckeyid = 100;
int MngServer_InitInfo(MngServer_Info *svrInfo)
{
int ret = 0;
strcpy(svrInfo->serverId, "0001");
strcpy(svrInfo->dbuse, "SECMNG");
strcpy(svrInfo->dbpasswd, "SECMNG");
strcpy(svrInfo->dbsid, "orcl");
svrInfo->dbpoolnum = 8;
strcpy(svrInfo->serverip, "127.0.0.1");
svrInfo->serverport = 8001;
svrInfo->maxnode = 10;
svrInfo->shmkey = 0x0001;
svrInfo->shmhdl = 0;
//创建/打开 共享内存
ret = KeyMng_ShmInit(svrInfo->shmkey, svrInfo->maxnode, &svrInfo->shmhdl);
if (ret != 0) {
printf("---------服务器创建/打开 共享内存失败-----\n");
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 KeyMng_ShmInit() err:%d", ret);
return ret;
}
//初始化数据库连接池
ret = IC_DBApi_PoolInit(svrInfo->dbpoolnum, svrInfo->dbsid, svrInfo->dbuse, svrInfo->dbpasswd);
if (ret != 0) {
printf("---------服务器初始化连接池失败-----\n");
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 IC_DBApi_PoolInit() err:%d", ret);
return ret;
}
return 0;
}
int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen)
{
int ret = 0;
int i = 0;
int keyid = -1;
MsgKey_Res msgKey_Res;
NodeSHMInfo nodeSHMInfo;
ICDBHandle handle = NULL;
// --结合 r1 r2 生成密钥 ---> 成功、失败 rv
if (strcmp(svrInfo->serverId, msgkeyReq->serverId) != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "客户端访问了错误的服务器");
return -1;
}
// 组织 应答结构体 res : rv r2 clientId serverId seckeyid
msgKey_Res.rv = 0; //0 成功 1 失败。
strcpy(msgKey_Res.clientId, msgkeyReq->clientId);
strcpy(msgKey_Res.serverId, msgkeyReq->serverId);
// 生成随机数 r2
for (i = 0; i < 64; i++) {
msgKey_Res.r2[i] = 'a' + i;
}
//获取一条数据库连接池中的连接
ret = IC_DBApi_ConnGet(&handle, 0, 0);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 IC_DBApi_ConnGet() err:%d", ret);
return ret;
}
//开启事务
IC_DBApi_BeginTran(handle);
//从数据库中获取 seckeyid
//msgKey_Res.seckeyid = seckeyid++;
ret = KeyMngsvr_DBOp_GenKeyID(handle, &keyid);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 KeyMngsvr_DBOp_GenKeyID() err:%d", ret);
return ret;
}
msgKey_Res.seckeyid = keyid;
// 组织密钥节点信息结构体
for (i = 0; i < 64; i++) {
nodeSHMInfo.seckey[2*i] = msgkeyReq->r1[i];
nodeSHMInfo.seckey[2*i+1] = msgKey_Res.r2[i];
}
nodeSHMInfo.status = 0; //0-有效 1无效
strcpy(nodeSHMInfo.clientId, msgkeyReq->clientId);
strcpy(nodeSHMInfo.serverId, msgkeyReq->serverId);
nodeSHMInfo.seckeyid = msgKey_Res.seckeyid;
// --写数据库
ret = KeyMngsvr_DBOp_WriteSecKey(handle, &nodeSHMInfo);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 KeyMngsvr_DBOp_WriteSecKey() err:%d", ret);
}
// 关闭事务
if (ret != 0) {
iIC_DBApi_Rollback(handle);
IC_DBApi_ConnFree(handle, 0);//释放数据库连接到连接池
return -1;
}
else if(ret == 0)
{
IC_DBApi_Commit(handle);
IC_DBApi_ConnFree(handle, 1);//释放数据库连接到连接池
}
// --写入共享内存。
ret = KeyMng_ShmWrite(svrInfo->shmhdl, svrInfo->maxnode, &nodeSHMInfo);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "服务器 KeyMng_ShmWrite() err:%d", ret);
return ret;
}
// 编码应答报文 传出
ret = MsgEncode(&msgKey_Res, ID_MsgKey_Res, outData, datalen);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "serverAgree MsgEncode() err:%d", ret);
return ret;
}
return 0;
}
int MngServer_Check(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen)
{
return 0;
}
keymngserverop.c
>vi keymngserver.c
1)增加头文件icdbapi.h;
2)main函数增加-释放数据库连接池 IC_DBApi_PoolFree()函数;
#include <stdio.h>#include <stdlib.h>#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include "poolsocket.h"
#include "keymngserverop.h"
#include "keymng_msg.h"
#include "keymnglog.h"
#include "icdbapi.h"
MngServer_Info serverInfo;
int flg = 1;
//注意定义宏的时候最后是一个整体,不能有空格!
#define CREATE_DAEMON if(fork()>0)exit(1);setsid();
void *start_routine(void * arg)
{
int ret;
int timeout = 3;
int connfd = (int)arg;
unsigned char *out = NULL;
int outlen = 0;
MsgKey_Req *pStruct_req = NULL;
int iType = 0;
unsigned char *res_outData = NULL;
int res_outDataLen = 0;
while (1) {
if (flg == 0)
break;
//服务器端端接受报文
ret = sckServer_rev(connfd, timeout, &out, &outlen);
if (ret == Sck_ErrPeerClosed) {
// 检测到 对端关闭,关闭本端。
printf("----------------ErrPeerClosed 关闭服务器\n");
break;
} else if (ret == Sck_ErrTimeOut) {
if (out != NULL) sck_FreeMem((void **)&out);
continue;
} else if (ret != 0) {
printf("未知错误\n");
break;
}
// 解码客户端 密钥请求报文 ---> cmdType
ret = MsgDecode(out, outlen, (void **)&pStruct_req, &iType);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MsgDecode() err:%d", ret);
break;
}
switch(pStruct_req->cmdType) {
case KeyMng_NEWorUPDATE:
ret = MngServer_Agree(&serverInfo, pStruct_req, &res_outData, &res_outDataLen);
case KeyMng_Check:
MngServer_Check(&serverInfo, pStruct_req, &res_outData, &res_outDataLen);
/*
case 密钥注销:
mngServer_Agree();
*/
default:
break;
}
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MngServer_Agree() err:%d", ret);
break;
}
//服务器端发送报文
ret = sckServer_send(connfd, timeout, res_outData, res_outDataLen);
if (ret == Sck_ErrPeerClosed) {
// 检测到 对端关闭,关闭本端。
printf("---ErrPeerClosed \n");
break;
} else if (ret == Sck_ErrTimeOut) {
printf("---服务器检测到本端发送数据 超时 \n");
if (out != NULL) sck_FreeMem((void **)&out);
if (pStruct_req != NULL) MsgMemFree((void **)&pStruct_req, iType);
if (res_outData != NULL) MsgMemFree((void **)&res_outData, 0);
continue;
} else if (ret != 0) {
printf("未知错误\n");
break;
}
}
if (out != NULL) sck_FreeMem((void **)&out);
if (pStruct_req != NULL) MsgMemFree((void **)&pStruct_req, iType);
if (res_outData != NULL) MsgMemFree((void **)&res_outData, 0);
sckServer_close(connfd);
return NULL;
}
void catchSignal(int signum)
{
flg = 0;
printf(" catch signal %d, process is going to die.\n", signum);
return ;
}
int main(void)
{
int listenfd;
int ret = 0;
int timeout = 3;
int connfd = -1;
pthread_t pid;
CREATE_DAEMON
signal(SIGUSR1, catchSignal);
// 服务器信息初始化。
ret = MngServer_InitInfo(&serverInfo);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MngServer_InitInfo() err:%d", ret);
return ret;
}
//服务器端初始化连接
ret = sckServer_init(serverInfo.serverport, &listenfd);
if (ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "sckServer_init() err:%d", ret);
return ret;
}
while (1) {
if (flg == 0)
break;
ret = sckServer_accept(listenfd, timeout, &connfd);
if (ret == Sck_ErrTimeOut){
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[2], ret, "---等待客户端连接超时---");
continue;
} else if(ret != 0) {
KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "sckServer_accept() err:%d", ret);
return ret;
}
ret = pthread_create(&pid, NULL, start_routine, (void *)connfd);
}
//服务器端环境释放
sckServer_destroy();
IC_DBApi_PoolFree();
printf("服务器 优雅退出。\n");
return 0;
}
keymngserver.c
>vi makefile
.PHONY:clean allWORKDIR=.VPATH = ./srcCC=gcc
CFLGS= -Wall -g -I$(WORKDIR)/inc/
LIBFLAG = -L$(HOME)/lib
BIN = keymngclient keymngserver
all:$(BIN)
keymngclient:keymngclient.o keymnglog.o keymngclientop.o myipc_shm.o keymng_shmop.o
$(CC) $(LIBFLAG) -lpthread -litcastsocket -lmessagereal $^ -o $@
keymngserver:keymngserver.o keymngserverop.o keymnglog.o myipc_shm.o keymng_shmop.o keymng_dbop.o
$(CC) $(LIBFLAG) $^ -o $@ -lpthread -litcastsocket -lmessagereal -lclntsh -licdbapi
#testdbapi:testdbapi.o
# $(CC) $(LIBFLAG) $^ -o $@ -lpthread -lclntsh -licdbapi
%.o:%.c
$(CC) $(CFLGS) -c $< -o $@
clean:
rm -f *.o $(BIN)
makefile
>make
>./keymngserver

打开另一个终端,切换到该目录下,执行>./keymngclient
连续执行3次后,打开SQL Developer查看表中数据:
>SECKYEINFO表:
>KEYSN表:
2、表外键约束导致的插入时间错误
3、密钥注销流程分析
4、4大基础组件源码
5、数据库连接池错误说明
6、配置ODBC驱动
7、ODBC驱动错误说明
8、界面框架思想
9、MFC空项目创建
10、处理源码中CUR图标对应错误
11、添加消息宏定义