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
sslserver.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 #include <iostream>
18 #include <fstream>
19 #include <algorithm>
20 #include <vector>
21 #include <string>
22 #include <sstream>
23 #include <map>
24 #include <utility>
25 using namespace std;
26 
27 #include "sslserver.h"
28 #include "generic_plugin.h"
29 #include "generic_server.h"
30 #include "control.h"
31 
34 {
35 #ifdef WINDOWS
36  HANDLE mutex;
37 #else
38  pthread_mutex_t mutex;
39 #endif
40 };
41 #ifdef WINDOWS
42 static HANDLE *mutex_buf;
43 #else
44 static pthread_mutex_t *mutex_buf;
45 #endif
46 static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,const char *file, int line);
47 static void dyn_destroy_function(struct CRYPTO_dynlock_value *l,const char *file, int line);
48 static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line);
49 static void locking_function(int mode, int n, const char *file, int line);
50 static unsigned long id_function(void);
52 {
53  cert_file = "";
54  priv_key_file = "";
55  ctx = NULL;
56 }
57 /**********************************************************************************************/
58 
59 SSLServer::SSLServer(char *cFile, char *kFile)
60 {
61  cert_file = cFile;
62  priv_key_file = kFile;
63  ctx = NULL;
64  mutex_buf = NULL;
65 }
66 /**********************************************************************************************/
67 
68 SSL_CTX *SSLServer::get_ctx(void)
69 {
70  return(ctx);
71 }
72 /**********************************************************************************************/
73 
75 {
76  int i;
77 
78  SSL_load_error_strings();
79  SSL_library_init();
80  // Load algorithms and error strings.
81  OpenSSL_add_all_algorithms();
82  /* static locks area */
83 #ifdef WINDOWS
84  mutex_buf = (HANDLE *) malloc(CRYPTO_num_locks() * sizeof(HANDLE));
85 #else
86  mutex_buf = (pthread_mutex_t *) malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
87 #endif
88  if (mutex_buf == NULL)
89  return (0);
90  for (i = 0; i < CRYPTO_num_locks(); i++)
91  {
92 #ifdef WINDOWS
93  mutex_buf[i] = CreateMutex( NULL, FALSE, NULL );
94 #else
95  pthread_mutex_init(&mutex_buf[i], NULL);
96 #endif
97  }
98  /* static locks callbacks */
99  CRYPTO_set_locking_callback(locking_function);
100  CRYPTO_set_id_callback(id_function);
101  /* dynamic locks callbacks */
102  CRYPTO_set_dynlock_create_callback(dyn_create_function);
103  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
104  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
105 #ifndef WINDOWS
106  RAND_load_file("/dev/urandom", 1024);
107 // OpenSSL uses several sources of entropy automatically on Windows
108 #endif
109  return (1);
110 }
111 /**********************************************************************************************/
112 
113 int SSLServer::tls_cleanup(void)
114 {
115  int i;
116 
117  if (mutex_buf == NULL)
118  return (0);
119  CRYPTO_set_dynlock_create_callback(NULL);
120  CRYPTO_set_dynlock_lock_callback(NULL);
121  CRYPTO_set_dynlock_destroy_callback(NULL);
122 
123  CRYPTO_set_locking_callback(NULL);
124  CRYPTO_set_id_callback(NULL);
125 
126  for (i = 0; i < CRYPTO_num_locks(); i++)
127  {
128 #ifdef WINDOWS
129  CloseHandle(mutex_buf[i]);
130 #else
131  pthread_mutex_destroy(&mutex_buf[i]);
132 #endif
133  }
134  free(mutex_buf);
135  mutex_buf = NULL;
136  return (1);
137 }
138 /**********************************************************************************************/
139 
140 int SSLServer::set_priv_key(string priv_key)
141 {
142  priv_key_file = priv_key;
143  return(1);
144 }
145 /**********************************************************************************************/
146 
147 int SSLServer::set_cert_file(string server_cert_file)
148 {
149  cert_file = server_cert_file;
150  return(1);
151 }
152 /**********************************************************************************************/
153 
154 int SSLServer::set_verify_client(bool status_flag)
155 {
156  verify_client = status_flag;
157  return(1);
158 }
159 /**********************************************************************************************/
160 
161 int SSLServer::set_ca_cert(string ca_cert)
162 {
163  ca_certificate = ca_cert;
164  return(1);
165 }
166 /**********************************************************************************************/
167 
169 {
171 ostringstream oss;
172 // The method describes which SSL protocol we will be using.
173 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) // openssl returns a const SSL_METHOD
174  const SSL_METHOD *method = NULL;
175 #else
176  SSL_METHOD *method = NULL;
177 #endif
178  STACK_OF(X509_NAME) *cert_names;
179  // Compatible with SSLv2, SSLv3 and TLSv1
180  method = SSLv23_server_method();
181  //method = TLSv1_server_method();
182 
183  // Create new context from method.
184  ctx = SSL_CTX_new(method);
185  if(ctx == NULL)
186  return(0);
187  SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY);
188  cert_names = SSL_load_client_CA_file(ca_certificate.c_str());
189  if (cert_names != NULL)
190  SSL_CTX_set_client_CA_list(ctx, cert_names);
191  else
192  return(0);
193  if(!SSL_CTX_load_verify_locations(ctx,ca_certificate.c_str(),NULL))
194  if(verify_client)
195  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
196  return(1);
197 }
198 /**********************************************************************************************/
199 
200 /* Load the certification files, ie the public and private keys. */
202 {
203  if ( SSL_CTX_use_certificate_chain_file(ctx, cert_file.c_str()) <= 0)
204  return(0);
205  if ( SSL_CTX_use_PrivateKey_file(ctx, priv_key_file.c_str(), SSL_FILETYPE_PEM) <= 0)
206  return(0);
207  // Verify that the two keys goto together.
208  if ( !SSL_CTX_check_private_key(ctx) )
209  return(0);
210  return(1);
211 }
212 /**********************************************************************************************/
222 static void locking_function(int mode, int n, const char *file, int line)
223 {
224  if (mode & CRYPTO_LOCK)
225  {
226 #ifdef WINDOWS
227  DWORD dwWaitResult;
228  dwWaitResult = WaitForSingleObject(mutex_buf[n],INFINITE);
229 #else
230  pthread_mutex_lock(&mutex_buf[n]);
231 #endif
232  }
233  else
234  {
235 #ifdef WINDOWS
236  ReleaseMutex(mutex_buf[n]);
237 #else
238  pthread_mutex_unlock(&mutex_buf[n]);
239 #endif
240  }
241 }
242 /**********************************************************************************************/
243 
249 static unsigned long id_function(void)
250 {
251 #ifdef WINDOWS
252  return(unsigned long) GetCurrentThreadId();
253  //return(1);
254 #else
255  return ((unsigned long) pthread_self());
256 #endif
257 }
258 /**********************************************************************************************/
259 
260 static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
261 {
262  struct CRYPTO_dynlock_value *value;
263 
264  value = NULL;
265  value = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
266  if (!value)
267  return(NULL);
268 #ifdef WINDOWS
269  value->mutex = CreateMutex( NULL, FALSE, NULL );
270 #else
271  pthread_mutex_init(&value->mutex, NULL);
272 #endif
273  return value;
274 }
275 /**********************************************************************************************/
276 
277 static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,const char *file, int line)
278 {
279  if (mode & CRYPTO_LOCK)
280  {
281 #ifdef WINDOWS
282  DWORD dwWaitResult;
283  dwWaitResult = WaitForSingleObject(l->mutex,INFINITE);
284 #else
285  pthread_mutex_lock(&l->mutex);
286 #endif
287  }
288  else
289  {
290 #ifdef WINDOWS
291  ReleaseMutex(l->mutex);
292 #else
293  pthread_mutex_unlock(&l->mutex);
294 #endif
295  }
296 }
297 /**********************************************************************************************/
298 
299 static void dyn_destroy_function(struct CRYPTO_dynlock_value *l,const char *file, int line)
300 {
301 #ifdef WINDOWS
302  CloseHandle(l->mutex);
303 #else
304  pthread_mutex_destroy(&l->mutex);
305 #endif
306  free(l);
307 }
308 /**********************************************************************************************/
static generic_server * pinstance
Pointer to singleton framework instance.
Singleton class to manage framework state and provide utility functions. This class stores master Vec...
This is a singleton class and provides framework functionality.
This is the base class for all plugins. All plug-ins should derive from this class. This class has a bunch of virtual functions that all plug-in could/should implement. In addition to virtual functions, this class also provides a lot of utility functions for all plug-ins.
int CreateCTX(void)
Load algorithms and create context.
Definition: sslserver.cpp:168
Struct to store OS agnostic mutex. Required for Openssl locking functions.
Definition: sslserver.cpp:33
SSLServer()
Constructors.
Definition: sslserver.cpp:51
int tls_init(void)
Definition: sslserver.cpp:74
int LoadCerts(void)
Load certification files.
Definition: sslserver.cpp:201
Master program that initiates GENERIC_SERVER, spawns a thread for each plug-in and runs message loop ...
Utility class for TLS. Please refer excellent documentation at: http://www.openssl.org/docs/ssl/ssl.html.