summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_kmip_client_impl.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/rgw/rgw_kmip_client_impl.cc
parentInitial commit. (diff)
downloadceph-upstream/16.2.11+ds.tar.xz
ceph-upstream/16.2.11+ds.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/rgw/rgw_kmip_client_impl.cc')
-rw-r--r--src/rgw/rgw_kmip_client_impl.cc728
1 files changed, 728 insertions, 0 deletions
diff --git a/src/rgw/rgw_kmip_client_impl.cc b/src/rgw/rgw_kmip_client_impl.cc
new file mode 100644
index 000000000..0824273e6
--- /dev/null
+++ b/src/rgw/rgw_kmip_client_impl.cc
@@ -0,0 +1,728 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+#include <boost/intrusive/list.hpp>
+#include <atomic>
+#include <mutex>
+#include <string.h>
+
+#include "include/compat.h"
+#include "common/errno.h"
+#include "rgw_common.h"
+#include "rgw_kmip_client.h"
+#include "rgw_kmip_client_impl.h"
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+extern "C" {
+#include "kmip.h"
+#include "kmip_bio.h"
+#include "kmip_memset.h"
+};
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rgw
+
+static enum kmip_version protocol_version = KMIP_1_0;
+
+struct RGWKmipHandle {
+ int uses;
+ mono_time lastuse;
+ SSL_CTX *ctx;
+ SSL *ssl;
+ BIO *bio;
+ KMIP kmip_ctx[1];
+ TextString textstrings[2];
+ UsernamePasswordCredential upc[1];
+ Credential credential[1];
+ int need_to_free_kmip;
+ size_t buffer_blocks, buffer_block_size, buffer_total_size;
+ uint8 *encoding;
+
+ explicit RGWKmipHandle() :
+ uses(0), ctx(0), ssl(0), bio(0),
+ need_to_free_kmip(0),
+ encoding(0) {
+ memset(kmip_ctx, 0, sizeof kmip_ctx);
+ memset(textstrings, 0, sizeof textstrings);
+ memset(upc, 0, sizeof upc);
+ memset(credential, 0, sizeof credential);
+ };
+};
+
+struct RGWKmipWorker: public Thread {
+ RGWKMIPManagerImpl &m;
+ RGWKmipWorker(RGWKMIPManagerImpl& m) : m(m) {}
+ void *entry() override;
+ void signal() {
+ std::lock_guard l{m.lock};
+ m.cond.notify_all();
+ }
+};
+
+static void
+kmip_free_handle_stuff(RGWKmipHandle *kmip)
+{
+ if (kmip->encoding) {
+ kmip_free_buffer(kmip->kmip_ctx,
+ kmip->encoding,
+ kmip->buffer_total_size);
+ kmip_set_buffer(kmip->kmip_ctx, NULL, 0);
+ }
+ if (kmip->need_to_free_kmip)
+ kmip_destroy(kmip->kmip_ctx);
+ if (kmip->bio)
+ BIO_free_all(kmip->bio);
+ if (kmip->ctx)
+ SSL_CTX_free(kmip->ctx);
+}
+
+class RGWKmipHandleBuilder {
+private:
+ CephContext *cct;
+ const char *clientcert = 0;
+ const char *clientkey = 0;
+ const char *capath = 0;
+ const char *host = 0;
+ const char *portstring = 0;
+ const char *username = 0;
+ const char *password = 0;
+public:
+ RGWKmipHandleBuilder(CephContext *cct) : cct(cct) {};
+ RGWKmipHandleBuilder& set_clientcert(const std::string &v) {
+ const char *s = v.c_str();
+ if (*s) {
+ clientcert = s;
+ }
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_clientkey(const std::string &v) {
+ const char *s = v.c_str();
+ if (*s) {
+ clientkey = s;
+ }
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_capath(const std::string &v) {
+ const char *s = v.c_str();
+ if (*s) {
+ capath = s;
+ }
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_host(const char *v) {
+ host = v;
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_portstring(const char *v) {
+ portstring = v;
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_username(const std::string &v) {
+ const char *s = v.c_str();
+ if (*s) {
+ username = s;
+ }
+ return *this;
+ }
+ RGWKmipHandleBuilder& set_password(const std::string& v) {
+ const char *s = v.c_str();
+ if (*s) {
+ password = s;
+ }
+ return *this;
+ }
+ RGWKmipHandle *build() const;
+};
+
+static int
+kmip_write_an_error_helper(const char *s, size_t l, void *u) {
+ CephContext *cct = (CephContext *)u;
+ std::string_view es(s, l);
+ lderr(cct) << es << dendl;
+ return l;
+}
+
+void
+ERR_print_errors_ceph(CephContext *cct)
+{
+ ERR_print_errors_cb(kmip_write_an_error_helper, cct);
+}
+
+RGWKmipHandle *
+RGWKmipHandleBuilder::build() const
+{
+ int failed = 1;
+ RGWKmipHandle *r = new RGWKmipHandle();
+ TextString *up = 0;
+ size_t ns;
+
+ r->ctx = SSL_CTX_new(TLS_client_method());
+
+ if (!clientcert)
+ ;
+ else if (SSL_CTX_use_certificate_file(r->ctx, clientcert, SSL_FILETYPE_PEM) != 1) {
+ lderr(cct) << "ERROR: can't load client cert from "
+ << clientcert << dendl;
+ ERR_print_errors_ceph(cct);
+ goto Done;
+ }
+
+ if (!clientkey)
+ ;
+ else if (SSL_CTX_use_PrivateKey_file(r->ctx, clientkey,
+ SSL_FILETYPE_PEM) != 1) {
+ lderr(cct) << "ERROR: can't load client key from "
+ << clientkey << dendl;
+ ERR_print_errors_ceph(cct);
+ goto Done;
+ }
+
+ if (!capath)
+ ;
+ else if (SSL_CTX_load_verify_locations(r->ctx, capath, NULL) != 1) {
+ lderr(cct) << "ERROR: can't load cacert from "
+ << capath << dendl;
+ ERR_print_errors_ceph(cct);
+ goto Done;
+ }
+ r->bio = BIO_new_ssl_connect(r->ctx);
+ if (!r->bio) {
+ lderr(cct) << "BIO_new_ssl_connect failed" << dendl;
+ goto Done;
+ }
+ BIO_get_ssl(r->bio, &r->ssl);
+ SSL_set_mode(r->ssl, SSL_MODE_AUTO_RETRY);
+
+ BIO_set_conn_hostname(r->bio, host);
+ BIO_set_conn_port(r->bio, portstring);
+ if (BIO_do_connect(r->bio) != 1) {
+ lderr(cct) << "BIO_do_connect failed to " << host
+ << ":" << portstring << dendl;
+ ERR_print_errors_ceph(cct);
+ goto Done;
+ }
+
+ // setup kmip
+
+ kmip_init(r->kmip_ctx, NULL, 0, protocol_version);
+ r->need_to_free_kmip = 1;
+ r->buffer_blocks = 1;
+ r->buffer_block_size = 1024;
+ r->encoding = static_cast<uint8*>(r->kmip_ctx->calloc_func(
+ r->kmip_ctx->state, r->buffer_blocks, r->buffer_block_size));
+ if (!r->encoding) {
+ lderr(cct) << "kmip buffer alloc failed: "
+ << r->buffer_blocks <<
+ " * " << r->buffer_block_size << dendl;
+ goto Done;
+ }
+ ns = r->buffer_blocks * r->buffer_block_size;
+ kmip_set_buffer(r->kmip_ctx, r->encoding, ns);
+ r->buffer_total_size = ns;
+
+ up = r->textstrings;
+ if (username) {
+ memset(r->upc, 0, sizeof *r->upc);
+ up->value = (char *) username;
+ up->size = strlen(username);
+ r->upc->username = up++;
+ if (password) {
+ up->value = (char *) password;
+ up->size = strlen(password);
+ r->upc->password = up++;
+ }
+ r->credential->credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
+ r->credential->credential_value = r->upc;
+ int i = kmip_add_credential(r->kmip_ctx, r->credential);
+ if (i != KMIP_OK) {
+ fprintf(stderr,"failed to add credential to kmip\n");
+ goto Done;
+ }
+ }
+
+ failed = 0;
+Done:
+ if (!failed)
+ ;
+ else if (!r)
+ ;
+ else {
+ kmip_free_handle_stuff(r);
+ delete r;
+ r = 0;
+ }
+ return r;
+}
+
+struct RGWKmipHandles : public Thread {
+ CephContext *cct;
+ ceph::mutex cleaner_lock = ceph::make_mutex("RGWKmipHandles::cleaner_lock");
+ std::vector<RGWKmipHandle*> saved_kmip;
+ int cleaner_shutdown;
+ bool cleaner_active = false;
+ ceph::condition_variable cleaner_cond;
+ RGWKmipHandles(CephContext *cct) :
+ cct(cct), cleaner_shutdown{0} {
+ }
+ RGWKmipHandle* get_kmip_handle();
+ void release_kmip_handle_now(RGWKmipHandle* kmip);
+ void release_kmip_handle(RGWKmipHandle* kmip);
+ void flush_kmip_handles();
+ int do_one_entry(RGWKMIPTransceiver &element);
+ void* entry();
+ void start();
+ void stop();
+};
+
+RGWKmipHandle*
+RGWKmipHandles::get_kmip_handle()
+{
+ RGWKmipHandle* kmip = 0;
+ const char *hostaddr = cct->_conf->rgw_crypt_kmip_addr.c_str();
+ {
+ std::lock_guard lock{cleaner_lock};
+ if (!saved_kmip.empty()) {
+ kmip = *saved_kmip.begin();
+ saved_kmip.erase(saved_kmip.begin());
+ }
+ }
+ if (!kmip && hostaddr) {
+ char *hosttemp = strdup(hostaddr);
+ char *port = strchr(hosttemp, ':');
+ if (port)
+ *port++ = 0;
+ kmip = RGWKmipHandleBuilder{cct}
+ .set_clientcert(cct->_conf->rgw_crypt_kmip_client_cert)
+ .set_clientkey(cct->_conf->rgw_crypt_kmip_client_key)
+ .set_capath(cct->_conf->rgw_crypt_kmip_ca_path)
+ .set_host(hosttemp)
+ .set_portstring(port ? port : "5696")
+ .set_username(cct->_conf->rgw_crypt_kmip_username)
+ .set_password(cct->_conf->rgw_crypt_kmip_password)
+ .build();
+ free(hosttemp);
+ }
+ return kmip;
+}
+
+void
+RGWKmipHandles::release_kmip_handle_now(RGWKmipHandle* kmip)
+{
+ kmip_free_handle_stuff(kmip);
+ delete kmip;
+}
+
+#define MAXIDLE 5
+void
+RGWKmipHandles::release_kmip_handle(RGWKmipHandle* kmip)
+{
+ if (cleaner_shutdown) {
+ release_kmip_handle_now(kmip);
+ } else {
+ std::lock_guard lock{cleaner_lock};
+ kmip->lastuse = mono_clock::now();
+ saved_kmip.insert(saved_kmip.begin(), 1, kmip);
+ }
+}
+
+void*
+RGWKmipHandles::entry()
+{
+ RGWKmipHandle* kmip;
+ std::unique_lock lock{cleaner_lock};
+
+ for (;;) {
+ if (cleaner_shutdown) {
+ if (saved_kmip.empty())
+ break;
+ } else {
+ cleaner_cond.wait_for(lock, std::chrono::seconds(MAXIDLE));
+ }
+ mono_time now = mono_clock::now();
+ while (!saved_kmip.empty()) {
+ auto cend = saved_kmip.end();
+ --cend;
+ kmip = *cend;
+ if (!cleaner_shutdown && now - kmip->lastuse
+ < std::chrono::seconds(MAXIDLE))
+ break;
+ saved_kmip.erase(cend);
+ release_kmip_handle_now(kmip);
+ }
+ }
+ return nullptr;
+}
+
+void
+RGWKmipHandles::start()
+{
+ std::lock_guard lock{cleaner_lock};
+ if (!cleaner_active) {
+ cleaner_active = true;
+ this->create("KMIPcleaner"); // len<16!!!
+ }
+}
+
+void
+RGWKmipHandles::stop()
+{
+ std::unique_lock lock{cleaner_lock};
+ cleaner_shutdown = 1;
+ cleaner_cond.notify_all();
+ if (cleaner_active) {
+ lock.unlock();
+ this->join();
+ cleaner_active = false;
+ }
+}
+
+void
+RGWKmipHandles::flush_kmip_handles()
+{
+ stop();
+ join();
+ if (!saved_kmip.empty()) {
+ ldout(cct, 0) << "ERROR: " << __func__ << " failed final cleanup" << dendl;
+ }
+ saved_kmip.shrink_to_fit();
+}
+
+int
+RGWKMIPManagerImpl::start()
+{
+ if (worker) {
+ lderr(cct) << "kmip worker already started" << dendl;
+ return -1;
+ }
+ worker = new RGWKmipWorker(*this);
+ worker->create("kmip worker");
+ return 0;
+}
+
+void
+RGWKMIPManagerImpl::stop()
+{
+ going_down = true;
+ if (worker) {
+ worker->signal();
+ worker->join();
+ delete worker;
+ worker = 0;
+ }
+}
+
+int
+RGWKMIPManagerImpl::add_request(RGWKMIPTransceiver *req)
+{
+ std::unique_lock l{lock};
+ if (going_down)
+ return -ECANCELED;
+ requests.push_back(*new Request{*req});
+ l.unlock();
+ if (worker)
+ worker->signal();
+ return 0;
+}
+
+int
+RGWKmipHandles::do_one_entry(RGWKMIPTransceiver &element)
+{
+ auto h = get_kmip_handle();
+ std::unique_lock l{element.lock};
+ Attribute a[8], *ap;
+ TextString nvalue[1], uvalue[1];
+ Name nattr[1];
+ enum cryptographic_algorithm alg = KMIP_CRYPTOALG_AES;
+ int32 length = 256;
+ int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
+ size_t ns;
+ ProtocolVersion pv[1];
+ RequestHeader rh[1];
+ RequestMessage rm[1];
+ Authentication auth[1];
+ ResponseMessage resp_m[1];
+ int i;
+ union {
+ CreateRequestPayload create_req[1];
+ LocateRequestPayload locate_req[1];
+ GetRequestPayload get_req[1];
+ GetAttributeListRequestPayload lsattrs_req[1];
+ GetAttributesRequestPayload getattrs_req[1];
+ } u[1];
+ RequestBatchItem rbi[1];
+ TemplateAttribute ta[1];
+ const char *what = "?";
+ int need_to_free_response = 0;
+ char *response = NULL;
+ int response_size = 0;
+ enum result_status rs;
+ ResponseBatchItem *req;
+
+ if (!h) {
+ element.ret = -ERR_SERVICE_UNAVAILABLE;
+ return element.ret;
+ }
+ memset(a, 0, sizeof *a);
+ for (i = 0; i < (int)(sizeof a/sizeof *a); ++i)
+ kmip_init_attribute(a+i);
+ ap = a;
+ switch(element.operation) {
+ case RGWKMIPTransceiver::CREATE:
+ ap->type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
+ ap->value = &alg;
+ ++ap;
+ ap->type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
+ ap->value = &length;
+ ++ap;
+ ap->type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
+ ap->value = &mask;
+ ++ap;
+ break;
+ default:
+ break;
+ }
+ if (element.name) {
+ memset(nvalue, 0, sizeof *nvalue);
+ nvalue->value = element.name;
+ nvalue->size = strlen(element.name);
+ memset(nattr, 0, sizeof *nattr);
+ nattr->value = nvalue;
+ nattr->type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
+ ap->type = KMIP_ATTR_NAME;
+ ap->value = nattr;
+ ++ap;
+ }
+ if (element.unique_id) {
+ memset(uvalue, 0, sizeof *uvalue);
+ uvalue->value = element.unique_id;
+ uvalue->size = strlen(element.unique_id);
+ }
+ memset(pv, 0, sizeof *pv);
+ memset(rh, 0, sizeof *rh);
+ memset(rm, 0, sizeof *rm);
+ memset(auth, 0, sizeof *auth);
+ memset(resp_m, 0, sizeof *resp_m);
+ kmip_init_protocol_version(pv, h->kmip_ctx->version);
+ kmip_init_request_header(rh);
+ rh->protocol_version = pv;
+ rh->maximum_response_size = h->kmip_ctx->max_message_size;
+ rh->time_stamp = time(NULL);
+ rh->batch_count = 1;
+ memset(rbi, 0, sizeof *rbi);
+ kmip_init_request_batch_item(rbi);
+ memset(u, 0, sizeof *u);
+ rbi->request_payload = u;
+ switch(element.operation) {
+ case RGWKMIPTransceiver::CREATE:
+ memset(ta, 0, sizeof *ta);
+ ta->attributes = a;
+ ta->attribute_count = ap-a;
+ u->create_req->object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
+ u->create_req->template_attribute = ta;
+ rbi->operation = KMIP_OP_CREATE;
+ what = "create";
+ break;
+ case RGWKMIPTransceiver::GET:
+ if (element.unique_id)
+ u->get_req->unique_identifier = uvalue;
+ rbi->operation = KMIP_OP_GET;
+ what = "get";
+ break;
+ case RGWKMIPTransceiver::LOCATE:
+ if (ap > a) {
+ u->locate_req->attributes = a;
+ u->locate_req->attribute_count = ap - a;
+ }
+ rbi->operation = KMIP_OP_LOCATE;
+ what = "locate";
+ break;
+ case RGWKMIPTransceiver::GET_ATTRIBUTES:
+ case RGWKMIPTransceiver::GET_ATTRIBUTE_LIST:
+ case RGWKMIPTransceiver::DESTROY:
+ default:
+ lderr(cct) << "Missing operation logic op=" << element.operation << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ rm->request_header = rh;
+ rm->batch_items = rbi;
+ rm->batch_count = 1;
+ if (h->kmip_ctx->credential_list) {
+ LinkedListItem *item = h->kmip_ctx->credential_list->head;
+ if (item) {
+ auth->credential = (Credential *)item->data;
+ rh->authentication = auth;
+ }
+ }
+ for (;;) {
+ i = kmip_encode_request_message(h->kmip_ctx, rm);
+ if (i != KMIP_ERROR_BUFFER_FULL) break;
+ h->kmip_ctx->free_func(h->kmip_ctx->state, h->encoding);
+ h->encoding = 0;
+ ++h->buffer_blocks;
+ h->encoding = static_cast<uint8*>(h->kmip_ctx->calloc_func(h->kmip_ctx->state, h->buffer_blocks, h->buffer_block_size));
+ if (!h->encoding) {
+ lderr(cct) << "kmip buffer alloc failed: "
+ << h->buffer_blocks
+ << " * " << h->buffer_block_size << dendl;
+ element.ret = -ENOMEM;
+ goto Done;
+ }
+ ns = h->buffer_blocks * h->buffer_block_size;
+ kmip_set_buffer(h->kmip_ctx, h->encoding, ns);
+ h->buffer_total_size = ns;
+ }
+ if (i != KMIP_OK) {
+ lderr(cct) << " Failed to encode " << what
+ << " request; err=" << i
+ << " ctx error message " << h->kmip_ctx->error_message
+ << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ i = kmip_bio_send_request_encoding(h->kmip_ctx, h->bio,
+ (char*)h->encoding,
+ h->kmip_ctx->index - h->kmip_ctx->buffer,
+ &response, &response_size);
+ if (i < 0) {
+ lderr(cct) << "Problem sending request to " << what << " " << i << " context error message " << h->kmip_ctx->error_message << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ kmip_free_buffer(h->kmip_ctx, h->encoding,
+ h->buffer_total_size);
+ h->encoding = 0;
+ kmip_set_buffer(h->kmip_ctx, response, response_size);
+ need_to_free_response = 1;
+ i = kmip_decode_response_message(h->kmip_ctx, resp_m);
+ if (i != KMIP_OK) {
+ lderr(cct) << "Failed to decode " << what << " " << i << " context error message " << h->kmip_ctx->error_message << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ if (resp_m->batch_count != 1) {
+ lderr(cct) << "Failed; weird response count doing " << what << " " << resp_m->batch_count << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ req = resp_m->batch_items;
+ rs = req->result_status;
+ if (rs != KMIP_STATUS_SUCCESS) {
+ lderr(cct) << "Failed; result status not success " << rs << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ if (req->operation != rbi->operation) {
+ lderr(cct) << "Failed; response operation mismatch, got " << req->operation << " expected " << rbi->operation << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ switch(req->operation)
+ {
+ case KMIP_OP_CREATE: {
+ CreateResponsePayload *pld = (CreateResponsePayload *)req->response_payload;
+ element.out = static_cast<char *>(malloc(pld->unique_identifier->size+1));
+ memcpy(element.out, pld->unique_identifier->value, pld->unique_identifier->size);
+ element.out[pld->unique_identifier->size] = 0;
+ } break;
+ case KMIP_OP_LOCATE: {
+ LocateResponsePayload *pld = (LocateResponsePayload *)req->response_payload;
+ char **list = static_cast<char **>(malloc(sizeof (char*) * (1 + pld->unique_identifiers_count)));
+ for (i = 0; i < pld->unique_identifiers_count; ++i) {
+ list[i] = static_cast<char *>(malloc(pld->unique_identifiers[i].size+1));
+ memcpy(list[i], pld->unique_identifiers[i].value, pld->unique_identifiers[i].size);
+ list[i][pld->unique_identifiers[i].size] = 0;
+ }
+ list[i] = 0;
+ element.outlist->strings = list;
+ element.outlist->string_count = pld->unique_identifiers_count;
+ } break;
+ case KMIP_OP_GET: {
+ GetResponsePayload *pld = (GetResponsePayload *)req->response_payload;
+ element.out = static_cast<char *>(malloc(pld->unique_identifier->size+1));
+ memcpy(element.out, pld->unique_identifier->value, pld->unique_identifier->size);
+ element.out[pld->unique_identifier->size] = 0;
+ if (pld->object_type != KMIP_OBJTYPE_SYMMETRIC_KEY) {
+ lderr(cct) << "get: expected symmetric key got " << pld->object_type << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ KeyBlock *kp = static_cast<SymmetricKey *>(pld->object)->key_block;
+ ByteString *bp;
+ if (kp->key_format_type != KMIP_KEYFORMAT_RAW) {
+ lderr(cct) << "get: expected raw key fromat got " << kp->key_format_type << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ KeyValue *kv = static_cast<KeyValue *>(kp->key_value);
+ bp = static_cast<ByteString*>(kv->key_material);
+ element.outkey->data = static_cast<unsigned char *>(malloc(bp->size));
+ element.outkey->keylen = bp->size;
+ memcpy(element.outkey->data, bp->value, bp->size);
+ } break;
+ case KMIP_OP_GET_ATTRIBUTES: {
+ GetAttributesResponsePayload *pld = (GetAttributesResponsePayload *)req->response_payload;
+ element.out = static_cast<char *>(malloc(pld->unique_identifier->size+1));
+ memcpy(element.out, pld->unique_identifier->value, pld->unique_identifier->size);
+ element.out[pld->unique_identifier->size] = 0;
+ } break;
+ case KMIP_OP_GET_ATTRIBUTE_LIST: {
+ GetAttributeListResponsePayload *pld = (GetAttributeListResponsePayload *)req->response_payload;
+ element.out = static_cast<char *>(malloc(pld->unique_identifier->size+1));
+ memcpy(element.out, pld->unique_identifier->value, pld->unique_identifier->size);
+ element.out[pld->unique_identifier->size] = 0;
+ } break;
+ case KMIP_OP_DESTROY: {
+ DestroyResponsePayload *pld = (DestroyResponsePayload *)req->response_payload;
+ element.out = static_cast<char *>(malloc(pld->unique_identifier->size+1));
+ memcpy(element.out, pld->unique_identifier->value, pld->unique_identifier->size);
+ element.out[pld->unique_identifier->size] = 0;
+ } break;
+ default:
+ lderr(cct) << "Missing response logic op=" << element.operation << dendl;
+ element.ret = -EINVAL;
+ goto Done;
+ }
+ element.ret = 0;
+Done:
+ if (need_to_free_response)
+ kmip_free_response_message(h->kmip_ctx, resp_m);
+ element.done = true;
+ element.cond.notify_all();
+ release_kmip_handle(h);
+ return element.ret;
+}
+
+void *
+RGWKmipWorker::entry()
+{
+ std::unique_lock entry_lock{m.lock};
+ ldout(m.cct, 10) << __func__ << " start" << dendl;
+ RGWKmipHandles handles{m.cct};
+ handles.start();
+ while (!m.going_down) {
+ if (m.requests.empty()) {
+ m.cond.wait_for(entry_lock, std::chrono::seconds(MAXIDLE));
+ continue;
+ }
+ auto iter = m.requests.begin();
+ auto element = *iter;
+ m.requests.erase(iter);
+ entry_lock.unlock();
+ (void) handles.do_one_entry(element.details);
+ entry_lock.lock();
+ }
+ for (;;) {
+ if (m.requests.empty()) break;
+ auto iter = m.requests.begin();
+ auto element = std::move(*iter);
+ m.requests.erase(iter);
+ element.details.ret = -666;
+ element.details.done = true;
+ element.details.cond.notify_all();
+ }
+ handles.stop();
+ ldout(m.cct, 10) << __func__ << " finish" << dendl;
+ return nullptr;
+}