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