0
点赞
收藏
分享

微信扫一扫

安全传输平台项目——密钥协商共享内存-守护进程-脚本


在学习安全传输平台项目总结了笔记,并分享出来

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 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

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_02

分析了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.h

>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;

}

keymng_shmop.c

 

》网点密钥信息结构体            --- 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

》存共享内存分析图:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_03

 

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;
}

keymngclientop.c

 

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;
}

keymng_shmop.c

 >vi makefile



.PHONY:clean allWORKDIR=.VPATH = ./srcCC=gccCFLGS= -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)

makefile

 

>make

>./keymngclient

打开另一个终端,执行>./keymngserver,分别查看终端执行情况。

客户端情况:(输入:1):

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_04

“Ctrl+c”结束进程后,>ipcs 查看共享内存的创建情况

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_05

服务器端情况:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_06

 

》同理,将服务器添加共享内存:

>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;
}

keymngserverop.c

>vi makefile


.PHONY:clean allWORKDIR=.VPATH = ./srcCC=gccCFLGS= -Wall -g -I$(WORKDIR)/inc/LIBFLAG = -L$(HOME)/libBIN = 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)

makefile

 

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;
}

keymngserver.c

>make

>./keymngclient

打开另一个终端,执行>./keymngserver,分别查看终端执行情况。

客户端情况:(输入:1):

安全传输平台项目——密钥协商共享内存-守护进程-脚本_共享内存_07

服务器端情况:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_08

打开第三个终端,输入>ipcs,查看共享内存:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_09

 

6、共享内存补充说明

问题:密钥协商业务逻辑图中两块共享内存是一块吗?有什么关系吗?

分析:服务器和客户端是两个PC,两个共享内存是分别在不同的PC的内核区创建的,图中上边的共享内存(服务器的共享内存)用于app1和keymngserver进行通信,图中下边的的共享内存(客户端的共享内存)用于app2和keymngclient进行通信。而这两个共享内存没有任何关系!

 

7、服务器守护进程创建

问题:当>./keymngserver 运行时,当前终端,不能输入shell指令,完全被服务器进程占据?

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_10

解决:守护进程。

》守护进程创建:
    守护进程:
        运行于操作系统后台的服务进程。周期性的执行某个任务,或者等待某些事件发生。
        不占用控制终端。不随用户的注销而结束、退出。  通常以 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;
}

keymngserver.c

>make

>./keymngserver

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_11

 

8、守护进程管理脚本

问题抛出:当服务器进程变为守护进程后,无法使用Ctrl+c 结束服务器进程,只能通过>ps aux | grep keymngserver 查到pid,然后 kill -9 pid。但是用户怎么办?用户无法结束服务器进程?

所以,采用脚本。

》shell脚本:
    集成 一系列 shell命令。组织到一个文件中。统一运行。
    第一行: 指定解析器。  #!/bin/bash   /bin/shell
    awk 处理列
    sed 处理行

在UltraEdit中编辑文件:

>touch myshell


#! /bin/bashls -ldateecho $HOME


>ls -l myshell

>chmod a+x myshell

安全传输平台项目——密钥协商共享内存-守护进程-脚本_共享内存_12

但是运行脚本,会报错:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_13

分析:错误由于wind和Linux换行不一致造成的:

    windows         \r\n       

    ---

    Linux            \n    \r --> ^M    

解决:

    vim        --> :set ff=unix(fileformat可以简写为ff)

安全传输平台项目——密钥协商共享内存-守护进程-脚本_共享内存_14

再次执行>./myshell

安全传输平台项目——密钥协商共享内存-守护进程-脚本_共享内存_15

但是,在myshell新增加行,设置就失效了,

法一:把set ff=unix写到vim的配置文件vimrc中;

法二:在Linux中写脚本

如何提取pid?如何提取服务器进程?(-u指定用户,awk指定列,$1指定第一列)

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_16

>ps -u test04 | grep keymngserver | awk '{print $1}'

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_17

》获取 命令结果:(两种方式,常用第二种)
    src=$(whoami)
    src=`whoami`  --> “反引号”

>vi myshell


#! /bin/bashuserN=`whoami`mypid=`ps -u ${userN} | grep keymngserver | awk '{print $1}'`if [ -z ${mypid} ];then    echo "The process is not started."    exit 1;fikill -9 ${mypid}echo "kill keymngserver successful"


如果启动服务器>./keymngserver,执行>./myshell

 

9、借助信号管理守护进程

问题抛出:当服务器进程当运行在某处时,执行>./myshell,服务器进程终止,导致可能服务器正和客户端协商,终止了,导致共享内存,堆空间都消失了;服务器里边某些内存没释放,某些进程没有正常终止?

查看kill -l 中这几个信号:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_18

 

>man sigaction(设置信号捕捉)

安全传输平台项目——密钥协商共享内存-守护进程-脚本_#include_19

>man signal

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_20

 

》加入信号捕捉函数: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;
}

keymngserver.c

>vi myshell(更改为发送10号信号)



#! /bin/bashuserN=`whoami`mypid=`ps -u ${userN} | grep keymngserver | awk '{print $1}'`if [ -z ${mypid} ];then echo "The process is not started." exit 1;fikill -10 ${mypid}echo "kill keymngserver successful"

myshell

>make

>./keymngserver

打开另一个终端,执行>./myshell,

安全传输平台项目——密钥协商共享内存-守护进程-脚本_共享内存_21

查看服务器端:

安全传输平台项目——密钥协商共享内存-守护进程-脚本_守护进程_22

 

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 不一致。 //给用户返回校验结果。 }


 

 

在学习安全传输平台项目总结了笔记,并分享出来

举报

相关推荐

0 条评论