libcouchbase 1.2.8 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/README.md +16 -8
- data/ext/libcouchbase/CMakeLists.txt +34 -32
- data/ext/libcouchbase/RELEASE_NOTES.markdown +277 -6
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +14 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +2 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +2 -1
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +8 -1
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +14 -0
- data/ext/libcouchbase/cmake/configure +8 -26
- data/ext/libcouchbase/cmake/defs.mk.in +2 -2
- data/ext/libcouchbase/cmake/libcouchbase.stp.in +829 -0
- data/ext/libcouchbase/cmake/source_files.cmake +11 -2
- data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +18 -2
- data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +44 -2
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +285 -73
- data/ext/libcouchbase/contrib/cbsasl/src/common.c +4 -0
- data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.c +500 -0
- data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.h +99 -0
- data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +1 -1
- data/ext/libcouchbase/contrib/cliopts/cliopts.h +14 -1
- data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +2 -3
- data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +4 -0
- data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +7 -5
- data/ext/libcouchbase/contrib/snappy/snappy.cc +7 -2
- data/ext/libcouchbase/example/crypto/.gitignore +2 -0
- data/ext/libcouchbase/example/crypto/Makefile +13 -0
- data/ext/libcouchbase/example/crypto/common_provider.c +24 -0
- data/ext/libcouchbase/example/crypto/common_provider.h +31 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +139 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +147 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +281 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.h +29 -0
- data/ext/libcouchbase/example/tracing/.gitignore +2 -0
- data/ext/libcouchbase/example/tracing/Makefile +8 -0
- data/ext/libcouchbase/example/tracing/cJSON.c +1 -0
- data/ext/libcouchbase/example/tracing/cJSON.h +1 -0
- data/ext/libcouchbase/example/tracing/tracing.c +439 -0
- data/ext/libcouchbase/example/tracing/views.c +444 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +56 -4
- data/ext/libcouchbase/include/libcouchbase/cbft.h +8 -0
- data/ext/libcouchbase/include/libcouchbase/cntl-private.h +55 -1
- data/ext/libcouchbase/include/libcouchbase/cntl.h +101 -1
- data/ext/libcouchbase/include/libcouchbase/configuration.h.in +6 -0
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +109 -6
- data/ext/libcouchbase/include/libcouchbase/crypto.h +140 -0
- data/ext/libcouchbase/include/libcouchbase/error.h +38 -2
- data/ext/libcouchbase/include/libcouchbase/kvbuf.h +6 -1
- data/ext/libcouchbase/include/libcouchbase/metrics.h +79 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +9 -0
- data/ext/libcouchbase/include/libcouchbase/tracing.h +319 -0
- data/ext/libcouchbase/include/libcouchbase/vbucket.h +1 -1
- data/ext/libcouchbase/include/libcouchbase/views.h +8 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +40 -10
- data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +6 -14
- data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +3 -0
- data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +1 -0
- data/ext/libcouchbase/plugins/io/select/plugin-select.c +4 -1
- data/ext/libcouchbase/src/auth-priv.h +36 -4
- data/ext/libcouchbase/src/auth.cc +66 -27
- data/ext/libcouchbase/src/bootstrap.cc +1 -1
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +12 -7
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +26 -17
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +1 -1
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +4 -2
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +6 -3
- data/ext/libcouchbase/src/cbft.cc +48 -0
- data/ext/libcouchbase/src/cntl.cc +138 -2
- data/ext/libcouchbase/src/config_static.h +17 -0
- data/ext/libcouchbase/src/connspec.cc +54 -6
- data/ext/libcouchbase/src/connspec.h +9 -1
- data/ext/libcouchbase/src/crypto.cc +386 -0
- data/ext/libcouchbase/src/ctx-log-inl.h +23 -6
- data/ext/libcouchbase/src/dump.cc +4 -0
- data/ext/libcouchbase/src/getconfig.cc +1 -2
- data/ext/libcouchbase/src/handler.cc +65 -27
- data/ext/libcouchbase/src/hostlist.cc +35 -7
- data/ext/libcouchbase/src/hostlist.h +7 -0
- data/ext/libcouchbase/src/http/http-priv.h +2 -0
- data/ext/libcouchbase/src/http/http.cc +77 -37
- data/ext/libcouchbase/src/http/http_io.cc +19 -2
- data/ext/libcouchbase/src/instance.cc +90 -17
- data/ext/libcouchbase/src/internal.h +5 -0
- data/ext/libcouchbase/src/lcbio/connect.cc +39 -4
- data/ext/libcouchbase/src/lcbio/connect.h +27 -0
- data/ext/libcouchbase/src/lcbio/ctx.c +49 -23
- data/ext/libcouchbase/src/lcbio/ioutils.cc +30 -3
- data/ext/libcouchbase/src/lcbio/ioutils.h +2 -0
- data/ext/libcouchbase/src/lcbio/manager.cc +44 -8
- data/ext/libcouchbase/src/lcbio/manager.h +2 -0
- data/ext/libcouchbase/src/lcbio/rw-inl.h +1 -0
- data/ext/libcouchbase/src/lcbio/ssl.h +3 -5
- data/ext/libcouchbase/src/logging.c +1 -1
- data/ext/libcouchbase/src/logging.h +2 -0
- data/ext/libcouchbase/src/mc/compress.cc +164 -0
- data/ext/libcouchbase/src/mc/compress.h +7 -12
- data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +5 -1
- data/ext/libcouchbase/src/mc/mcreq.c +11 -1
- data/ext/libcouchbase/src/mc/mcreq.h +35 -4
- data/ext/libcouchbase/src/mcserver/mcserver.cc +30 -7
- data/ext/libcouchbase/src/mcserver/mcserver.h +7 -0
- data/ext/libcouchbase/src/mcserver/negotiate.cc +103 -57
- data/ext/libcouchbase/src/mcserver/negotiate.h +2 -2
- data/ext/libcouchbase/src/mctx-helper.h +11 -0
- data/ext/libcouchbase/src/metrics.cc +132 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
- data/ext/libcouchbase/src/n1ql/n1ql.cc +66 -0
- data/ext/libcouchbase/src/newconfig.cc +9 -2
- data/ext/libcouchbase/src/operations/counter.cc +2 -1
- data/ext/libcouchbase/src/operations/durability-cas.cc +11 -0
- data/ext/libcouchbase/src/operations/durability-seqno.cc +3 -0
- data/ext/libcouchbase/src/operations/durability.cc +24 -2
- data/ext/libcouchbase/src/operations/durability_internal.h +19 -0
- data/ext/libcouchbase/src/operations/get.cc +4 -2
- data/ext/libcouchbase/src/operations/observe-seqno.cc +1 -0
- data/ext/libcouchbase/src/operations/observe.cc +113 -62
- data/ext/libcouchbase/src/operations/ping.cc +246 -67
- data/ext/libcouchbase/src/operations/remove.cc +2 -1
- data/ext/libcouchbase/src/operations/store.cc +17 -14
- data/ext/libcouchbase/src/operations/touch.cc +3 -0
- data/ext/libcouchbase/src/packetutils.h +68 -4
- data/ext/libcouchbase/src/probes.d +132 -161
- data/ext/libcouchbase/src/rdb/bigalloc.c +1 -1
- data/ext/libcouchbase/src/retryq.cc +6 -2
- data/ext/libcouchbase/src/rnd.cc +68 -0
- data/ext/libcouchbase/src/rnd.h +39 -0
- data/ext/libcouchbase/src/settings.c +27 -0
- data/ext/libcouchbase/src/settings.h +67 -3
- data/ext/libcouchbase/src/ssl/CMakeLists.txt +0 -12
- data/ext/libcouchbase/src/ssl/ssl_common.c +23 -4
- data/ext/libcouchbase/src/strcodecs/base64.c +141 -16
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +16 -1
- data/ext/libcouchbase/src/trace.h +68 -61
- data/ext/libcouchbase/src/tracing/span.cc +289 -0
- data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +171 -0
- data/ext/libcouchbase/src/tracing/tracer.cc +53 -0
- data/ext/libcouchbase/src/tracing/tracing-internal.h +213 -0
- data/ext/libcouchbase/src/utilities.c +5 -0
- data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -2
- data/ext/libcouchbase/src/vbucket/vbucket.c +50 -18
- data/ext/libcouchbase/src/views/docreq.cc +26 -1
- data/ext/libcouchbase/src/views/docreq.h +17 -0
- data/ext/libcouchbase/src/views/viewreq.cc +64 -1
- data/ext/libcouchbase/src/views/viewreq.h +21 -0
- data/ext/libcouchbase/tests/CMakeLists.txt +6 -6
- data/ext/libcouchbase/tests/basic/t_base64.cc +34 -6
- data/ext/libcouchbase/tests/basic/t_connstr.cc +14 -0
- data/ext/libcouchbase/tests/basic/t_creds.cc +10 -10
- data/ext/libcouchbase/tests/basic/t_host.cc +22 -2
- data/ext/libcouchbase/tests/basic/t_scram.cc +514 -0
- data/ext/libcouchbase/tests/check-all.cc +6 -2
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +64 -0
- data/ext/libcouchbase/tests/iotests/mock-environment.h +27 -1
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +2 -2
- data/ext/libcouchbase/tests/iotests/t_forward.cc +8 -0
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +124 -0
- data/ext/libcouchbase/tests/iotests/t_smoke.cc +1 -1
- data/ext/libcouchbase/tests/iotests/t_snappy.cc +316 -0
- data/ext/libcouchbase/tests/socktests/socktest.cc +2 -2
- data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
- data/ext/libcouchbase/tests/socktests/t_manager.cc +1 -1
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
- data/ext/libcouchbase/tools/CMakeLists.txt +1 -1
- data/ext/libcouchbase/tools/cbc-handlers.h +17 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +7 -4
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +408 -100
- data/ext/libcouchbase/tools/cbc-proxy.cc +134 -3
- data/ext/libcouchbase/tools/cbc-subdoc.cc +1 -2
- data/ext/libcouchbase/tools/cbc.cc +113 -8
- data/ext/libcouchbase/tools/common/histogram.cc +1 -0
- data/ext/libcouchbase/tools/common/options.cc +28 -1
- data/ext/libcouchbase/tools/common/options.h +5 -0
- data/ext/libcouchbase/tools/docgen/docgen.h +36 -10
- data/ext/libcouchbase/tools/docgen/loc.h +5 -4
- data/ext/libcouchbase/tools/docgen/seqgen.h +28 -0
- data/lib/libcouchbase/ext/libcouchbase/enums.rb +10 -0
- data/lib/libcouchbase/n1ql.rb +6 -1
- data/lib/libcouchbase/version.rb +1 -1
- data/spec/connection_spec.rb +6 -6
- metadata +38 -5
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +0 -11
- data/ext/libcouchbase/src/mc/compress.c +0 -90
- data/ext/libcouchbase/tools/common/my_inttypes.h +0 -22
@@ -66,7 +66,7 @@ Connspec::parse_hosts(const char *hostbegin,
|
|
66
66
|
while (*c) {
|
67
67
|
// get the current host
|
68
68
|
const char *curend;
|
69
|
-
unsigned curlen, hostlen;
|
69
|
+
unsigned curlen, hostlen, hoststart;
|
70
70
|
int rv;
|
71
71
|
|
72
72
|
/* Seek ahead, chopping off any ',' */
|
@@ -95,15 +95,30 @@ Connspec::parse_hosts(const char *hostbegin,
|
|
95
95
|
}
|
96
96
|
|
97
97
|
size_t colonpos = scratch.find(":");
|
98
|
+
size_t rcolonpos = scratch.rfind(":");
|
98
99
|
std::string port;
|
99
100
|
|
101
|
+
hoststart = 0;
|
100
102
|
if (colonpos == std::string::npos) {
|
101
103
|
hostlen = scratch.size();
|
102
|
-
} else if (colonpos ==
|
103
|
-
|
104
|
+
} else if (colonpos == rcolonpos) {
|
105
|
+
if (colonpos == 0 || colonpos == scratch.size() - 1) {
|
106
|
+
SET_ERROR("First or last character in spec is colon!");
|
107
|
+
} else {
|
108
|
+
hostlen = colonpos;
|
109
|
+
port = scratch.substr(colonpos + 1);
|
110
|
+
}
|
104
111
|
} else {
|
105
|
-
|
106
|
-
|
112
|
+
size_t rbracket = scratch.rfind(']');
|
113
|
+
if (scratch[0] == '[' && rbracket != std::string::npos) {
|
114
|
+
hoststart = 1;
|
115
|
+
hostlen = rbracket - hoststart;
|
116
|
+
if (scratch.size() > rbracket + 1) {
|
117
|
+
port = scratch.substr(rbracket + 2);
|
118
|
+
}
|
119
|
+
} else {
|
120
|
+
hostlen = scratch.size();
|
121
|
+
}
|
107
122
|
}
|
108
123
|
|
109
124
|
if (m_flags & F_DNSSRV_EXPLICIT) {
|
@@ -116,7 +131,7 @@ Connspec::parse_hosts(const char *hostbegin,
|
|
116
131
|
|
117
132
|
m_hosts.resize(m_hosts.size() + 1);
|
118
133
|
Spechost *dh = &m_hosts.back();
|
119
|
-
dh->hostname = scratch.substr(
|
134
|
+
dh->hostname = scratch.substr(hoststart, hostlen);
|
120
135
|
|
121
136
|
if (port.empty()) {
|
122
137
|
continue;
|
@@ -235,15 +250,35 @@ Connspec::parse_options(
|
|
235
250
|
} else {
|
236
251
|
SET_ERROR("Invalid value for 'ssl'. Choices are on, off, and no_verify");
|
237
252
|
}
|
253
|
+
} else if (!strcmp(key, "truststorepath")) {
|
254
|
+
if (! (m_flags & F_SSLSCHEME)) {
|
255
|
+
SET_ERROR("Trust store path must be specified with SSL host or scheme");
|
256
|
+
}
|
257
|
+
m_truststorepath = value;
|
238
258
|
} else if (!strcmp(key, "certpath")) {
|
239
259
|
if (! (m_flags & F_SSLSCHEME)) {
|
240
260
|
SET_ERROR("Certificate path must be specified with SSL host or scheme");
|
241
261
|
}
|
242
262
|
m_certpath = value;
|
263
|
+
} else if (!strcmp(key, "keypath")) {
|
264
|
+
if (! (m_flags & F_SSLSCHEME)) {
|
265
|
+
SET_ERROR("Private key path must be specified with SSL host or scheme");
|
266
|
+
}
|
267
|
+
m_keypath = value;
|
243
268
|
} else if (!strcmp(key, "console_log_level")) {
|
244
269
|
if (sscanf(value, "%d", &m_loglevel) != 1) {
|
245
270
|
SET_ERROR("console_log_level must be a numeric value");
|
246
271
|
}
|
272
|
+
} else if (!strcmp(key, "log_redaction")) {
|
273
|
+
int btmp = 0;
|
274
|
+
if (!strcmp(value, "on") || !strcmp(value, "true")) {
|
275
|
+
btmp = 1;
|
276
|
+
} else if (!strcmp(value, "off") || !strcmp(value, "false")) {
|
277
|
+
btmp = 0;
|
278
|
+
} else if (sscanf(value, "%d", &btmp) != 1) {
|
279
|
+
SET_ERROR("log_redaction must have numeric (boolean) value");
|
280
|
+
}
|
281
|
+
m_logredact = btmp != 0;
|
247
282
|
} else if (!strcmp(key, "dnssrv")) {
|
248
283
|
if ((m_flags & F_DNSSRV_EXPLICIT) == F_DNSSRV_EXPLICIT) {
|
249
284
|
SET_ERROR("Cannot use dnssrv scheme with dnssrv option");
|
@@ -261,10 +296,23 @@ Connspec::parse_options(
|
|
261
296
|
} else {
|
262
297
|
m_flags &= ~F_DNSSRV_EXPLICIT;
|
263
298
|
}
|
299
|
+
} else if (!strcmp(key, "ipv6")) {
|
300
|
+
if (!strcmp(value, "only")) {
|
301
|
+
m_ipv6 = LCB_IPV6_ONLY;
|
302
|
+
} else if (!strcmp(value, "disabled")) {
|
303
|
+
m_ipv6 = LCB_IPV6_DISABLED;
|
304
|
+
} else if (!strcmp(value, "allow")) {
|
305
|
+
m_ipv6 = LCB_IPV6_ALLOW;
|
306
|
+
} else {
|
307
|
+
SET_ERROR("Value for ipv6 must be 'disabled', 'allow', or 'only'");
|
308
|
+
}
|
264
309
|
} else {
|
265
310
|
m_ctlopts.push_back(std::make_pair(key, value));
|
266
311
|
}
|
267
312
|
}
|
313
|
+
if (!m_keypath.empty() && m_certpath.empty()) {
|
314
|
+
SET_ERROR("Private key path must be specified with certificate path");
|
315
|
+
}
|
268
316
|
|
269
317
|
return LCB_SUCCESS;
|
270
318
|
}
|
@@ -61,7 +61,7 @@ struct Spechost {
|
|
61
61
|
class LCB_CLASS_EXPORT Connspec {
|
62
62
|
public:
|
63
63
|
typedef std::vector<std::pair<std::string,std::string> > Options;
|
64
|
-
Connspec() : m_sslopts(0), m_implicit_port(0), m_loglevel(0), m_flags(0) {}
|
64
|
+
Connspec() : m_sslopts(0), m_implicit_port(0), m_loglevel(0), m_logredact(false), m_flags(0), m_ipv6(LCB_IPV6_DISABLED) {}
|
65
65
|
|
66
66
|
lcb_error_t parse(const char *connstr, const char **errmsg = NULL);
|
67
67
|
lcb_error_t load(const lcb_create_st&);
|
@@ -92,24 +92,31 @@ public:
|
|
92
92
|
const std::string& bucket() const { return m_bucket; }
|
93
93
|
const std::string& username() const { return m_username; }
|
94
94
|
const std::string& password() const { return m_password; }
|
95
|
+
const std::string& truststorepath() const { return m_truststorepath; }
|
95
96
|
const std::string& certpath() const { return m_certpath; }
|
97
|
+
const std::string& keypath() const { return m_keypath; }
|
96
98
|
unsigned sslopts() const { return m_sslopts; }
|
97
99
|
const Options& options() const { return m_ctlopts; }
|
98
100
|
unsigned loglevel() const { return m_loglevel; }
|
101
|
+
bool logredact() const { return m_logredact; }
|
99
102
|
const std::string& connstr() const { return m_connstr; }
|
100
103
|
void clear_hosts() { m_hosts.clear(); }
|
101
104
|
void add_host(const Spechost& host) { m_hosts.push_back(host); }
|
105
|
+
lcb_ipv6_t ipv6_policy() const { return m_ipv6; }
|
102
106
|
private:
|
103
107
|
Options m_ctlopts;
|
104
108
|
std::string m_bucket;
|
105
109
|
std::string m_username;
|
106
110
|
std::string m_password;
|
111
|
+
std::string m_truststorepath;
|
107
112
|
std::string m_certpath;
|
113
|
+
std::string m_keypath;
|
108
114
|
std::string m_connstr;
|
109
115
|
unsigned m_sslopts; /**< SSL Options */
|
110
116
|
std::vector<Spechost> m_hosts;
|
111
117
|
lcb_U16 m_implicit_port; /**< Implicit port, based on scheme */
|
112
118
|
int m_loglevel; /* cached loglevel */
|
119
|
+
bool m_logredact;
|
113
120
|
|
114
121
|
inline lcb_error_t parse_options(
|
115
122
|
const char *options, const char *optend, const char **errmsg);
|
@@ -118,6 +125,7 @@ private:
|
|
118
125
|
|
119
126
|
std::set<int> m_transports;
|
120
127
|
unsigned m_flags; /**< Internal flags */
|
128
|
+
lcb_ipv6_t m_ipv6;
|
121
129
|
};
|
122
130
|
|
123
131
|
#define LCB_SPECSCHEME_RAW "couchbase+explicit://"
|
@@ -0,0 +1,386 @@
|
|
1
|
+
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2017-2018 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "internal.h"
|
19
|
+
|
20
|
+
void lcbcrypto_ref(lcbcrypto_PROVIDER *provider)
|
21
|
+
{
|
22
|
+
provider->_refcnt++;
|
23
|
+
}
|
24
|
+
|
25
|
+
void lcbcrypto_unref(lcbcrypto_PROVIDER *provider)
|
26
|
+
{
|
27
|
+
provider->_refcnt--;
|
28
|
+
if (provider->_refcnt == 0 && provider->destructor) {
|
29
|
+
provider->destructor(provider);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
void lcbcrypto_register(lcb_t instance, const char *name, lcbcrypto_PROVIDER *provider)
|
34
|
+
{
|
35
|
+
std::map< std::string, lcbcrypto_PROVIDER * >::iterator old = instance->crypto->find(name);
|
36
|
+
if (old != instance->crypto->end()) {
|
37
|
+
lcbcrypto_unref(old->second);
|
38
|
+
}
|
39
|
+
lcbcrypto_ref(provider);
|
40
|
+
(*instance->crypto)[name] = provider;
|
41
|
+
}
|
42
|
+
|
43
|
+
void lcbcrypto_unregister(lcb_t instance, const char *name)
|
44
|
+
{
|
45
|
+
std::map< std::string, lcbcrypto_PROVIDER * >::iterator old = instance->crypto->find(name);
|
46
|
+
if (old != instance->crypto->end()) {
|
47
|
+
lcbcrypto_unref(old->second);
|
48
|
+
instance->crypto->erase(old);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
static bool lcbcrypto_is_valid(lcbcrypto_PROVIDER *provider)
|
53
|
+
{
|
54
|
+
if (!(provider && provider->_refcnt > 0)) {
|
55
|
+
return false;
|
56
|
+
}
|
57
|
+
if (provider->version != 0) {
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
if (provider->v.v0.sign && provider->v.v0.verify_signature == NULL) {
|
61
|
+
return false;
|
62
|
+
}
|
63
|
+
return provider->v.v0.load_key && provider->v.v0.encrypt && provider->v.v0.decrypt;
|
64
|
+
}
|
65
|
+
|
66
|
+
#define PROVIDER_LOAD_KEY(provider, type, keyid, key, nkey) \
|
67
|
+
(provider)->v.v0.load_key((provider), (type), (keyid), (key), (nkey))
|
68
|
+
|
69
|
+
#define PROVIDER_NEED_SIGN(provider) (provider)->v.v0.sign != NULL
|
70
|
+
#define PROVIDER_SIGN(provider, parts, nparts, sig, nsig) \
|
71
|
+
(provider)->v.v0.sign((provider), (parts), (nparts), (sig), (nsig));
|
72
|
+
#define PROVIDER_VERIFY_SIGNATURE(provider, parts, nparts, sig, nsig) \
|
73
|
+
(provider)->v.v0.verify_signature((provider), (parts), (nparts), (sig), (nsig));
|
74
|
+
|
75
|
+
#define PROVIDER_NEED_IV(provider) (provider)->v.v0.generate_iv != NULL
|
76
|
+
#define PROVIDER_GENERATE_IV(provider, iv, niv) (provider)->v.v0.generate_iv((provider), (iv), (niv))
|
77
|
+
|
78
|
+
#define PROVIDER_ENCRYPT(provider, ptext, nptext, key, nkey, iv, niv, ctext, nctext) \
|
79
|
+
(provider)->v.v0.encrypt((provider), (ptext), (nptext), (key), (nkey), (iv), (niv), (ctext), (nctext));
|
80
|
+
#define PROVIDER_DECRYPT(provider, ctext, nctext, key, nkey, iv, niv, ptext, nptext) \
|
81
|
+
(provider)->v.v0.decrypt((provider), (ctext), (nctext), (key), (nkey), (iv), (niv), (ptext), (nptext));
|
82
|
+
|
83
|
+
#define PROVIDER_RELEASE_BYTES(provider, bytes) \
|
84
|
+
if ((bytes) && (provider)->v.v0.release_bytes) { \
|
85
|
+
(provider)->v.v0.release_bytes((provider), (bytes)); \
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
static lcbcrypto_PROVIDER *lcb_get_provider(const lcb_st *instance, const std::string &alg)
|
90
|
+
{
|
91
|
+
const lcb_st::lcb_ProviderMap::iterator provider_iterator = (*instance->crypto).find(alg);
|
92
|
+
return provider_iterator != (*instance->crypto).end() ? provider_iterator->second : NULL;
|
93
|
+
}
|
94
|
+
|
95
|
+
lcb_error_t lcbcrypto_encrypt_fields(lcb_t instance, lcbcrypto_CMDENCRYPT *cmd)
|
96
|
+
{
|
97
|
+
cmd->out = NULL;
|
98
|
+
cmd->nout = 0;
|
99
|
+
|
100
|
+
Json::Value jdoc;
|
101
|
+
if (!Json::Reader().parse(cmd->doc, cmd->doc + cmd->ndoc, jdoc)) {
|
102
|
+
return LCB_EINVAL;
|
103
|
+
}
|
104
|
+
bool changed = false;
|
105
|
+
std::string prefix = (cmd->prefix == NULL) ? "__crypt_" : cmd->prefix;
|
106
|
+
for (size_t ii = 0; ii < cmd->nfields; ii++) {
|
107
|
+
lcbcrypto_FIELDSPEC *field = cmd->fields + ii;
|
108
|
+
lcb_error_t rc;
|
109
|
+
uint8_t *key = NULL;
|
110
|
+
size_t nkey = 0;
|
111
|
+
|
112
|
+
lcbcrypto_PROVIDER *provider = lcb_get_provider(instance, field->alg);
|
113
|
+
if (!lcbcrypto_is_valid(provider)) {
|
114
|
+
continue;
|
115
|
+
}
|
116
|
+
|
117
|
+
rc = PROVIDER_LOAD_KEY(provider, LCBCRYPTO_KEY_ENCRYPT, field->kid, &key, &nkey);
|
118
|
+
if (rc != LCB_SUCCESS) {
|
119
|
+
PROVIDER_RELEASE_BYTES(provider, key);
|
120
|
+
continue;
|
121
|
+
}
|
122
|
+
|
123
|
+
if (jdoc.isMember(field->name)) {
|
124
|
+
std::string contents = Json::FastWriter().write(jdoc[field->name]);
|
125
|
+
Json::Value encrypted;
|
126
|
+
int ret;
|
127
|
+
|
128
|
+
uint8_t *iv = NULL;
|
129
|
+
char *biv = NULL;
|
130
|
+
size_t niv = 0;
|
131
|
+
lcb_SIZE nbiv = 0;
|
132
|
+
if (PROVIDER_NEED_IV(provider)) {
|
133
|
+
rc = PROVIDER_GENERATE_IV(provider, &iv, &niv);
|
134
|
+
if (rc != 0) {
|
135
|
+
PROVIDER_RELEASE_BYTES(provider, iv);
|
136
|
+
continue;
|
137
|
+
}
|
138
|
+
ret = lcb_base64_encode2(reinterpret_cast< char * >(iv), niv, &biv, &nbiv);
|
139
|
+
if (ret < 0) {
|
140
|
+
free(biv);
|
141
|
+
PROVIDER_RELEASE_BYTES(provider, iv);
|
142
|
+
continue;
|
143
|
+
}
|
144
|
+
encrypted["iv"] = biv;
|
145
|
+
}
|
146
|
+
const uint8_t *ptext = reinterpret_cast< const uint8_t * >(contents.c_str());
|
147
|
+
uint8_t *ctext = NULL;
|
148
|
+
size_t nptext = contents.size(), nctext = 0;
|
149
|
+
rc = PROVIDER_ENCRYPT(provider, ptext, nptext, key, nkey, iv, niv, &ctext, &nctext);
|
150
|
+
PROVIDER_RELEASE_BYTES(provider, iv);
|
151
|
+
if (rc != LCB_SUCCESS) {
|
152
|
+
PROVIDER_RELEASE_BYTES(provider, ctext);
|
153
|
+
continue;
|
154
|
+
}
|
155
|
+
char *btext = NULL;
|
156
|
+
lcb_SIZE nbtext = 0;
|
157
|
+
ret = lcb_base64_encode2(reinterpret_cast< char * >(ctext), nctext, &btext, &nbtext);
|
158
|
+
PROVIDER_RELEASE_BYTES(provider, ctext);
|
159
|
+
if (ret < 0) {
|
160
|
+
free(btext);
|
161
|
+
continue;
|
162
|
+
}
|
163
|
+
encrypted["ciphertext"] = btext;
|
164
|
+
|
165
|
+
if (PROVIDER_NEED_SIGN(provider)) {
|
166
|
+
lcbcrypto_SIGV parts[4] = {};
|
167
|
+
size_t nparts = 0;
|
168
|
+
uint8_t *sig = NULL;
|
169
|
+
size_t nsig = 0;
|
170
|
+
|
171
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(field->kid);
|
172
|
+
parts[nparts].len = strlen(field->kid);
|
173
|
+
nparts++;
|
174
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(field->alg);
|
175
|
+
parts[nparts].len = strlen(field->alg);
|
176
|
+
nparts++;
|
177
|
+
if (biv) {
|
178
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(biv);
|
179
|
+
parts[nparts].len = nbiv;
|
180
|
+
nparts++;
|
181
|
+
}
|
182
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(btext);
|
183
|
+
parts[nparts].len = nbtext;
|
184
|
+
nparts++;
|
185
|
+
|
186
|
+
rc = PROVIDER_SIGN(provider, parts, nparts, &sig, &nsig);
|
187
|
+
if (rc != LCB_SUCCESS) {
|
188
|
+
PROVIDER_RELEASE_BYTES(provider, sig);
|
189
|
+
continue;
|
190
|
+
}
|
191
|
+
char *bsig = NULL;
|
192
|
+
lcb_SIZE nbsig = 0;
|
193
|
+
ret = lcb_base64_encode2(reinterpret_cast< char * >(sig), nsig, &bsig, &nbsig);
|
194
|
+
PROVIDER_RELEASE_BYTES(provider, sig);
|
195
|
+
if (ret < 0) {
|
196
|
+
free(bsig);
|
197
|
+
continue;
|
198
|
+
}
|
199
|
+
encrypted["sig"] = bsig;
|
200
|
+
free(bsig);
|
201
|
+
}
|
202
|
+
free(biv);
|
203
|
+
free(btext);
|
204
|
+
encrypted["kid"] = field->kid;
|
205
|
+
encrypted["alg"] = field->alg;
|
206
|
+
jdoc[prefix + field->name] = encrypted;
|
207
|
+
jdoc.removeMember(field->name);
|
208
|
+
changed = true;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
if (changed) {
|
212
|
+
std::string doc = Json::FastWriter().write(jdoc);
|
213
|
+
cmd->out = strdup(doc.c_str());
|
214
|
+
cmd->nout = strlen(cmd->out);
|
215
|
+
}
|
216
|
+
return LCB_SUCCESS;
|
217
|
+
}
|
218
|
+
|
219
|
+
lcb_error_t lcbcrypto_decrypt_fields(lcb_t instance, lcbcrypto_CMDDECRYPT *cmd)
|
220
|
+
{
|
221
|
+
cmd->out = NULL;
|
222
|
+
cmd->nout = 0;
|
223
|
+
|
224
|
+
Json::Value jdoc;
|
225
|
+
if (!Json::Reader().parse(cmd->doc, cmd->doc + cmd->ndoc, jdoc)) {
|
226
|
+
return LCB_EINVAL;
|
227
|
+
}
|
228
|
+
|
229
|
+
if (!jdoc.isObject()) {
|
230
|
+
return LCB_EINVAL;
|
231
|
+
}
|
232
|
+
|
233
|
+
bool changed = false;
|
234
|
+
std::string prefix = (cmd->prefix == NULL) ? "__crypt_" : cmd->prefix;
|
235
|
+
|
236
|
+
const Json::Value::Members names = jdoc.getMemberNames();
|
237
|
+
for (Json::Value::Members::const_iterator ii = names.begin(); ii != names.end(); ii++) {
|
238
|
+
const std::string &name = *ii;
|
239
|
+
if (name.size() <= prefix.size()) {
|
240
|
+
continue;
|
241
|
+
}
|
242
|
+
if (prefix.compare(0, prefix.size(), name, 0, prefix.size()) != 0) {
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
Json::Value &encrypted = jdoc[name];
|
246
|
+
if (!encrypted.isObject()) {
|
247
|
+
continue;
|
248
|
+
}
|
249
|
+
|
250
|
+
Json::Value &jalg = encrypted["alg"];
|
251
|
+
if (!jalg.isString()) {
|
252
|
+
continue;
|
253
|
+
}
|
254
|
+
const std::string &alg = jalg.asString();
|
255
|
+
|
256
|
+
Json::Value &jkid = encrypted["kid"];
|
257
|
+
if (!jkid.isString()) {
|
258
|
+
continue;
|
259
|
+
}
|
260
|
+
const std::string &kid = jkid.asString();
|
261
|
+
|
262
|
+
Json::Value &jiv = encrypted["iv"];
|
263
|
+
const char *biv = NULL;
|
264
|
+
size_t nbiv = 0;
|
265
|
+
if (jiv.isString()) {
|
266
|
+
biv = jiv.asCString();
|
267
|
+
nbiv = strlen(biv);
|
268
|
+
}
|
269
|
+
|
270
|
+
int ret;
|
271
|
+
lcb_error_t rc;
|
272
|
+
|
273
|
+
lcbcrypto_PROVIDER *provider = lcb_get_provider(instance, alg);
|
274
|
+
if (!lcbcrypto_is_valid(provider)) {
|
275
|
+
continue;
|
276
|
+
}
|
277
|
+
Json::Value &jctext = encrypted["ciphertext"];
|
278
|
+
if (!jctext.isString()) {
|
279
|
+
continue;
|
280
|
+
}
|
281
|
+
const std::string &btext = jctext.asString();
|
282
|
+
|
283
|
+
if (PROVIDER_NEED_SIGN(provider)) {
|
284
|
+
Json::Value &jsig = encrypted["sig"];
|
285
|
+
if (!jsig.isString()) {
|
286
|
+
/* TODO: warn about missing signature? */
|
287
|
+
continue;
|
288
|
+
}
|
289
|
+
uint8_t *sig = NULL;
|
290
|
+
lcb_SIZE nsig = 0;
|
291
|
+
const std::string &bsig = jsig.asString();
|
292
|
+
ret = lcb_base64_decode2(bsig.c_str(), bsig.size(), reinterpret_cast< char ** >(&sig), &nsig);
|
293
|
+
if (ret < 0) {
|
294
|
+
PROVIDER_RELEASE_BYTES(provider, sig);
|
295
|
+
continue;
|
296
|
+
}
|
297
|
+
|
298
|
+
lcbcrypto_SIGV parts[4] = {};
|
299
|
+
size_t nparts = 0;
|
300
|
+
|
301
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(kid.c_str());
|
302
|
+
parts[nparts].len = kid.size();
|
303
|
+
nparts++;
|
304
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(alg.c_str());
|
305
|
+
parts[nparts].len = alg.size();
|
306
|
+
nparts++;
|
307
|
+
if (biv) {
|
308
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(biv);
|
309
|
+
parts[nparts].len = nbiv;
|
310
|
+
nparts++;
|
311
|
+
}
|
312
|
+
parts[nparts].data = reinterpret_cast< const uint8_t * >(btext.c_str());
|
313
|
+
parts[nparts].len = btext.size();
|
314
|
+
nparts++;
|
315
|
+
|
316
|
+
rc = PROVIDER_VERIFY_SIGNATURE(provider, parts, nparts, sig, nsig);
|
317
|
+
free(sig);
|
318
|
+
if (rc != LCB_SUCCESS) {
|
319
|
+
continue;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
|
323
|
+
uint8_t *ctext = NULL;
|
324
|
+
lcb_SIZE nctext = 0;
|
325
|
+
ret = lcb_base64_decode2(btext.c_str(), btext.size(), reinterpret_cast< char ** >(&ctext), &nctext);
|
326
|
+
if (ret < 0) {
|
327
|
+
continue;
|
328
|
+
}
|
329
|
+
|
330
|
+
uint8_t *key = NULL;
|
331
|
+
size_t nkey = 0;
|
332
|
+
rc = PROVIDER_LOAD_KEY(provider, LCBCRYPTO_KEY_DECRYPT, kid.c_str(), &key, &nkey);
|
333
|
+
if (rc != LCB_SUCCESS) {
|
334
|
+
free(ctext);
|
335
|
+
PROVIDER_RELEASE_BYTES(provider, key);
|
336
|
+
continue;
|
337
|
+
}
|
338
|
+
|
339
|
+
uint8_t *iv = NULL;
|
340
|
+
lcb_SIZE niv = 0;
|
341
|
+
if (biv) {
|
342
|
+
ret = lcb_base64_decode2(biv, nbiv, reinterpret_cast< char ** >(&iv), &niv);
|
343
|
+
if (ret < 0) {
|
344
|
+
free(ctext);
|
345
|
+
PROVIDER_RELEASE_BYTES(provider, key);
|
346
|
+
continue;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
uint8_t *ptext = NULL;
|
351
|
+
size_t nptext = 0;
|
352
|
+
rc = PROVIDER_DECRYPT(provider, ctext, nctext, key, nkey, iv, niv, &ptext, &nptext);
|
353
|
+
PROVIDER_RELEASE_BYTES(provider, key);
|
354
|
+
free(ctext);
|
355
|
+
if (rc != LCB_SUCCESS) {
|
356
|
+
PROVIDER_RELEASE_BYTES(provider, ptext);
|
357
|
+
continue;
|
358
|
+
}
|
359
|
+
Json::Value frag;
|
360
|
+
char *json = reinterpret_cast< char * >(ptext);
|
361
|
+
bool valid_json = Json::Reader().parse(json, json + nptext, frag);
|
362
|
+
PROVIDER_RELEASE_BYTES(provider, ptext);
|
363
|
+
if (!valid_json) {
|
364
|
+
continue;
|
365
|
+
}
|
366
|
+
jdoc[name.substr(prefix.size())] = frag;
|
367
|
+
jdoc.removeMember(name);
|
368
|
+
changed = true;
|
369
|
+
}
|
370
|
+
if (changed) {
|
371
|
+
std::string doc = Json::FastWriter().write(jdoc);
|
372
|
+
cmd->out = strdup(doc.c_str());
|
373
|
+
cmd->nout = strlen(cmd->out);
|
374
|
+
}
|
375
|
+
return LCB_SUCCESS;
|
376
|
+
}
|
377
|
+
|
378
|
+
lcb_error_t lcbcrypto_encrypt_document(lcb_t, lcbcrypto_CMDENCRYPT *)
|
379
|
+
{
|
380
|
+
return LCB_NOT_SUPPORTED;
|
381
|
+
}
|
382
|
+
|
383
|
+
lcb_error_t lcbcrypto_decrypt_document(lcb_t, lcbcrypto_CMDDECRYPT *)
|
384
|
+
{
|
385
|
+
return LCB_NOT_SUPPORTED;
|
386
|
+
}
|