2018-11-09-Demo之C语言使用OpenSSL建立SSL的TLS连接

Demo之C语言使用OpenSSL建立SSL的TLS连接

使用开源的OpenSSL

初始准备

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <curl.h>
#include <netdb.h>
#include <sys/sysinfo.h>
#include <signal.h>
#include "openssl/rsa.h"
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/rand.h"
/*所有需要的参数信息都在此处以#define的形式提供*/
#define CERTF "/bin/client.crt" /*客户端的证书(需经CA签名)*/
#define KEYF "/bin/client.key" /*客户端的私钥(建议加密存储)*/
#define CACERT "ca.crt" /*CA 的证书*/
// #define PORT 9090 /*服务端的端口*/
// #define SERVER_ADDR "data.xxx.com" /*服务段的IP地址*/
SSL* ssl;
#define CHK_NULL(x) if ((x)==NULL) exit (-1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(-2); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(-3); }
// #define LOGFILE "/dev/console"
// // #define LOG(fmt, arg...)
// #define LOG(fmt, arg...) do { FILE *log_fp = fopen(LOGFILE, "w+"); \
// fprintf(log_fp, "%s:%s:%d:" fmt "\n", __FILE__, __func__, __LINE__, ##arg); \
// printf("[%s:%d]" fmt"\n", __FILE__, __LINE__, ##arg);\
// fclose(log_fp); \
// } while(0)
//测试环境
#define TEST_TCP_SERVER "10.10.10.100"
#define TEST_TCP_PORT 8888
#define TEST_MSG_SERVER "http://10.10.10.100:38080"
#define TEST_UPLOAD_SERVER "https://data.xxx.com:36443/voiceUploadByDev"
#define TEST_MP3_SERVER "http://10.10.10.100:38080"
long getuptimestamp()
{
struct sysinfo info_now;
memset(&info_now, 0 ,sizeof(struct sysinfo));
sysinfo(&info_now);
return info_now.uptime;
}
void copyname(char *name,char *str,int len)
{
if( strlen(str) > len-1 )
strncpy( name,str,len-1);
else
strcpy( name,str );
}
void to_lower(char *str)
{
int i=0;
while(str[i]!=0)
{
if((str[i]>='A')&&(str[i]<='Z'))
str[i]+=32;
i++;
}
}
void to_upper(char *str)
{
int i=0;
while(str[i]!=0)
{
if((str[i]>='a')&&(str[i]<='z'))
str[i]-=32;
i++;
}
}
void to_erasing(char *str, char *pBuf)
{
int i = 0, j = 0;
while(str[i] != 0)
{
if(str[i] != ':')
{
pBuf[j] = str[i];
j++;
}
i++;
}
LOG("pBuf:%s\n", pBuf);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
void* HelloThread(void *arg);
pthread_t syshellothreadhandle = 0; //和服务器通讯
if( syshellothreadhandle == 0 )
{
pthread_create( &syshellothreadhandle, NULL, HelloThread, NULL );
}
void* HelloThread(void *arg)
{
LOG("------- HelloThread -------\n");

struct sockaddr_in addr_client;
struct sockaddr_in addr_server;
int nLen = 1024*60;
char *msg = (char *)malloc(nLen);
memset(msg, 0, nLen);

int nBleCount = 0;
int nLedKey = 0;
int nLedKey_mode = 0;
//LOG("****************sayHelloII 1******************\n\n");
while(1)
{
//LOG("****************sayHelloII 2******************\n\n");
g_test_register_states = 0;
connectstatus = 0;
hearttimerecv = getuptimestamp();
hearttimesend = hearttimerecv;
pushtime = hearttimerecv;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int err;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
// SSL* ssl;
X509* server_cert;
char* str;
// char buf [4096];
SSL_METHOD *meth;
int seed_int[100]; /*存放随机序列*/

// WSADATA wsaData;

// if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0){
// LOG("WSAStartup()fail:%d\n",GetLastError());
// return -1;
// }

OpenSSL_add_ssl_algorithms(); /*初始化*/
SSL_load_error_strings(); /*为打印调试信息作准备*/

meth = TLSv1_client_method(); /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
ctx = SSL_CTX_new (meth);
CHK_NULL(ctx);

// SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /*验证与否*/
// SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/


if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
sleep(3);
continue;
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
sleep(3);
continue;
}

if (!SSL_CTX_check_private_key(ctx)) {
LOG("Private key does not match the certificate public key\n");
sleep(3);
continue;
}

/*构建随机数生成机制,WIN32平台必需*/
srand( (unsigned)time( NULL ) );
int i = 0;
for( i = 0; i < 100; i++ )
seed_int[i] = rand();
RAND_seed(seed_int, sizeof(seed_int));

/*以下是正常的TCP socket建立过程 .............................. */
LOG("Begin tcp socket...\n");

sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(sd, "socket");


memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
//sa.sin_addr.s_addr = inet_addr (SERVER_ADDR); /* Server IP */
LOG("TEST_TCP_SERVER:%s\n", TEST_TCP_SERVER);
if( strstr(TEST_TCP_SERVER,"xxx.com") )
{
struct hostent *phost = gethostbyname(TEST_TCP_SERVER);
if( !phost )
{
// LOG("gethostbyname error client_socket:%d.\n", client_socket);
// if(client_socket > 0)
// close( client_socket );
// client_socket = -1;
sleep(3);
continue;
}
char str[32];
memset(str,0,32);
strcpy(str, inet_ntoa(*((struct in_addr*)(phost->h_addr)) ) );
LOG("%s:------%s\n",TEST_TCP_SERVER, str);
sa.sin_addr.s_addr=inet_addr(str);
}
else
{
sa.sin_addr.s_addr=inet_addr(TEST_TCP_SERVER);
}
sa.sin_port = htons (PORT); /* Server Port number */

err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa));
CHK_ERR(err, "connect");

/* TCP 链接已建立.开始 SSL 握手过程.......................... */
LOG("Begin SSL negotiation \n");

ssl = SSL_new (ctx);
CHK_NULL(ssl);

SSL_set_fd (ssl, sd);
err = SSL_connect (ssl);
CHK_SSL(err);

/*打印所有加密算法的信息(可选)*/
LOG ("SSL connection using %s\n", SSL_get_cipher (ssl));

/*得到服务端的证书并打印些信息(可选) */
server_cert = SSL_get_peer_certificate (ssl);
CHK_NULL(server_cert);
LOG ("Server certificate:\n");

str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
CHK_NULL(str);
LOG ("/t subject: %s\n", str);
// Free (str);

str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);
CHK_NULL(str);
LOG ("/t issuer: %s\n", str);

// Free (str);

// X509_free (server_cert); /*如不再需要,需将证书释放 */

/* 数据交换开始,用SSL_write,SSL_read代替write,read */
LOG("Begin SSL data exchange\n");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

nLedKey = 0;

LOG("----- connect ok ----\n");
int res = regist();
LOG("regist RES = %d.................\n",res);
if( res == 1 )
{
}
else if( res == 1000 )
{
// close( client_socket );

SSL_shutdown (ssl); /* send SSL/TLS close_notify */
/* 收尾工作 */
sd = -1;
shutdown (sd,2);
SSL_free (ssl);
SSL_CTX_free (ctx);

// client_socket = -1;
sleep(3);
continue;
}
else
{
// close( client_socket );

SSL_shutdown (ssl); /* send SSL/TLS close_notify */
/* 收尾工作 */
sd = -1;
shutdown (sd,2);
SSL_free (ssl);
SSL_CTX_free (ctx);

// client_socket = -1;
if(msg)
free(msg);
return NULL;
}
if(atoi(szRun) == 0)
{
char szBuf[120] = "\0";
memset(szBuf, 0, sizeof(szBuf));
sprintf(szBuf, "connectok.mp3");

pthread_t prompt_thread;
pthread_create( &prompt_thread, NULL, prompt_play, (void *)szBuf);

}

g_test_register_states = 1;

//获取设备信息
char sDid[64];
memset(sDid,0,64);

int toType;
getSdevice(g_boxsettings.toCallUser,g_boxsettings.sDid,&toType);


char szTempMac[32] = "\0";
memset(szTempMac, 0, sizeof(szTempMac));
sprintf(szTempMac, "11");
to_erasing(test_did, szTempMac+2);
char cmd[128];
memset(cmd,0,128);
// sprintf(cmd,"{\"msisdn\":\"\",\"mac\":\"%s\",\"smartDeviceId\":\"%s\",\"imei\":\"00099\",\"sim\":\"1111100\"}",test_did, test_did);
sprintf(cmd,"{\"mac\":\"%s\",\"smartDeviceId\":\"%s\"}",test_did, szTempMac);
LOG("%s\n", cmd);

int nR = 0;
nR = migusdk_init(cmd);
LOG("nr:%d\n", nR);

char szVersion[48] = "\0";
getSdkVersion(szVersion);
LOG("migu version:%s\n", szVersion);
heartBeat();

//LOG("****************sayHelloII 3******************\n\n");
while(1)
{
//LOG("****************sayHelloII 4******************\n\n");
if(atoi(szRun) == 0)
{
//LOG("****************sayHelloII connstatus %s\n", szRun);
break;
}

if( sendheart() < 0 )
{
//LOG("****************sayHelloII sendheart < 0\n");
break;
}

struct timeval tm;
fd_set set;
tm.tv_sec = 3;
tm.tv_usec = 0;
FD_ZERO(&set);
/*
FD_SET(client_socket, &set);
int res = select(client_socket+1, &set, NULL, NULL, &tm);
*/
//LOG("****************sayHelloII 5******************\n\n");
SSL_set_fd(ssl, sd);
int res = SSL_pending(ssl);
//LOG("****************sayHelloII 6******************\n\n");
// if( res > 0 )
{
// SSL_set_fd (ssl, sd);
// int err = SSL_connect (ssl);
// CHK_SSL(err);
// if(err>=0)
//if( FD_ISSET(client_socket, &set) )
{

{

//LOG("****************sayHelloII 7******************\n\n");
memset(msg,0,nLen);
int errr = SSL_read (ssl, msg, nLen);
CHK_SSL(errr);
//LOG("****************sayHelloII 8******************\n\n");
{

// if(total < 1024)
// LOG("\n\n\n %s \n\n",msg);
if(nLen < 1024)
LOG("\n\n\n (%s) \n\n",msg);
else
{

}
doyidongapp(msg+4);
}

}

}

}


}


if(!ssl)
{
SSL_shutdown (ssl); /* send SSL/TLS close_notify */
/* 收尾工作 */
sd = -1;
shutdown (sd,2);
SSL_free (ssl);
SSL_CTX_free (ctx);
LOG("SSL_new error!\n");
}
connectstatus = 0;
LOG("\n\n****************sayHelloII end******************\n\n");
sleep(2);

}

g_test_register_states = 0;

if(msg)
free(msg);

LOG("====== HelloThread end ======\n");
return NULL;

}