1 /* $Id: ssl.c 20800 2012-01-19 05:13:45Z m-oki $ */
2
3 /*
4 * Copyright (c) 2012, Internet Initiative Japan, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "config.h"
31
32 #include <inttypes.h>
33 #include <string.h>
34 #include <sys/ioctl.h>
35
36 #include <openssl/ssl.h>
37 #include <openssl/err.h>
38 #include <openssl/rand.h>
39
40 #include <libarms_log.h>
41 #include <libarms_resource.h>
42 #include <transaction/transaction.h>
43 #include <libarms/ssl.h>
44
45 static X509 *ssl_mycert;
46 static EVP_PKEY *ssl_mykey;
47
48 /*0:LS 1:RS*/
49 static X509 *ssl_cacert;
50
51 static void free_certificate(void);
52 static int verify_ls_cn(X509_STORE_CTX *, void *);
53
54 int
arms_ssl_register_cacert(const char * cacert)55 arms_ssl_register_cacert(const char *cacert)
56 {
57 BIO *mem;
58 X509 *tmp_cacert;
59
60 ERR_clear_error();
61
62 mem = BIO_new_mem_buf((void *)cacert, -1);
63 tmp_cacert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
64 BIO_free(mem);
65 if (tmp_cacert == NULL) {
66 return -1;
67 }
68 if (ssl_cacert != NULL) {
69 X509_free(ssl_cacert);
70 }
71 ssl_cacert = tmp_cacert;
72 return 0;
73 }
74
75 /*
76 * originally from http/http.c::http_register_cert()
77 */
78 int
arms_ssl_register_cert(const char * mycert,const char * mykey)79 arms_ssl_register_cert(const char *mycert, const char *mykey)
80 {
81 BIO *mem;
82 EVP_PKEY *tmp_mykey;
83 X509 *tmp_mycert;
84 int error = 0;
85
86 tmp_mycert = NULL;
87 tmp_mykey = NULL;
88
89 ERR_clear_error();
90
91 if (mycert != NULL && strlen(mycert) > 0) {
92 mem = BIO_new_mem_buf((void *)mycert, -1);
93 tmp_mycert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
94 BIO_free(mem);
95
96 if (tmp_mycert == NULL) {
97 error = 1;
98 goto err;
99 }
100 }
101
102 if (mykey != NULL && strlen(mykey) > 0) {
103 mem = BIO_new_mem_buf((void *)mykey, -1);
104 tmp_mykey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
105 BIO_free(mem);
106
107 if (tmp_mykey == NULL) {
108 error = 2;
109 goto err;
110 }
111 }
112
113
114 free_certificate();
115 ssl_mycert = tmp_mycert;
116 ssl_mykey = tmp_mykey;
117
118 return 0;
119
120 err:
121 if (tmp_mycert != NULL)
122 X509_free(tmp_mycert);
123 if (tmp_mykey != NULL)
124 EVP_PKEY_free(tmp_mykey);
125 libarms_log(ARMS_LOG_ECERTIFICATE,
126 "Registering certification got error.");
127 return error;
128 }
129
130 X509 *
arms_ssl_mycert(void)131 arms_ssl_mycert(void)
132 {
133 return ssl_mycert;
134 }
135 EVP_PKEY *
arms_ssl_mykey(void)136 arms_ssl_mykey(void)
137 {
138 return ssl_mykey;
139 }
140
141 X509 *
arms_ssl_cacert(void)142 arms_ssl_cacert(void)
143 {
144 return ssl_cacert;
145 }
146
147 static void
free_certificate(void)148 free_certificate(void)
149 {
150 if (ssl_mycert != NULL) {
151 X509_free(ssl_mycert);
152 ssl_mycert = NULL;
153 }
154 if (ssl_mykey != NULL) {
155 EVP_PKEY_free(ssl_mykey);
156 ssl_mykey = NULL;
157 }
158 }
159
160 int
arms_ssl_servercert_verify_cb(int ok,X509_STORE_CTX * ctx)161 arms_ssl_servercert_verify_cb(int ok, X509_STORE_CTX *ctx)
162 {
163 char cn[256];
164 const char *errmsg = NULL;
165 int error;
166
167 X509_NAME_oneline(
168 X509_get_subject_name(
169 X509_STORE_CTX_get_current_cert(ctx)), cn, sizeof(cn));
170
171 X509_NAME_oneline(
172 X509_get_issuer_name(
173 X509_STORE_CTX_get_current_cert(ctx)), cn, sizeof(cn));
174
175 error = X509_STORE_CTX_get_error(ctx);
176
177 if (!ok) {
178 switch (error) {
179 case X509_V_ERR_CERT_NOT_YET_VALID:
180 case X509_V_ERR_CERT_HAS_EXPIRED:
181 /* XXX: ignore Validity Not Before/Not After field */
182 ok = 1;
183 X509_STORE_CTX_set_error(ctx, X509_V_OK);
184 break;
185
186 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
187 errmsg =
188 "unable to get local issuer certificate"
189 "(certificate chain may be too long)";
190 break;
191
192 default:
193 errmsg = X509_verify_cert_error_string(error);
194 break;
195 }
196
197 }
198 if (ok) {
199 /* call libarms verify function */
200 SSL *ssl;
201 transaction *tr;
202
203 ssl = X509_STORE_CTX_get_ex_data(
204 ctx,
205 SSL_get_ex_data_X509_STORE_CTX_idx());
206
207 /* tunnel ssl is no transaction required. */
208 tr = SSL_get_ex_data(ssl, 0);
209 if (tr != NULL && TR_TYPE(tr->state) == TR_LSPULL)
210 ok = (verify_ls_cn(ctx, tr) == X509_V_OK);
211 }
212 if (!ok) {
213 libarms_log(ARMS_LOG_ESSL,
214 "verification failure of server certificate");
215 libarms_log(ARMS_LOG_ESSL,
216 "reason: %s", errmsg);
217 }
218 return ok;
219 }
220
221 static int
verify_ls_cn(X509_STORE_CTX * x509ctx,void * u)222 verify_ls_cn(X509_STORE_CTX *x509ctx, void *u)
223 {
224 char subject[256];
225
226 X509_NAME_oneline(
227 X509_get_subject_name(
228 X509_STORE_CTX_get_current_cert(x509ctx)),
229 subject, sizeof(subject));
230
231 if (strstr(subject, "CN=ARMS Root CA") != NULL)
232 return X509_V_OK;
233
234 if (strstr(subject, "CN=Location Server ") != NULL)
235 return X509_V_OK;
236
237 return -1;
238 }
239
240 void
arms_ssl_register_randomness(const void * seed,unsigned int len)241 arms_ssl_register_randomness(const void *seed, unsigned int len)
242 {
243 unsigned long zero = 0;
244 int n;
245 const int limit = 10000;
246
247 if (seed != NULL && len != 0)
248 RAND_seed(seed, len);
249 for (n = 0; RAND_status() != 1 && n < limit; n++)
250 RAND_seed(&zero, sizeof(zero));
251 /* if (n == limit) give up */
252 }
253
254 static void
arms_log_ssl_error(void)255 arms_log_ssl_error(void)
256 {
257 char errbuf[128];
258 int code, line, flags;
259 const char *file, *data;
260
261 while ((code = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
262 ERR_error_string_n(code, errbuf, sizeof(errbuf) - 8);
263 libarms_log(ARMS_LOG_ESSL, errbuf);
264 if (data != NULL && (flags & ERR_TXT_STRING)) {
265 libarms_log(ARMS_LOG_ESSL, data);
266 }
267 }
268 }
269
270 /*
271 * SSL_CTX_new wrapper
272 */
273 SSL_CTX *
arms_ssl_ctx_new(int type)274 arms_ssl_ctx_new(int type)
275 {
276 #if OPENSSL_VERSION_NUMBER >= 0x00909000L
277 const SSL_METHOD *method;
278 #else
279 SSL_METHOD *method;
280 #endif
281 SSL_CTX *ctx;
282 long mode;
283
284 switch (type) {
285 case ARMS_SSL_SERVER_METHOD:
286 method = TLSv1_server_method();
287 break;
288 case ARMS_SSL_CLIENT_METHOD:
289 method = TLSv1_client_method();
290 break;
291 default:
292 /* illegal type */
293 return NULL;
294
295 }
296 ctx = SSL_CTX_new(method);
297 if (ctx == NULL)
298 return NULL;
299
300 /* workaround for SSL_R_BAD_WRITE_RETRY by SSL_write. */
301 mode = SSL_CTX_get_mode(ctx);
302 /*mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;*/
303 mode |= SSL_MODE_AUTO_RETRY;
304 SSL_CTX_set_mode(ctx, mode);
305
306 return ctx;
307 }
308
309 /*
310 * SSL_new wrapper
311 */
312 SSL *
arms_ssl_new(SSL_CTX * ctx)313 arms_ssl_new(SSL_CTX *ctx)
314 {
315 return SSL_new(ctx);
316 }
317
318 /*
319 * SSL_connect wrapper
320 */
321 int
arms_ssl_connect(SSL * ssl)322 arms_ssl_connect(SSL *ssl)
323 {
324 int rv;
325
326 rv = SSL_connect(ssl);
327 if (rv <= 0) {
328 switch(SSL_get_error(ssl, rv)) {
329 case SSL_ERROR_WANT_READ:
330 case SSL_ERROR_WANT_WRITE:
331 case SSL_ERROR_NONE:
332 return 0;
333 case SSL_ERROR_SYSCALL:
334 arms_log_ssl_error();
335 libarms_log(ARMS_LOG_ESSL,
336 "SSL_connect: syscall errno %d", errno);
337 return -1;
338 case SSL_ERROR_ZERO_RETURN:
339 default:
340 arms_log_ssl_error();
341 if (rv == 0) {
342 rv = -1;
343 }
344 break;
345 }
346 }
347 return rv;
348 }
349
350 /*
351 * SSL_read wrapper
352 */
353 int
arms_ssl_read(SSL * ssl,char * buf,int len)354 arms_ssl_read(SSL *ssl, char *buf, int len)
355 {
356 int rv, err;
357
358 #ifdef ARMS_DEBUG_SSL_IO
359 memset(buf, 0, len);
360 #endif
361 rv = SSL_read(ssl, buf, len);
362 if (rv < 0) {
363 switch((err = SSL_get_error(ssl, rv))) {
364 case SSL_ERROR_WANT_READ:
365 case SSL_ERROR_WANT_WRITE:
366 case SSL_ERROR_NONE:
367 /*
368 * in non-blocking mode, negotiation is incomplete.
369 * call select(2) and re-calling it.
370 */
371 return 0;
372 case SSL_ERROR_SYSCALL:
373 arms_log_ssl_error();
374 libarms_log(ARMS_LOG_ESSL,
375 "SSL_read: syscall errno %d\n", errno);
376 break;
377 case SSL_ERROR_ZERO_RETURN:
378 default:
379 arms_log_ssl_error();
380 libarms_log(ARMS_LOG_ESSL,
381 "SSL_read: OpenSSL Connection reset by peer (%d)", err);
382 break;
383 }
384 } else if (rv == 0) {
385 /* received shutdown. */
386 rv = -1;
387 }
388 #ifdef ARMS_DEBUG_SSL_IO
389 else printf("%s: (((%s)))\n", __func__, buf);
390 #endif
391 return rv;
392 }
393
394 /*
395 * SSL_write wrapper
396 */
397 int
arms_ssl_write(SSL * ssl,const char * buf,int len)398 arms_ssl_write(SSL *ssl, const char *buf, int len)
399 {
400 int rv, err;
401
402 if (len == 0) {
403 libarms_log(ARMS_LOG_DEBUG,
404 "try to write zero bytes. nothing to do.\n");
405 return 0;
406 }
407 rv = SSL_write(ssl, buf, len);
408 if (rv < 0) {
409 switch((err = SSL_get_error(ssl, rv))) {
410 case SSL_ERROR_WANT_READ:
411 case SSL_ERROR_WANT_WRITE:
412 case SSL_ERROR_NONE:
413 /*
414 * in non-blocking mode, negotiation is incomplete.
415 * call select(2) and re-calling it.
416 */
417 return 0;
418 case SSL_ERROR_SYSCALL:
419 arms_log_ssl_error();
420 libarms_log(ARMS_LOG_ESSL,
421 "SSL_write: syscall errno %d\n", errno);
422 break;
423 case SSL_ERROR_ZERO_RETURN:
424 default:
425 arms_log_ssl_error();
426 libarms_log(ARMS_LOG_ESSL,
427 "SSL_write: OpenSSL Connection reset by peer (%d)", err);
428 break;
429 }
430 } else if (rv == 0) {
431 /* received shutdown. */
432 rv = -1;
433 }
434 #ifdef ARMS_DEBUG_SSL_IO
435 else libarms_log(ARMS_LOG_DEBUG, "%s: (((%s)))\n", __func__, buf);
436 #endif
437 return rv;
438 }
439
440 /*
441 * SSL_shutdown wrapper
442 */
443 void
arms_ssl_shutdown(SSL * ssl)444 arms_ssl_shutdown(SSL *ssl)
445 {
446 int i, fd, on;
447
448 /*
449 * switch to non-blocking mode
450 */
451 fd = SSL_get_fd(ssl);
452 on = 1;
453 ioctl(fd, FIONBIO, &on);
454 /*
455 * 0... incomplete shutdown. recall it.
456 * 1... shutdown complete.
457 * -1.. already shutdown by peer.
458 */
459 for (i = 0; i < 4; i++) {
460 if (SSL_shutdown(ssl) != 0)
461 break;
462 }
463 }
464
465 /*
466 * SSL_free wrapper
467 */
468 void
arms_ssl_free(SSL * ssl)469 arms_ssl_free(SSL *ssl)
470 {
471 SSL_free(ssl);
472 }
473
474 /*
475 * SSL_CTX_free wrapper
476 */
477 void
arms_ssl_ctx_free(SSL_CTX * ctx)478 arms_ssl_ctx_free(SSL_CTX *ctx)
479 {
480 SSL_CTX_free(ctx);
481 }
482