安全传输平台项目——密钥协商共享内存-守护进程-脚本
在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
10-安全传输平台项目-第06天(密钥协商共享内存-守护进程-脚本)
目录:
一、复习
二、密钥协商共享内存-守护进程-脚本
1、共享内存操作函数接口设计
2、共享内存操作函数实现领读
3、生成密钥-组织密钥结构体信息
4、客户端写密钥信息到共享内存
5、服务器内存释放
6、共享内存补充说明
7、服务器守护进程创建
8、守护进程管理脚本
9、借助信号管理守护进程
10、密钥校验流程分析
一、复习
1、客户端:keymngclient.c—负责业务逻辑;keymngclientop.c—负责功能实现
2、服务器:keymngserver.c—负责业务逻辑;keymngserverop.c—负责功能实现
》密钥协商业务逻辑图:
二、安全传输平台项目——密钥协商共享内存-守护进程-脚本
1、共享内存操作函数接口设计
----共享内存 函数接口。
分析网点密钥信息 元素 --- struct shmNodeInfo{}
shmNodeInfo{ seckey, clientID, serverID, seckeyid, status, time }
模块组织关系:
客户端:
协商密钥成功,写 密钥节点信息 到 共享内存。 密钥校验, 读 取共享内存密钥信息。
服务器:
协商密钥成功,写 密钥节点信息 到 共享内存。 密钥校验, 读 取共享内存密钥信息。
存储:
服务器:struct shmNodeInfo shmInfo[N];
1
:
N
客户端:struct shmNodeInfo shmInfo;
初始化/创建共享内存
int shmInit(int shmkey, int size, int *shmhdle); int -- map(shmat) --->void *
写网点信息共享内存
int shmNode_write(int shmhdle, struct shmNodeInfo *pShmNode, int maxnode);
读网点信息共享内存
int shmNode_Read(int shmhdle, struct shmNodeInfo **pShmNode, char *clientID,char *serverID);
2、共享内存操作函数实现领读
》函数封装:shmget()--> myipc_shm.c --> keymng_shmop.c --- keymng_shmop.h
分析了keymng_shmop.h和keymng_shmop.c
>keymng_shmop.h
// keymng_shmop.h #ifndef _KEYMNG_SHMOP_H_ #define _KEYMNG_SHMOP_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif //将网点密钥信息写共享内存, 网点共享内存结构体 typedef struct _NodeSHMInfo { int status; //密钥状态 0-有效 1无效 char clientId[12]; //客户端id char serverId[12]; //服务器端id int seckeyid; //对称密钥id unsigned char seckey[128]; //对称密钥 //hash1 hash256 md5 }NodeSHMInfo; //int KeyMng_ShmInit(int keyid, int keysize, void *shmid ) //打开共享内存 共享内存存在则使用 不存在则创建(此函数并不是初始化) int KeyMng_ShmInit(int key, int maxnodenum, int *shmhdl); int KeyMng_ShmWrite(int shmhdl, int maxnodenum, NodeSHMInfo *pNodeInfo);//pNodeInfo是传入参数 int KeyMng_ShmRead(int shmhdl, char *clientId, char *serverId, int maxnodenum, NodeSHMInfo *pNodeInfo);//pNodeInfo是传出参数 #ifdef __cplusplus } #endif #endif
>keymng_shmop.c
#include <unistd.h> #include <sys/types.h> #include <signal.h> #include <sys/wait.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include "keymnglog.h" #include "keymng_shmop.h" #include "myipc_shm.h" #include "keymngclientop.h" //查看共享内存是否存在 //若 存在使用旧 //若 不存在创建 int KeyMng_ShmInit(int key, int maxnodenum, int *shmhdl) { int ret = 0; //打开共享内存 ret = IPC_OpenShm(key, maxnodenum*sizeof(NodeSHMInfo), shmhdl); if (ret == MYIPC_NotEXISTErr) { printf("keymng监测到共享内存不存在 正在创建共享内存...\n"); ret = IPC_CreatShm(key, maxnodenum*sizeof(NodeSHMInfo), shmhdl); if (ret != 0) { printf("keymng创建共享内存 err:%d \n", ret); return ret; } else { void *mapaddr = NULL; printf("keymng创建共享内存 ok...\n"); ret = IPC_MapShm(*shmhdl, (void **) &mapaddr); if (ret != 0) { printf("fun IPC_MapShm() err:%d 清空共享内存失败\n", ret); return ret; } memset(mapaddr, 0, maxnodenum*sizeof(NodeSHMInfo)); IPC_UnMapShm(mapaddr); printf("keymng清空共享内存ok\n"); } } else if (ret == 0) { printf("keymng监测到共享内存存在 使用旧的共享内存...\n"); } else { printf("fun IPC_OpenShm() err:%d\n", ret); } return ret; } //写网点密钥 //若存在 则修改 //若不存在 则找一个空的位置写入 int KeyMng_ShmWrite(int shmhdl, int maxnodenum, NodeSHMInfo *pNodeInfo) { int ret = 0, i = 0; NodeSHMInfo tmpNodeInfo; //空结点 NodeSHMInfo *pNode = NULL; void *mapaddr = NULL; memset(&tmpNodeInfo, 0, sizeof(NodeSHMInfo)); //连接共享内存 ret = IPC_MapShm(shmhdl, (void **) &mapaddr); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IPC_MapShm() err"); goto End; } //判断传入的网点密钥 是否已经 存在 for (i=0; i<maxnodenum; i++) { pNode = mapaddr + sizeof(NodeSHMInfo)*i; if (strcmp(pNode->clientId, pNodeInfo->clientId) == 0 && strcmp(pNode->serverId, pNodeInfo->serverId) == 0 ) { KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[3], ret,"系统检测到 共享内存中已经存在网点信息cliented:%s serverid%s", pNode->clientId, pNode->serverId); memcpy(pNode, pNodeInfo, sizeof(NodeSHMInfo)); goto End; } } //若不存在 for (i=0; i<maxnodenum; i++) { pNode = mapaddr + sizeof(NodeSHMInfo)*i; if (memcmp(&tmpNodeInfo, pNode, sizeof(NodeSHMInfo)) == 0 ) { KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[3], ret,"系统检测到 有一个空的位置 "); memcpy(pNode, pNodeInfo, sizeof(NodeSHMInfo)); goto End; } } if (i == maxnodenum) { ret = 1111; KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"系统检测到共享内存已满 "); goto End; } End: IPC_UnMapShm(mapaddr); return ret; } //根据clientid和serverid 去读网点信息 int KeyMng_ShmRead(int shmhdl, char *clientId, char *serverId, int maxnodenum, NodeSHMInfo *pNodeInfo) { int ret = 0, i = 0; NodeSHMInfo tmpNodeInfo; //空结点 NodeSHMInfo *pNode = NULL; void *mapaddr = NULL; memset(&tmpNodeInfo, 0, sizeof(NodeSHMInfo)); //连接共享内存 ret = IPC_MapShm(shmhdl, (void **) &mapaddr); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"func IPC_MapShm() err"); goto End; } //遍历网点信息 for (i=0; i<maxnodenum; i++) { pNode = mapaddr + sizeof(NodeSHMInfo)*i; if ( strcmp(pNode->clientId, clientId) == 0 && strcmp(pNode->serverId, serverId) == 0 ) { KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[3], ret,"系统检测到 有一个空的位置 "); memcpy(pNodeInfo, pNode, sizeof(NodeSHMInfo)); goto End; } } if (i == maxnodenum) { ret = 1111; KeyMng_Log(__FILE__, __LINE__,KeyMngLevel[4], ret,"系统检测到共享内存已满 "); goto End; } End: IPC_UnMapShm(mapaddr); return ret; }
》网点密钥信息结构体 --- struct shmNodeInfo{}
shmNodeInfo{ seckey, clientID, serverID, seckeyid, status, time }
clientid serverid status seckeyid time seckey
1111 0001 1 100 2017/7/2 a1b2c3
2222 0001 1 101 2017/7/4 abc123
3333 0001 1 102 2017/7/1 ab12c3
4444 0001 1 105 2017/7/3 a1bc23
》存共享内存分析图:
3、生成密钥-组织密钥结构体信息
》生成密钥:
1)借助开源算法 md5 sha1 sha256
2) 自定义算法:
123 abc a1b2c3
abc abc aabbcc
将keymng_shmop.h放入./secmng/inc/目录下,keymng_shmop.c放入./secmng/src/目录下。
>vi keymngclientop.c
1)将头文件"keymng_shmop.h"包含
2)在MngClient_InitInfo中调用KeyMng_ShmInit
3)在MngClient_Agree中组织密钥结构体信息
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymnglog.h" #include "poolsocket.h" #include "keymng_msg.h" #include "keymngclientop.h" #include "keymng_shmop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { int ret = 0; strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; ret = KeyMng_ShmInit(pCltInfo->shmkey, pCltInfo->maxnode, &pCltInfo->shmhdl); if (ret != 0) { printf("---------客户端创建/打开 共享内存失败-----\n"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "KeyMng_ShmInit() err:%d", ret); return 0; } return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { int i = 0; int ret = 0; int time = 3; int connfd = -1; // 存放编码 TLV 完成的 req unsigned char *msgKey_Req_Data = NULL; int msgKey_Req_DataLen = 0; // 存放编码 TLV 完成的 res unsigned char *msgKey_Res_Data = NULL; int msgKey_Res_DataLen = 0; MsgKey_Res *pStruct_Res = NULL; int iType = 0; // 初始化密钥请求结构体 MsgKey_Req msgKey_req; msgKey_req.cmdType = KeyMng_NEWorUPDATE; strcpy(msgKey_req.clientId, pCltInfo->clientId); strcpy(msgKey_req.AuthCode, pCltInfo->AuthCode); strcpy(msgKey_req.serverId, pCltInfo->serverId); // 产生随机数 c: abcdefg s: abcdefg aabbccddeeffgg for (i = 0; i < 64; i++) { msgKey_req.r1[i] = 'a' + i; } // 编码密钥请求 结构体 req ret = MsgEncode(&msgKey_req, ID_MsgKey_Req, &msgKey_Req_Data, &msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgEncode() err:%d", ret); goto END; } // 初始化建立连接函数 ret = sckClient_init(); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_init() err:%d", ret); goto END; } // 创建连接。 ret = sckClient_connect(pCltInfo->serverip, pCltInfo->serverport, time, &connfd); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_connect() err:%d", ret); goto END; } // 发送数据 TLV ret = sckClient_send(connfd, time, msgKey_Req_Data, msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_send() err:%d", ret); goto END; } // ---- 等待服务器回发数据 // 接收数据 ret = sckClient_rev(connfd, time, &msgKey_Res_Data, &msgKey_Res_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_rev() err:%d", ret); goto END; } // 解码密钥应答 结构体 res ---> rv r2 ret = MsgDecode(msgKey_Res_Data, msgKey_Res_DataLen, (void **)&pStruct_Res, &iType); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgDecode() err:%d", ret); goto END; } if (pStruct_Res->rv != 0) { ret = -1; goto END; } else if (pStruct_Res->rv == 0) { printf("---当前生成的密钥编号为:%d\n", pStruct_Res->seckeyid); } // --组织密钥信息结构体 NodeSHMInfo nodeSHMInfo; // --利用 r1 r2 生成密钥 for (i = 0; i < 64; i++) { nodeSHMInfo.seckey[2*i] = msgKey_req.r1[i]; nodeSHMInfo.seckey[2*i+1] = pStruct_Res->r2[i]; } nodeSHMInfo.status = 0; //0-有效 1无效 strcpy(nodeSHMInfo.clientId, msgKey_req.clientId); strcpy(nodeSHMInfo.serverId, msgKey_req.serverId); nodeSHMInfo.seckeyid = pStruct_Res->seckeyid; // --写入共享内存。 END: if (msgKey_Req_Data != NULL) MsgMemFree((void **)&msgKey_Req_Data, 0); if (msgKey_Res_Data != NULL) MsgMemFree((void **)&msgKey_Res_Data, 0); if (pStruct_Res != NULL) MsgMemFree((void **)&pStruct_Res, iType); return ret; }
4、客户端写密钥信息到共享内存
>vi keymngclientop.c
在MngClient_Agree中调用写入共享内存的函数KeyMng_ShmWrite
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymnglog.h" #include "poolsocket.h" #include "keymng_msg.h" #include "keymngclientop.h" #include "keymng_shmop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { int ret = 0; strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; ret = KeyMng_ShmInit(pCltInfo->shmkey, pCltInfo->maxnode, &pCltInfo->shmhdl); if (ret != 0) { printf("---------客户端创建/打开 共享内存失败-----\n"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "KeyMng_ShmInit() err:%d", ret); return 0; } return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { int i = 0; int ret = 0; int time = 3; int connfd = -1; // 存放编码 TLV 完成的 req unsigned char *msgKey_Req_Data = NULL; int msgKey_Req_DataLen = 0; // 存放编码 TLV 完成的 res unsigned char *msgKey_Res_Data = NULL; int msgKey_Res_DataLen = 0; MsgKey_Res *pStruct_Res = NULL; int iType = 0; // 初始化密钥请求结构体 MsgKey_Req msgKey_req; msgKey_req.cmdType = KeyMng_NEWorUPDATE; strcpy(msgKey_req.clientId, pCltInfo->clientId); strcpy(msgKey_req.AuthCode, pCltInfo->AuthCode); strcpy(msgKey_req.serverId, pCltInfo->serverId); // 产生随机数 c: abcdefg s: abcdefg aabbccddeeffgg for (i = 0; i < 64; i++) { msgKey_req.r1[i] = 'a' + i; } // 编码密钥请求 结构体 req ret = MsgEncode(&msgKey_req, ID_MsgKey_Req, &msgKey_Req_Data, &msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgEncode() err:%d", ret); goto END; } // 初始化建立连接函数 ret = sckClient_init(); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_init() err:%d", ret); goto END; } // 创建连接。 ret = sckClient_connect(pCltInfo->serverip, pCltInfo->serverport, time, &connfd); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_connect() err:%d", ret); goto END; } // 发送数据 TLV ret = sckClient_send(connfd, time, msgKey_Req_Data, msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_send() err:%d", ret); goto END; } // ---- 等待服务器回发数据 // 接收数据 ret = sckClient_rev(connfd, time, &msgKey_Res_Data, &msgKey_Res_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_rev() err:%d", ret); goto END; } // 解码密钥应答 结构体 res ---> rv r2 ret = MsgDecode(msgKey_Res_Data, msgKey_Res_DataLen, (void **)&pStruct_Res, &iType); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgDecode() err:%d", ret); goto END; } if (pStruct_Res->rv != 0) { ret = -1; goto END; } else if (pStruct_Res->rv == 0) { printf("---当前生成的密钥编号为:%d\n", pStruct_Res->seckeyid); } // --组织密钥信息结构体 NodeSHMInfo nodeSHMInfo; // --利用 r1 r2 生成密钥 for (i = 0; i < 64; i++) { nodeSHMInfo.seckey[2*i] = msgKey_req.r1[i]; nodeSHMInfo.seckey[2*i+1] = pStruct_Res->r2[i]; } nodeSHMInfo.status = 0; //0-有效 1无效 strcpy(nodeSHMInfo.clientId, msgKey_req.clientId); strcpy(nodeSHMInfo.serverId, msgKey_req.serverId); nodeSHMInfo.seckeyid = pStruct_Res->seckeyid; // --写入共享内存。 ret = KeyMng_ShmWrite(pCltInfo->shmhdl, pCltInfo->maxnode, &nodeSHMInfo); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "KeyMng_ShmWrite() err:%d", ret); goto END; } printf("--------------写共享内存完成------\n"); END: if (msgKey_Req_Data != NULL) MsgMemFree((void **)&msgKey_Req_Data, 0); if (msgKey_Res_Data != NULL) MsgMemFree((void **)&msgKey_Res_Data, 0); if (pStruct_Res != NULL) MsgMemFree((void **)&pStruct_Res, iType); return ret; }
>vi makefile
.PHONY:clean all WORKDIR=. VPATH = ./src CC=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 $@ #myipc_shm.o keymng_shmop.o keymng_dbop.o -lclntsh -licdbapi keymngserver:keymngserver.o keymngserverop.o keymnglog.o $(CC) $(LIBFLAG) $^ -o $@ -lpthread -litcastsocket -lmessagereal #testdbapi:testdbapi.o # $(CC) $(LIBFLAG) $^ -o $@ -lpthread -lclntsh -licdbapi %.o:%.c $(CC) $(CFLGS) -c $< -o $@ clean: rm -f *.o $(BIN)
>make
>./keymngclient
打开另一个终端,执行>./keymngserver,分别查看终端执行情况。
客户端情况:(输入:1):
“Ctrl+c”结束进程后,>ipcs 查看共享内存的创建情况
服务器端情况:
》同理,将服务器添加共享内存:
>vi keymngserverop.c
#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" 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; } return 0; } int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen) { int ret = 0; int i = 0; MsgKey_Res msgKey_Res; NodeSHMInfo nodeSHMInfo; // --结合 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; } msgKey_Res.seckeyid = seckeyid++; // 组织密钥节点信息结构体 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 = 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; }
>vi makefile
.PHONY:clean all WORKDIR=. VPATH = ./src CC=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 $@ # keymng_dbop.o -lclntsh -licdbapi keymngserver:keymngserver.o keymngserverop.o keymnglog.o myipc_shm.o keymng_shmop.o $(CC) $(LIBFLAG) $^ -o $@ -lpthread -litcastsocket -lmessagereal #testdbapi:testdbapi.o # $(CC) $(LIBFLAG) $^ -o $@ -lpthread -lclntsh -licdbapi %.o:%.c $(CC) $(CFLGS) -c $< -o $@ clean: rm -f *.o $(BIN)
5、服务器内存释放
>free(在该释放内存的地方加入 相应创建的函数中寻找释放内存的函数)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include "poolsocket.h" #include "keymngserverop.h" #include "keymng_msg.h" #include "keymnglog.h" MngServer_Info serverInfo; 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) { //服务器端端接受报文 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; } int main(void) { int listenfd; int ret = 0; int timeout = 3; int connfd = -1; pthread_t pid; // 服务器信息初始化。 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) { 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(); return 0; }
>make
>./keymngclient
打开另一个终端,执行>./keymngserver,分别查看终端执行情况。
客户端情况:(输入:1):
服务器端情况:
打开第三个终端,输入>ipcs,查看共享内存:
6、共享内存补充说明
问题:密钥协商业务逻辑图中两块共享内存是一块吗?有什么关系吗?
分析:服务器和客户端是两个PC,两个共享内存是分别在不同的PC的内核区创建的,图中上边的共享内存(服务器的共享内存)用于app1和keymngserver进行通信,图中下边的的共享内存(客户端的共享内存)用于app2和keymngclient进行通信。而这两个共享内存没有任何关系!
7、服务器守护进程创建
问题:当>./keymngserver 运行时,当前终端,不能输入shell指令,完全被服务器进程占据?
解决:守护进程。
》守护进程创建:
守护进程:
运行于操作系统后台的服务进程。周期性的执行某个任务,或者等待某些事件发生。
不占用控制终端。不随用户的注销而结束、退出。 通常以 d 结尾命名。 daemon
位于一个新会话中。新的进程组。 脱离控制终端。
1. fork 子进程, 父进程exit。
2. 子进程 调用 setsid()创建新会话。 成为会长。进程组组长。 子进程 pid。
3. 修改工作目录位置。防止可执行占用可卸载磁盘空间。 chdir();
4. 设定 创建文件的权限 掩码 umask
5. 关闭/重定向(dup2) 0/1/2 --> /dev/null ---- /dev/zero
6. 守护进程 循环逻辑。
7. 守护进程管理。———— 脚本
>vi keymngserver.c(添加守护进程CREATE_DAEMON)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include "poolsocket.h" #include "keymngserverop.h" #include "keymng_msg.h" #include "keymnglog.h" MngServer_Info serverInfo; //注意定义宏的时候最后是一个整体,不能有空格! #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) { //服务器端端接受报文 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; } int main(void) { int listenfd; int ret = 0; int timeout = 3; int connfd = -1; pthread_t pid; CREATE_DAEMON // 服务器信息初始化。 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) { 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(); return 0; }
>make
>./keymngserver
8、守护进程管理脚本
问题抛出:当服务器进程变为守护进程后,无法使用Ctrl+c 结束服务器进程,只能通过>ps aux | grep keymngserver 查到pid,然后 kill -9 pid。但是用户怎么办?用户无法结束服务器进程?
所以,采用shell脚本。
》shell脚本:
集成 一系列 shell命令。组织到一个文件中。统一运行。
第一行: 指定解析器。 #!/bin/bash /bin/shell
awk 处理列
sed 处理行
在UltraEdit中编辑文件:
>touch myshell
#! /bin/bash ls -l date echo $HOME
>ls -l myshell
>chmod a+x myshell
但是运行脚本,会报错:
分析:错误由于wind和Linux换行不一致造成的:
windows \r\n
---
Linux \n \r --> ^M
解决:
vim --> :set ff=unix(fileformat可以简写为ff)
再次执行>./myshell
但是,在myshell新增加行,设置就失效了,
法一:把set ff=unix写到vim的配置文件vimrc中;
法二:在Linux中写脚本
如何提取pid?如何提取服务器进程?(-u指定用户,awk指定列,$1指定第一列)
>ps -u test04 | grep keymngserver | awk '{print $1}'
》获取 命令结果:(两种方式,常用第二种)
src=$(whoami)
src=`whoami` --> “反引号”
>vi myshell
#! /bin/bash userN=`whoami` mypid=`ps -u ${userN} | grep keymngserver | awk '{print $1}'` if [ -z ${mypid} ];then echo "The process is not started." exit 1; fi kill -9 ${mypid} echo "kill keymngserver successful"
如果启动服务器>./keymngserver,执行>./myshell
9、借助信号管理守护进程
问题抛出:当服务器进程当运行在某处时,执行>./myshell,服务器进程终止,导致可能服务器正和客户端协商,终止了,导致共享内存,堆空间都消失了;服务器里边某些内存没释放,某些进程没有正常终止?
查看kill -l 中这几个信号:
>man sigaction(设置信号捕捉)
>man signal
》加入信号捕捉函数:signal(SIGUSR1, catchSignal);
>vi keymngserver.c
#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" 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(); printf("服务器 优雅退出。\n"); return 0; }
>vi myshell(更改为发送10号信号)
#! /bin/bash userN=`whoami` mypid=`ps -u ${userN} | grep keymngserver | awk '{print $1}'` if [ -z ${mypid} ];then echo "The process is not started." exit 1; fi kill -10 ${mypid} echo "kill keymngserver successful"
>make
>./keymngserver
打开另一个终端,执行>./myshell,
查看服务器端:
10、密钥校验流程分析
密钥校验:
》服务器:
int MngServer_check() { //读出 密钥请求结构体中 r1[] (10字节的密钥数据) //依据 clientid、serverid 读共享内存 --> seckey 密钥 --> 提取前10字节 --> 比较 //根据比较结果填充 res.rv //组织密钥应答结构体 res 其他成员变量 //编码密钥应答结构体 --> 传出。 }
》客户端:
校验方法:
1. a1b2c3 --> 再加密(非对称加密)--> jqk678
2. 片段校验法: 0-10 密钥信息一致 --> 一致。
int MngServer_check() { //读共享内存 --> seckey 密钥 --> 提取前10字节 --> req.r1[]; //组织密钥请求结构体(校验的事) //编码密钥请求结构体 req //初始化连接 --> listenfd //建立连接 --> connfd //发送请求报文 --> TLV send //接收应答报文 --> fwq TLV res //解析应答报文 --> TLV --> Struct --> rv --> 0 一致 1 不一致。 //给用户返回校验结果。 }
在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
posted on 2020-07-29 09:57 Alliswell_WP 阅读(321) 评论(0) 编辑 收藏 举报