mirror of
https://github.com/Icinga/icinga2.git
synced 2025-08-25 03:28:12 +02:00
116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
//
|
|
// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
|
|
#ifndef BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP
|
|
#define BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP
|
|
|
|
#include <boost/wintls/detail/sspi_functions.hpp>
|
|
#include <boost/wintls/detail/decrypt_buffers.hpp>
|
|
#include <boost/wintls/detail/decrypted_data_buffer.hpp>
|
|
#include <boost/wintls/detail/sspi_sec_handle.hpp>
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
|
|
namespace boost {
|
|
namespace wintls {
|
|
namespace detail {
|
|
|
|
class sspi_decrypt {
|
|
public:
|
|
enum class state {
|
|
data_needed,
|
|
data_available,
|
|
error
|
|
};
|
|
|
|
sspi_decrypt(ctxt_handle& ctxt_handle)
|
|
: size_decrypted(0)
|
|
, input_buffer(net::buffer(encrypted_data_))
|
|
, ctxt_handle_(ctxt_handle)
|
|
, last_error_(SEC_E_OK) {
|
|
buffers_[0].pvBuffer = encrypted_data_.data();
|
|
}
|
|
|
|
template <class MutableBufferSequence>
|
|
state operator()(const MutableBufferSequence& output_buffers) {
|
|
if (!decrypted_data_.empty()) {
|
|
size_decrypted = decrypted_data_.get(output_buffers);
|
|
return state::data_available;
|
|
}
|
|
|
|
if (buffers_[0].cbBuffer == 0) {
|
|
input_buffer = net::buffer(encrypted_data_);
|
|
return state::data_needed;
|
|
}
|
|
|
|
buffers_[0].BufferType = SECBUFFER_DATA;
|
|
buffers_[1].BufferType = SECBUFFER_EMPTY;
|
|
buffers_[2].BufferType = SECBUFFER_EMPTY;
|
|
buffers_[3].BufferType = SECBUFFER_EMPTY;
|
|
|
|
input_buffer = net::buffer(encrypted_data_) + buffers_[0].cbBuffer;
|
|
const auto size = buffers_[0].cbBuffer;
|
|
last_error_ = detail::sspi_functions::DecryptMessage(ctxt_handle_.get(), buffers_.desc(), 0, nullptr);
|
|
|
|
if (last_error_ == SEC_E_INCOMPLETE_MESSAGE) {
|
|
buffers_[0].cbBuffer = size;
|
|
return state::data_needed;
|
|
}
|
|
|
|
if (last_error_ != SEC_E_OK) {
|
|
return state::error;
|
|
}
|
|
|
|
if (buffers_[1].BufferType == SECBUFFER_DATA) {
|
|
const auto data_ptr = reinterpret_cast<const char*>(buffers_[1].pvBuffer);
|
|
const auto data_size = buffers_[1].cbBuffer;
|
|
size_decrypted = net::buffer_copy(output_buffers, net::buffer(data_ptr, data_size));
|
|
if (size_decrypted < data_size) {
|
|
decrypted_data_.fill(net::buffer(data_ptr + size_decrypted, data_size - size_decrypted));
|
|
}
|
|
}
|
|
|
|
if (buffers_[3].BufferType == SECBUFFER_EXTRA) {
|
|
const auto extra_size = buffers_[3].cbBuffer;
|
|
std::memmove(encrypted_data_.data(), buffers_[3].pvBuffer, extra_size);
|
|
buffers_[0].cbBuffer = extra_size;
|
|
} else {
|
|
buffers_[0].cbBuffer = 0;
|
|
}
|
|
|
|
return state::data_available;
|
|
}
|
|
|
|
void size_read(std::size_t size) {
|
|
buffers_[0].cbBuffer += static_cast<unsigned long>(size);
|
|
input_buffer = net::buffer(encrypted_data_) + buffers_[0].cbBuffer;
|
|
}
|
|
|
|
std::size_t size_decrypted;
|
|
net::mutable_buffer input_buffer;
|
|
|
|
boost::system::error_code last_error() const {
|
|
return error::make_error_code(last_error_);
|
|
}
|
|
|
|
private:
|
|
static constexpr std::size_t buffer_size = 0x10000;
|
|
|
|
ctxt_handle& ctxt_handle_;
|
|
SECURITY_STATUS last_error_;
|
|
decrypt_buffers buffers_;
|
|
std::array<char, buffer_size> encrypted_data_;
|
|
decrypted_data_buffer<buffer_size> decrypted_data_;
|
|
};
|
|
|
|
} // namespace detail
|
|
} // namespace wintls
|
|
} // namespace boost
|
|
|
|
#endif // BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP
|