CUBRID Engine  latest
cas_ssl.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * cas_ssl.c -
22  */
23 
24 #ident "$Id$"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <assert.h>
30 
31 #if defined(WINDOWS)
32 #include <winsock2.h>
33 #include <windows.h>
34 #include <process.h>
35 #include <sys/timeb.h>
36 #include <dbgHelp.h>
37 #include <io.h>
38 #include <direct.h>
39 #else /* WINDOWS */
40 #include <unistd.h>
41 #include <netinet/in.h>
42 #include <netinet/tcp.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #endif /* WINDOWS */
48 
49 #include "cas_common.h"
50 #include "cas.h"
51 #include "cas_network.h"
52 #include "cas_function.h"
53 #include "cas_net_buf.h"
54 #include "cas_log.h"
55 #include "cas_util.h"
56 #include "broker_filename.h"
57 #include "cas_execute.h"
58 
59 #include <openssl/crypto.h>
60 #include <openssl/x509.h>
61 #include <openssl/pem.h>
62 #include <openssl/ssl.h>
63 #include <openssl/err.h>
64 
65 #if defined(WINDOWS)
66 #else
67 #include <unistd.h>
68 #include <fcntl.h>
69 #endif
70 
71 #define CERTF "cas_ssl_cert.crt"
72 #define KEYF "cas_ssl_cert.key"
73 #define CERT_FILENAME_LEN 512
74 #define ER_SSL_GENERAL -1
75 #define ER_CERT_EXPIRED -2
76 #define ER_CERT_COPPUPTED -3
77 #define SOCKET_NONBLOCK 1
78 #define SOCKET_BLOCK 0
79 
80 static SSL *ssl = NULL;
81 bool ssl_client = false;
82 
83 static int cas_ssl_validity_check (SSL_CTX * ctx);
84 
85 int
86 cas_init_ssl (int sd)
87 {
88  SSL_CTX *ctx;
89  char cert[CERT_FILENAME_LEN];
90  char key[CERT_FILENAME_LEN];
91  int err_code;
92  unsigned long err;
93  struct stat sbuf;
94  bool cert_not_found, pk_not_found;
95 
96  if (ssl)
97  {
98  SSL_free (ssl);
99  }
100 
101 #if defined(WINDOWS)
102  u_long argp = SOCKET_BLOCK;
103  ioctlsocket (sd, FIONBIO, &argp);
104 #else
105  int oflags, flags = fcntl (sd, F_GETFL, 0);
106  oflags = flags;
107  flags = flags & ~O_NONBLOCK;
108 
109  fcntl (sd, F_SETFL, flags);
110 
111 #endif
112  snprintf (cert, CERT_FILENAME_LEN, "%s/conf/%s", getenv ("CUBRID"), CERTF);
113  snprintf (key, CERT_FILENAME_LEN, "%s/conf/%s", getenv ("CUBRID"), KEYF);
114 
115  cert_not_found = (stat (cert, &sbuf) < 0) ? true : false;
116  pk_not_found = (stat (key, &sbuf) < 0) ? true : false;
117 
118  if (cert_not_found && pk_not_found)
119  {
120  cas_log_write_and_end (0, false, "SSL: Both the certificate & Private key could not be found: %s, %s", cert, key);
121  return ER_CERT_COPPUPTED;
122  }
123 
124  if (cert_not_found)
125  {
126  cas_log_write_and_end (0, false, "SSL: Certificate not found: %s", cert);
127  return ER_CERT_COPPUPTED;
128  }
129 
130  if (pk_not_found)
131  {
132  cas_log_write_and_end (0, false, "SSL: Private key not found: %s", key);
133  return ER_CERT_COPPUPTED;
134  }
135 
136 #if OPENSSL_VERSION_NUMBER < 0x10100000L
137  SSL_load_error_strings ();
138  SSLeay_add_ssl_algorithms ();
139  ERR_load_crypto_strings ();
140 #endif
141 
142  if ((ctx = SSL_CTX_new (TLS_server_method ())) == NULL)
143  {
144  cas_log_write_and_end (0, true, "SSL: Initialize failed.");
145  return ER_SSL_GENERAL;
146  }
147 
148  if (SSL_CTX_use_certificate_file (ctx, cert, SSL_FILETYPE_PEM) <= 0
149  || SSL_CTX_use_PrivateKey_file (ctx, key, SSL_FILETYPE_PEM) <= 0)
150  {
151  cas_log_write_and_end (0, true, "SSL: Certificate or Key is coppupted.");
152  return ER_CERT_COPPUPTED;
153  }
154 
155  if ((err_code = cas_ssl_validity_check (ctx)) < 0)
156  {
157  cas_log_write (0, true, "SSL: Certificate validity error (%s)",
158  err_code == ER_CERT_EXPIRED ? "Expired" : "Unknow");
159  return err_code;
160  }
161 
162 
163  if ((ssl = SSL_new (ctx)) == NULL)
164  {
165  cas_log_write_and_end (0, true, "SSL: Creating SSL context failed.");
166  SSL_CTX_free (ctx);
167  return ER_SSL_GENERAL;
168  }
169 
170  if (SSL_set_fd (ssl, sd) == 0)
171  {
172  cas_log_write_and_end (0, true, "SSL: Cannot associate with socket.");
173  SSL_free (ssl);
174  ssl = NULL;
175  return ER_SSL_GENERAL;
176  }
177 
178  err_code = SSL_accept (ssl);
179  if (err_code < 0)
180  {
181  err_code = SSL_get_error (ssl, err_code);
182  err = ERR_get_error ();
183  cas_log_write_and_end (0, true, "SSL: Accept failed - '%s'", ERR_error_string (err, NULL));
184  SSL_free (ssl);
185  ssl = NULL;
186  return ER_SSL_GENERAL;
187  }
188 
189 #if defined (WINDOWS)
190  argp = SOCKET_NONBLOCK;
191  ioctlsocket (sd, FIONBIO, &argp);
192 #else
193  fcntl (sd, F_SETFL, oflags);
194 #endif
195 
196  ssl_client = true;
197 
198  return 0;
199 }
200 
201 int
202 cas_ssl_read (int sd, char *buf, int size)
203 {
204  int nread;
205 
206  if (IS_INVALID_SOCKET (sd) || ssl == NULL)
207  {
208  cas_log_write_and_end (0, true, "SSL: READ attempt for brokern connection");
209  return ER_SSL_GENERAL;
210  }
211 
212 #if defined(WINDOWS)
213  u_long argp = SOCKET_BLOCK;
214  ioctlsocket (sd, FIONBIO, &argp);
215 #else
216  int oflags, flags = fcntl (sd, F_GETFL, 0);
217  oflags = flags;
218  flags = flags & ~O_NONBLOCK;
219  fcntl (sd, F_SETFL, flags);
220 #endif
221 
222  nread = SSL_read (ssl, buf, size);
223 
224 #if defined(WINDOWS)
225  argp = SOCKET_NONBLOCK;
226  ioctlsocket (sd, FIONBIO, &argp);
227 #else
228  fcntl (sd, F_SETFL, oflags);
229 #endif
230  return nread;
231 }
232 
233 int
234 cas_ssl_write (int sd, const char *buf, int size)
235 {
236  int nwrite;
237 
238  if (IS_INVALID_SOCKET (sd) || ssl == NULL)
239  {
240  cas_log_write_and_end (0, true, "SSL: WRITE attempt for brokern connection");
241  return ER_SSL_GENERAL;
242  }
243 #if defined(WINDOWS)
244  u_long argp = SOCKET_BLOCK;
245  ioctlsocket (sd, FIONBIO, &argp);
246 #else
247  int oflags, flags = fcntl (sd, F_GETFL, 0);
248  oflags = flags;
249  flags = flags & ~O_NONBLOCK;
250  fcntl (sd, F_SETFL, flags);
251 #endif
252 
253  nwrite = SSL_write (ssl, buf, size);
254 
255 #if defined(WINDOWS)
256  argp = SOCKET_NONBLOCK;
257  ioctlsocket (sd, FIONBIO, &argp);
258 #else
259  fcntl (sd, F_SETFL, oflags);
260 #endif
261  return nwrite;
262 }
263 
264 void
265 cas_ssl_close (int client_sock_fd)
266 {
267  if (ssl)
268  {
269  SSL_free (ssl);
270  ssl = NULL;
271  }
272 }
273 
274 static int
275 cas_ssl_validity_check (SSL_CTX * ctx)
276 {
277  ASN1_TIME *not_before, *not_after;
278  X509 *crt;
279 
280  crt = SSL_CTX_get0_certificate (ctx);
281 
282  if (crt == NULL)
283  return ER_SSL_GENERAL;
284 
285  not_after = X509_getm_notAfter (crt);
286  if (X509_cmp_time (not_after, NULL) != 1)
287  {
288  return ER_CERT_EXPIRED;
289  }
290 
291  not_before = X509_getm_notBefore (crt);
292  if (X509_cmp_time (not_before, NULL) != -1)
293  {
294  return ER_SSL_GENERAL;
295  }
296 
297  return 0;
298 }
299 
300 bool
302 {
303  return (SSL_has_pending (ssl) == 1 ? true : false);
304 }
static int cas_ssl_validity_check(SSL_CTX *ctx)
Definition: cas_ssl.c:275
#define ER_CERT_EXPIRED
Definition: cas_ssl.c:75
#define CERTF
Definition: cas_ssl.c:71
#define KEYF
Definition: cas_ssl.c:72
#define SOCKET_NONBLOCK
Definition: cas_ssl.c:77
int cas_ssl_read(int sd, char *buf, int size)
Definition: cas_ssl.c:202
#define ER_SSL_GENERAL
Definition: cas_ssl.c:74
#define SOCKET_BLOCK
Definition: cas_ssl.c:78
#define IS_INVALID_SOCKET(socket)
Definition: porting.h:484
int cas_ssl_write(int sd, const char *buf, int size)
Definition: cas_ssl.c:234
void cas_ssl_close(int client_sock_fd)
Definition: cas_ssl.c:265
#define NULL
Definition: freelistheap.h:34
#define err(fd,...)
Definition: porting.h:431
int cas_init_ssl(int sd)
Definition: cas_ssl.c:86
static SSL * ssl
Definition: cas_ssl.c:80
void cas_log_write(unsigned int seq_num, bool unit_start, const char *fmt,...)
Definition: cas_log.c:506
static SOCKET sock_fd
Definition: broker.c:300
void cas_log_write_and_end(unsigned int seq_num, bool unit_start, const char *fmt,...)
Definition: cas_log.c:533
bool is_ssl_data_ready(int sock_fd)
Definition: cas_ssl.c:301
bool ssl_client
Definition: cas_ssl.c:81
#define ER_CERT_COPPUPTED
Definition: cas_ssl.c:76
#define CERT_FILENAME_LEN
Definition: cas_ssl.c:73