blob: dad15a5b15a381594dc6222bc4f9e5d0b5ddbf3a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SSLImpl.hpp"
#include <cstdint>
#include <stdexcept>
#include <ace/Guard_T.h>
namespace apache {
namespace geode {
namespace client {
ACE_Recursive_Thread_Mutex SSLImpl::s_mutex;
volatile bool SSLImpl::s_initialized = false;
void *gf_create_SslImpl(ACE_HANDLE sock, const char *pubkeyfile,
const char *privkeyfile, const char *pemPassword) {
return reinterpret_cast<void *>(
new SSLImpl(sock, pubkeyfile, privkeyfile, pemPassword));
}
void gf_destroy_SslImpl(void *impl) {
SSLImpl *theLib = reinterpret_cast<SSLImpl *>(impl);
delete theLib;
}
extern "C" {
static int pem_passwd_cb(char *buf, int size, int /*rwflag*/, void *passwd) {
strncpy(buf, (char *)passwd, size);
buf[size - 1] = '\0';
return static_cast<int>(strlen(buf));
}
}
SSLImpl::SSLImpl(ACE_HANDLE sock, const char *pubkeyfile,
const char *privkeyfile, const char *password) {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);
if (SSLImpl::s_initialized == false) {
ACE_SSL_Context *sslContext = ACE_SSL_Context::instance();
SSL_CTX_set_cipher_list(sslContext->context(), "DEFAULT");
sslContext->set_mode(ACE_SSL_Context::SSLv23_client);
sslContext->set_verify_peer();
if (sslContext->load_trusted_ca(pubkeyfile) != 0) {
throw std::invalid_argument("Failed to read SSL trust store.");
}
if (strlen(password) > 0) {
SSL_CTX_set_default_passwd_cb(sslContext->context(), pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(sslContext->context(),
const_cast<char *>(password));
}
if (privkeyfile && *privkeyfile) {
if (sslContext->certificate(privkeyfile) != 0) {
throw std::invalid_argument("Failed to read SSL certificate.");
}
if (sslContext->private_key(privkeyfile) != 0) {
throw std::invalid_argument("Invalid SSL keystore password.");
}
if (::SSL_CTX_use_certificate_chain_file(sslContext->context(),
privkeyfile) <= 0) {
throw std::invalid_argument("Failed to read SSL certificate chain.");
}
}
SSLImpl::s_initialized = true;
}
m_io = new ACE_SSL_SOCK_Stream();
m_io->set_handle(sock);
}
SSLImpl::~SSLImpl() {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);
if (m_io) {
delete m_io;
}
}
void SSLImpl::close() {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);
if (m_io) {
m_io->close();
}
}
int SSLImpl::setOption(int level, int option, void *optval, int optlen) {
return m_io->set_option(level, option, optval, optlen);
}
int SSLImpl::listen(ACE_INET_Addr addr, std::chrono::microseconds waitSeconds) {
ACE_SSL_SOCK_Acceptor listener(addr, 1);
if (waitSeconds > std::chrono::microseconds::zero()) {
ACE_Time_Value wtime(waitSeconds);
return listener.accept(*m_io, nullptr, &wtime);
} else {
return listener.accept(*m_io, nullptr);
}
}
int SSLImpl::connect(ACE_INET_Addr ipaddr,
std::chrono::microseconds waitSeconds) {
ACE_SSL_SOCK_Connector conn;
if (waitSeconds > std::chrono::microseconds::zero()) {
ACE_Time_Value wtime(waitSeconds);
return conn.connect(*m_io, ipaddr, &wtime);
} else {
return conn.connect(*m_io, ipaddr);
}
}
ssize_t SSLImpl::recv(void *buf, size_t len, const ACE_Time_Value *timeout,
size_t *bytes_transferred) {
return m_io->recv_n(buf, len, 0, timeout, bytes_transferred);
}
ssize_t SSLImpl::send(const void *buf, size_t len,
const ACE_Time_Value *timeout,
size_t *bytes_transferred) {
return m_io->send_n(buf, len, 0, timeout, bytes_transferred);
}
int SSLImpl::getLocalAddr(ACE_Addr &addr) { return m_io->get_local_addr(addr); }
} // namespace client
} // namespace geode
} // namespace apache