GENERIC_SERVER  0.0.0.9
A light-weight, cross-platform, pluggable, extensible and secure framework for deploying C++ plug-ins.
 All Classes Files Functions Variables Typedefs Pages
util.cpp
1 /*
2  Copyright 2013 Broadcom Corporation
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License version 2.1 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 #ifdef WINDOWS
18 #include <winsock2.h>
19 #include <ws2tcpip.h>
20 #include <conio.h>
21 #include <process.h>
22 #else
23 #include <sys/socket.h>
24 #include <arpa/inet.h>
25 #include <resolv.h>
26 #include <unistd.h>
27 #include <netinet/in.h>
28 #include <sys/socket.h>
29 #include <signal.h>
30 #include <fcntl.h>
31 #endif
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 #include <openssl/rand.h>
35 #include <stdio.h>
36 
37 #include <iostream>
38 #include <fstream>
39 #include <algorithm>
40 #include <vector>
41 #include <string>
42 #include <sstream>
43 #include <map>
44 #include <utility>
45 using namespace std;
46 #include "util.h"
47 
48 int ssl_read_socket(unsigned char *buffer,SOCKET &sock,SSL **ssl_client)
49 {
50  char buf[MAX_SZ];
51  fd_set socks;
52  int r;
53  unsigned int plugin_signature,no_bytes,msg_length;
54  struct timeval timeout;
55 
56  memset(buf,0,MAX_SZ);
57  memset(buffer,0,MAX_SZ);
58  FD_ZERO(&socks);
59  FD_SET (sock, &socks);
60  timeout.tv_sec = 1;
61  timeout.tv_usec = 0;
62  r = select((int)sock+1, &socks, NULL, NULL, &timeout);
63  if (r <= 0)
64  return(0);
65  else if (r > 0 && FD_ISSET(sock, &socks))
66  {
67  r = ssl_read((SSL *)*ssl_client,buf,MSG_HDR_SIZE); // First 4 bytes represent plugin SIGNATURE
68  if(r <= 0)
69  return(0);
70  memcpy(&plugin_signature,buf,4); // Next 4 byes represent msg length
71  memcpy(&msg_length,buf+4,4);
72  msg_length = ntohl(msg_length);
73  no_bytes = 0;
74  while(no_bytes < msg_length)
75  {
76  r = ssl_read((SSL *)*ssl_client,buf,msg_length);
77  if(r <= 0)
78  return(0);
79  memcpy(buffer+no_bytes,buf,r);
80  no_bytes += r;
81  }
82  }
83  return(no_bytes);
84 
85 }
86 /**************************************************************************************/
87 
88 int ssl_read(SSL *ssl,char *buf,int size)
89 {
90  int len,r;
91 
92  while(1)
93  {
94  r = SSL_read(ssl,buf,size);
95  switch(SSL_get_error(ssl,r))
96  {
97  case SSL_ERROR_NONE:
98  len=r;
99  break;
100  case SSL_ERROR_WANT_READ:
101  continue;
102  case SSL_ERROR_ZERO_RETURN:
103  return(0);
104  case SSL_ERROR_SYSCALL:
105  return(0);
106  default:
107  return(0);
108  }
109  if(len == r)
110  break;
111  }
112  return(len);
113 }
114 /**************************************************************************************/
115 
116 int read_socket(unsigned char *buffer,SOCKET conn_s)
117 {
118  unsigned int plugin_signature,msg_length;
119  fd_set socks;
120  struct timeval timeout;
121  char str[10000];
122  size_t readsock,t;
123  size_t bytes_recvd;
124  bytes_recvd = 0;
125 
126  memset(buffer,0,sizeof(buffer));
127  memset(str,0,10000);
128 
129  FD_ZERO(&socks);
130  FD_SET(conn_s,&socks);
131  timeout.tv_sec = 2;
132  timeout.tv_usec = 0;
133 
134  readsock = select((int)conn_s+1,&socks,NULL,NULL,&timeout);
135  if(readsock <= 0)
136  return(0);
137  if(FD_ISSET(conn_s,&socks))
138  {
139  t = recv(conn_s,str,MSG_HDR_SIZE, 0); // First 4 bytes represent plugin SIGNATURE
140  if(t < MSG_HDR_SIZE)
141  return(0);
142  memcpy(&plugin_signature,str,4); // Next 4 byes represent msg length
143  memcpy(&msg_length,str+4,4);
144  msg_length = ntohl(msg_length);
145  bytes_recvd = 0;
146  while(bytes_recvd < msg_length)
147  {
148  t = recv(conn_s,str,10000, 0);
149  if(t > 0)
150  {
151  memcpy(buffer+bytes_recvd,str,t);
152  bytes_recvd += t;
153  if(bytes_recvd >= msg_length)
154  break;
155  }
156  else
157  break;
158  }
159  }
160  return(bytes_recvd);
161 }
162 /**************************************************************************************/
163 /*
164  Open socket to the given IP Address and Port
165  returns 0 for success
166 */
167 int ssl_connect(unsigned char *ip_address, unsigned int port_number,SOCKET &sock,SSL **ssl_client,SSL_CTX **ctx)
168 {
169  struct sockaddr_in sockaddr;
170  memset(&sockaddr, 0, sizeof(sockaddr));
171  if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
172  {
173  cout << "Failed to create socket: " << sock << endl;
174  return(0);
175  }
176  sockaddr.sin_family = AF_INET; /* Internet/IP */
177  sockaddr.sin_addr.s_addr = inet_addr((const char *)ip_address); /* IP address */
178  sockaddr.sin_port = (u_short)htons((u_short)port_number); /* server port */
179  int i = connect(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
180  if (i == SOCKET_ERROR)
181  {
182  cout << "Failed to connect with server: " << i << " " << ip_address << " at port: " << port_number << endl;
183  return(0);
184  }
185  *ssl_client = SSL_new(*ctx);
186  SSL_set_fd(*ssl_client,sock);
187  SSL_set_connect_state(*ssl_client);
188 // SSL_set_verify(ssl,SSL_VERIFY_PEER,NULL);
189  if(SSL_connect(*ssl_client) <= 0)
190  {
191  cout << "Failed to successfully connect to SSL server: " << ip_address << " at port: " << port_number;
192  return(0);
193  }
194  return(1);
195 }
196 /*****************************************************************************************************/
197 
203 unsigned long id_function(void)
204 {
205 #ifdef WINDOWS
206  return(unsigned long) GetCurrentThreadId();
207 #else
208  return ((unsigned long) pthread_self());
209 #endif
210 }
211 /**********************************************************************************************/
212 
213 struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
214 {
215  struct CRYPTO_dynlock_value *value;
216 
217  value = NULL;
218  value = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
219  if (!value)
220  return(NULL);
221 #ifdef WINDOWS
222  value->mutex = CreateMutex( NULL, FALSE, NULL );
223 #else
224  pthread_mutex_init(&value->mutex, NULL);
225 #endif
226  return value;
227 }
228 /**********************************************************************************************/
229 
230 void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,const char *file, int line)
231 {
232  if (mode & CRYPTO_LOCK)
233  {
234 #ifdef WINDOWS
235  DWORD dwWaitResult;
236  dwWaitResult = WaitForSingleObject(l->mutex,INFINITE);
237 #else
238  pthread_mutex_lock(&l->mutex);
239 #endif
240  }
241  else
242  {
243 #ifdef WINDOWS
244  ReleaseMutex(l->mutex);
245 #else
246  pthread_mutex_unlock(&l->mutex);
247 #endif
248  }
249 }
250 /**********************************************************************************************/
251 
252 void dyn_destroy_function(struct CRYPTO_dynlock_value *l,const char *file, int line)
253 {
254 #ifdef WINDOWS
255  CloseHandle(l->mutex);
256 #else
257  pthread_mutex_destroy(&l->mutex);
258 #endif
259  free(l);
260 }
261 /**********************************************************************************************/
262 /*
263  Open socket to the given IP Address and Port
264  returns 0 for success
265 */
266 int sock_connect(unsigned char *ip_address, unsigned int port_number,SOCKET &sock)
267 {
268  struct sockaddr_in sockaddr;
269 
270  memset(&sockaddr, 0, sizeof(sockaddr));
271  if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
272  {
273  cout << "Failed to create socket: " << sock << endl;
274  return(0);
275  }
276  sockaddr.sin_family = AF_INET; /* Internet/IP */
277  sockaddr.sin_addr.s_addr = inet_addr((const char *)ip_address); /* IP address */
278  sockaddr.sin_port = (u_short)htons((u_short)port_number); /* server port */
279  int i = connect(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
280  if ( i == SOCKET_ERROR)
281  {
282  cout << "Failed to connect with server: " << i << " " << ip_address << " at port: " << port_number << endl;
283  return(0);
284  }
285  return(1);
286 }
287 /**********************************************************************************************/
288 
289 void locking_function(int mode, int n, const char *file, int line)
290 {
291  if (mode & CRYPTO_LOCK)
292  {
293 #ifdef WINDOWS
294  DWORD dwWaitResult;
295  dwWaitResult = WaitForSingleObject(mutex_buf[n],INFINITE);
296 #else
297  pthread_mutex_lock(&mutex_buf[n]);
298 #endif
299  }
300  else
301  {
302 #ifdef WINDOWS
303  ReleaseMutex(mutex_buf[n]);
304 #else
305  pthread_mutex_unlock(&mutex_buf[n]);
306 #endif
307  }
308 }
309 /**********************************************************************************************/
310 
311 int setnonblocking(int sock)
312 {
313  int iResult;
314 #ifdef WINDOWS
315  u_long iMode = 1;
316  iResult = ioctlsocket(sock, FIONBIO, &iMode);
317  if (iResult != NO_ERROR)
318  return(0);
319  return(1);
320 #else
321  int opts = fcntl(sock,F_GETFL);
322  if (opts < 0)
323  return(0);
324  opts = (opts | O_NONBLOCK);
325  if (fcntl(sock,F_SETFL,opts) < 0)
326  return(0);
327  return(1);
328 #endif
329 }
330 /*****************************************************************************************/
331 
332 int setblocking(int sock)
333 {
334  int iResult;
335 #ifdef WINDOWS
336  u_long iMode = 0;
337  iResult = ioctlsocket(sock, FIONBIO, &iMode);
338  if (iResult != NO_ERROR)
339  return(0);
340  return(1);
341 #else
342  int opts = fcntl(sock,F_GETFL);
343  if (opts < 0)
344  return(0);
345  opts = (opts | ~O_NONBLOCK);
346  if (fcntl(sock,F_SETFL,opts) < 0)
347  return(0);
348  return(1);
349 #endif
350 }
351 /*****************************************************************************************/
352 
353 #ifdef WINDOWS
354 int sock_init(void)
355 {
356  WSADATA wsaData;
357  int iResult;
358  // Initialize Winsock
359  iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
360  if (iResult != 0)
361  return(0);
362  return(1);
363 }
364 #endif
365 /*****************************************************************************************/
366 
367 int create_message(string plugin_name,string message,char *buff)
368 {
369 int size,tot_size;
370 unsigned int plugin_signature;
371 
372  plugin_signature = htonl(PLUGIN_SIGNATURE);
373  memset(buff,0,MAX_SZ);
374  size = plugin_name.length();
375  size = htonl(size);
376  memcpy(buff,&plugin_signature,4);
377  tot_size = plugin_name.length()+message.length()+4;
378  tot_size = htonl(tot_size);
379  memcpy(buff,&plugin_signature,4); // Adding SIGNATURE
380  memcpy(buff+4,&tot_size,4); // Adding total size
381  memcpy(buff+8,&size,4); // Adding plugin_name size
382  memcpy(buff+12,plugin_name.c_str(),plugin_name.length()); // Addling plugin_name
383  memcpy(buff+12+plugin_name.length(),message.c_str(),message.length()); // Adding message payload
384  return(12+plugin_name.length()+message.length());
385 }
386 /*****************************************************************************************/
387 
388 int ssl_init(SSL_CTX **ctx)
389 {
390  int i;
391 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) // openssl returns a const SSL_METHOD
392  const SSL_METHOD *method = NULL;
393 #else
394  SSL_METHOD *method = NULL;
395 #endif
396  SSL_load_error_strings();
397  SSL_library_init();
398  OpenSSL_add_all_algorithms();
399 #ifdef WINDOWS
400  mutex_buf = (HANDLE *) malloc(CRYPTO_num_locks() * sizeof(HANDLE));
401 #else
402  mutex_buf = (pthread_mutex_t *) malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
403 #endif
404  if (mutex_buf == NULL)
405  return (0);
406  for (i = 0; i < CRYPTO_num_locks(); i++)
407  {
408 #ifdef WINDOWS
409  mutex_buf[i] = CreateMutex( NULL, FALSE, NULL );
410 #else
411  pthread_mutex_init(&mutex_buf[i], NULL);
412 #endif
413  }
414  /* static locks callbacks */
415  CRYPTO_set_locking_callback(locking_function);
416  CRYPTO_set_id_callback(id_function);
417  /* dynamic locks callbacks */
418  CRYPTO_set_dynlock_create_callback(dyn_create_function);
419  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
420  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
421 #ifndef WINDOWS
422  RAND_load_file("/dev/urandom", MAX_SZ);
423 #endif
424  // Compatible with SSLv2, SSLv3 and TLSv1
425  method = SSLv3_client_method();
426  // Create new context from method.
427  *ctx = SSL_CTX_new(method);
428  if(*ctx == NULL)
429  {
430  cout << "CTX is NULL.." << endl;
431  return(0);
432  }
433  SSL_CTX_set_mode(*ctx,SSL_MODE_AUTO_RETRY);
434  return(1);
435 }
436 /*****************************************************************************************/
Struct to store OS agnostic mutex. Required for Openssl locking functions.
Definition: sslserver.cpp:33