34 #include <openssl/ssl.h>
35 #include <openssl/err.h>
39 static const int ERR_BUF_SIZE = 256;
40 const std::string TLSStream::TAG =
"TLSStream";
42 SSL_CTX *TLSStream::_ssl_ctx = NULL;
43 bool TLSStream::_initialized =
false;
44 bool TLSStream::_SSL_initialized =
false;
48 : iostream(this), _activated(false), in_buf_(BUFF_SIZE), out_buf_(BUFF_SIZE),
49 _stream(stream), _server(false), _ssl(NULL), _peer_cert(NULL), _iostreamBIO(NULL)
54 setp(&out_buf_[0], &out_buf_[0] +
BUFF_SIZE - 1);
59 if(_ssl) SSL_free(_ssl);
60 if (_iostreamBIO != NULL)
delete _iostreamBIO;
85 _ssl = SSL_new(_ssl_ctx);
87 char err_buf[ERR_BUF_SIZE];
88 ERR_error_string_n(ERR_get_error(), err_buf, ERR_BUF_SIZE);
89 err_buf[ERR_BUF_SIZE - 1] =
'\0';
96 SSL_set_accept_state(_ssl);
98 SSL_set_connect_state(_ssl);
109 SSL_set_bio(_ssl, _iostreamBIO->
getBIO(), _iostreamBIO->
getBIO());
111 if (_iostreamBIO != NULL)
delete _iostreamBIO;
119 error = SSL_do_handshake(_ssl);
121 int errcode = SSL_get_error(_ssl, static_cast<int>(error));
126 if (_iostreamBIO != NULL)
delete _iostreamBIO;
133 _peer_cert = SSL_get_peer_certificate(_ssl);
134 if((error = SSL_get_verify_result(_ssl)) != X509_V_OK || _peer_cert == NULL){
137 X509_free(_peer_cert);
140 if (_iostreamBIO != NULL)
delete _iostreamBIO;
144 std::stringstream ss; ss <<
"Certificate verification error " << error <<
".";
161 num_bytes = SSL_read(_ssl, &in_buf_[0],
BUFF_SIZE);
164 if(SSL_get_error(_ssl, num_bytes) == SSL_ERROR_ZERO_RETURN){
170 return traits::eof();
171 }
else if(num_bytes < 0) {
173 return traits::eof();
180 num_bytes =
static_cast<int>( _stream->read(&in_buf_[0], 1).readsome(&in_buf_[0]+1,
BUFF_SIZE-1) + 1 );
181 }
catch(ios_base::failure &ex){
186 return traits::eof();
190 return traits::eof();
194 return traits::eof();
198 setg(&in_buf_[0], &in_buf_[0], &in_buf_[0] + num_bytes);
200 return traits::not_eof(in_buf_[0]);
206 char *ibegin = &out_buf_[0];
210 setp(&out_buf_[0], &out_buf_[0] +
BUFF_SIZE - 1);
213 if(!traits::eq_int_type(c, traits::eof())) {
214 *iend++ = traits::to_char_type(c);
218 if ((iend - ibegin) == 0)
220 return traits::not_eof(c);
226 num_bytes = SSL_write(_ssl, &out_buf_[0], static_cast<int>(iend - ibegin));
229 return traits::eof();
230 }
else if(num_bytes < 0){
232 return traits::eof();
238 _stream->write(&out_buf_[0], (iend - ibegin));
239 }
catch(ios_base::failure &ex){
242 if (_stream->bad()) {
244 return traits::eof();
248 return traits::not_eof(c);
261 if(!_SSL_initialized){
262 SSL_load_error_strings();
264 ERR_load_BIO_strings();
265 ERR_load_SSL_strings();
266 _SSL_initialized =
true;
271 _ssl_ctx = SSL_CTX_new(TLSv1_method());
273 char err_buf[ERR_BUF_SIZE];
274 ERR_error_string_n(ERR_get_error(), err_buf, ERR_BUF_SIZE);
275 err_buf[ERR_BUF_SIZE - 1] =
'\0';
282 SSL_CTX_set_verify(_ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
286 if(SSL_CTX_load_verify_locations(_ssl_ctx, NULL, trustedCAPath.
getPath().c_str()) != 1){
295 if(!certificate || SSL_CTX_use_certificate(_ssl_ctx, certificate) != 1){
297 SSL_CTX_free(_ssl_ctx);
301 if(!privateKey || SSL_CTX_use_PrivateKey(_ssl_ctx, privateKey) != 1){
303 SSL_CTX_free(_ssl_ctx);
309 std::list<ibrcommon::File> files;
310 if(trustedCAPath.
getFiles(files) == 0){
312 for(std::list<ibrcommon::File>::iterator it = files.begin();
313 it != files.end(); ++it){
314 if(it->getType() == DT_LNK || it->isSystem() || it->isDirectory())
318 FILE *fp = fopen(it->getPath().c_str(),
"r");
319 if(fp && PEM_read_X509(fp, &cert, NULL, NULL)){
320 if(SSL_CTX_add_client_CA(_ssl_ctx, cert) != 1){
332 if(!enableEncryption){
333 if(!SSL_CTX_set_cipher_list(_ssl_ctx,
"eNULL")){
350 SSL_CTX_free(_ssl_ctx);
354 _initialized =
false;
362 if(_ssl && _stream->good()){
364 if((ret = SSL_shutdown(_ssl)) == -1) {
368 if((ret = SSL_shutdown(_ssl)) == -1){
379 int ret = traits::eq_int_type(this->
overflow(
380 traits::eof()), traits::eof()) ? -1
389 std::string TLSStream::log_error_msg(
int errnumber)
397 case SSL_ERROR_ZERO_RETURN:
398 ret =
"TLS Connection has been closed.";
400 case SSL_ERROR_WANT_READ:
401 case SSL_ERROR_WANT_WRITE:
402 ret =
"WANT_READ/WANT_WRITE";
404 case SSL_ERROR_WANT_CONNECT:
405 case SSL_ERROR_WANT_ACCEPT:
406 ret =
"WANT_CONNECT/WANT_ACCEPT";
408 case SSL_ERROR_WANT_X509_LOOKUP:
409 ret =
"WANT_X509_LOOKUP";
411 case SSL_ERROR_SYSCALL:
412 ret =
"Syscall error.";
415 char err_buf[ERR_BUF_SIZE];
416 ERR_error_string_n(ERR_get_error(), err_buf, ERR_BUF_SIZE);
417 err_buf[ERR_BUF_SIZE - 1] =
'\0';
418 std::stringstream ss; ss <<
"SSL error: \"" << err_buf <<
"\".";
423 std::stringstream ss; ss <<
"Unknown error code " << errnumber <<
".";