libcouchbase 1.2.8 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/README.md +16 -8
  4. data/ext/libcouchbase/CMakeLists.txt +34 -32
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +277 -6
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +14 -0
  7. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  10. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +8 -1
  11. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  12. data/ext/libcouchbase/cmake/config-cmake.h.in +14 -0
  13. data/ext/libcouchbase/cmake/configure +8 -26
  14. data/ext/libcouchbase/cmake/defs.mk.in +2 -2
  15. data/ext/libcouchbase/cmake/libcouchbase.stp.in +829 -0
  16. data/ext/libcouchbase/cmake/source_files.cmake +11 -2
  17. data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +18 -2
  18. data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +44 -2
  19. data/ext/libcouchbase/contrib/cbsasl/src/client.c +285 -73
  20. data/ext/libcouchbase/contrib/cbsasl/src/common.c +4 -0
  21. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.c +500 -0
  22. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.h +99 -0
  23. data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +1 -1
  24. data/ext/libcouchbase/contrib/cliopts/cliopts.h +14 -1
  25. data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +2 -3
  26. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +4 -0
  27. data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +7 -5
  28. data/ext/libcouchbase/contrib/snappy/snappy.cc +7 -2
  29. data/ext/libcouchbase/example/crypto/.gitignore +2 -0
  30. data/ext/libcouchbase/example/crypto/Makefile +13 -0
  31. data/ext/libcouchbase/example/crypto/common_provider.c +24 -0
  32. data/ext/libcouchbase/example/crypto/common_provider.h +31 -0
  33. data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +139 -0
  34. data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +147 -0
  35. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +281 -0
  36. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.h +29 -0
  37. data/ext/libcouchbase/example/tracing/.gitignore +2 -0
  38. data/ext/libcouchbase/example/tracing/Makefile +8 -0
  39. data/ext/libcouchbase/example/tracing/cJSON.c +1 -0
  40. data/ext/libcouchbase/example/tracing/cJSON.h +1 -0
  41. data/ext/libcouchbase/example/tracing/tracing.c +439 -0
  42. data/ext/libcouchbase/example/tracing/views.c +444 -0
  43. data/ext/libcouchbase/include/libcouchbase/auth.h +56 -4
  44. data/ext/libcouchbase/include/libcouchbase/cbft.h +8 -0
  45. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +55 -1
  46. data/ext/libcouchbase/include/libcouchbase/cntl.h +101 -1
  47. data/ext/libcouchbase/include/libcouchbase/configuration.h.in +6 -0
  48. data/ext/libcouchbase/include/libcouchbase/couchbase.h +109 -6
  49. data/ext/libcouchbase/include/libcouchbase/crypto.h +140 -0
  50. data/ext/libcouchbase/include/libcouchbase/error.h +38 -2
  51. data/ext/libcouchbase/include/libcouchbase/kvbuf.h +6 -1
  52. data/ext/libcouchbase/include/libcouchbase/metrics.h +79 -0
  53. data/ext/libcouchbase/include/libcouchbase/n1ql.h +9 -0
  54. data/ext/libcouchbase/include/libcouchbase/tracing.h +319 -0
  55. data/ext/libcouchbase/include/libcouchbase/vbucket.h +1 -1
  56. data/ext/libcouchbase/include/libcouchbase/views.h +8 -0
  57. data/ext/libcouchbase/include/memcached/protocol_binary.h +40 -10
  58. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +6 -14
  59. data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +3 -0
  60. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +1 -0
  61. data/ext/libcouchbase/plugins/io/select/plugin-select.c +4 -1
  62. data/ext/libcouchbase/src/auth-priv.h +36 -4
  63. data/ext/libcouchbase/src/auth.cc +66 -27
  64. data/ext/libcouchbase/src/bootstrap.cc +1 -1
  65. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +12 -7
  66. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +26 -17
  67. data/ext/libcouchbase/src/bucketconfig/bc_http.h +1 -1
  68. data/ext/libcouchbase/src/bucketconfig/clconfig.h +4 -2
  69. data/ext/libcouchbase/src/bucketconfig/confmon.cc +6 -3
  70. data/ext/libcouchbase/src/cbft.cc +48 -0
  71. data/ext/libcouchbase/src/cntl.cc +138 -2
  72. data/ext/libcouchbase/src/config_static.h +17 -0
  73. data/ext/libcouchbase/src/connspec.cc +54 -6
  74. data/ext/libcouchbase/src/connspec.h +9 -1
  75. data/ext/libcouchbase/src/crypto.cc +386 -0
  76. data/ext/libcouchbase/src/ctx-log-inl.h +23 -6
  77. data/ext/libcouchbase/src/dump.cc +4 -0
  78. data/ext/libcouchbase/src/getconfig.cc +1 -2
  79. data/ext/libcouchbase/src/handler.cc +65 -27
  80. data/ext/libcouchbase/src/hostlist.cc +35 -7
  81. data/ext/libcouchbase/src/hostlist.h +7 -0
  82. data/ext/libcouchbase/src/http/http-priv.h +2 -0
  83. data/ext/libcouchbase/src/http/http.cc +77 -37
  84. data/ext/libcouchbase/src/http/http_io.cc +19 -2
  85. data/ext/libcouchbase/src/instance.cc +90 -17
  86. data/ext/libcouchbase/src/internal.h +5 -0
  87. data/ext/libcouchbase/src/lcbio/connect.cc +39 -4
  88. data/ext/libcouchbase/src/lcbio/connect.h +27 -0
  89. data/ext/libcouchbase/src/lcbio/ctx.c +49 -23
  90. data/ext/libcouchbase/src/lcbio/ioutils.cc +30 -3
  91. data/ext/libcouchbase/src/lcbio/ioutils.h +2 -0
  92. data/ext/libcouchbase/src/lcbio/manager.cc +44 -8
  93. data/ext/libcouchbase/src/lcbio/manager.h +2 -0
  94. data/ext/libcouchbase/src/lcbio/rw-inl.h +1 -0
  95. data/ext/libcouchbase/src/lcbio/ssl.h +3 -5
  96. data/ext/libcouchbase/src/logging.c +1 -1
  97. data/ext/libcouchbase/src/logging.h +2 -0
  98. data/ext/libcouchbase/src/mc/compress.cc +164 -0
  99. data/ext/libcouchbase/src/mc/compress.h +7 -12
  100. data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +5 -1
  101. data/ext/libcouchbase/src/mc/mcreq.c +11 -1
  102. data/ext/libcouchbase/src/mc/mcreq.h +35 -4
  103. data/ext/libcouchbase/src/mcserver/mcserver.cc +30 -7
  104. data/ext/libcouchbase/src/mcserver/mcserver.h +7 -0
  105. data/ext/libcouchbase/src/mcserver/negotiate.cc +103 -57
  106. data/ext/libcouchbase/src/mcserver/negotiate.h +2 -2
  107. data/ext/libcouchbase/src/mctx-helper.h +11 -0
  108. data/ext/libcouchbase/src/metrics.cc +132 -0
  109. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
  110. data/ext/libcouchbase/src/n1ql/n1ql.cc +66 -0
  111. data/ext/libcouchbase/src/newconfig.cc +9 -2
  112. data/ext/libcouchbase/src/operations/counter.cc +2 -1
  113. data/ext/libcouchbase/src/operations/durability-cas.cc +11 -0
  114. data/ext/libcouchbase/src/operations/durability-seqno.cc +3 -0
  115. data/ext/libcouchbase/src/operations/durability.cc +24 -2
  116. data/ext/libcouchbase/src/operations/durability_internal.h +19 -0
  117. data/ext/libcouchbase/src/operations/get.cc +4 -2
  118. data/ext/libcouchbase/src/operations/observe-seqno.cc +1 -0
  119. data/ext/libcouchbase/src/operations/observe.cc +113 -62
  120. data/ext/libcouchbase/src/operations/ping.cc +246 -67
  121. data/ext/libcouchbase/src/operations/remove.cc +2 -1
  122. data/ext/libcouchbase/src/operations/store.cc +17 -14
  123. data/ext/libcouchbase/src/operations/touch.cc +3 -0
  124. data/ext/libcouchbase/src/packetutils.h +68 -4
  125. data/ext/libcouchbase/src/probes.d +132 -161
  126. data/ext/libcouchbase/src/rdb/bigalloc.c +1 -1
  127. data/ext/libcouchbase/src/retryq.cc +6 -2
  128. data/ext/libcouchbase/src/rnd.cc +68 -0
  129. data/ext/libcouchbase/src/rnd.h +39 -0
  130. data/ext/libcouchbase/src/settings.c +27 -0
  131. data/ext/libcouchbase/src/settings.h +67 -3
  132. data/ext/libcouchbase/src/ssl/CMakeLists.txt +0 -12
  133. data/ext/libcouchbase/src/ssl/ssl_common.c +23 -4
  134. data/ext/libcouchbase/src/strcodecs/base64.c +141 -16
  135. data/ext/libcouchbase/src/strcodecs/strcodecs.h +16 -1
  136. data/ext/libcouchbase/src/trace.h +68 -61
  137. data/ext/libcouchbase/src/tracing/span.cc +289 -0
  138. data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +171 -0
  139. data/ext/libcouchbase/src/tracing/tracer.cc +53 -0
  140. data/ext/libcouchbase/src/tracing/tracing-internal.h +213 -0
  141. data/ext/libcouchbase/src/utilities.c +5 -0
  142. data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -2
  143. data/ext/libcouchbase/src/vbucket/vbucket.c +50 -18
  144. data/ext/libcouchbase/src/views/docreq.cc +26 -1
  145. data/ext/libcouchbase/src/views/docreq.h +17 -0
  146. data/ext/libcouchbase/src/views/viewreq.cc +64 -1
  147. data/ext/libcouchbase/src/views/viewreq.h +21 -0
  148. data/ext/libcouchbase/tests/CMakeLists.txt +6 -6
  149. data/ext/libcouchbase/tests/basic/t_base64.cc +34 -6
  150. data/ext/libcouchbase/tests/basic/t_connstr.cc +14 -0
  151. data/ext/libcouchbase/tests/basic/t_creds.cc +10 -10
  152. data/ext/libcouchbase/tests/basic/t_host.cc +22 -2
  153. data/ext/libcouchbase/tests/basic/t_scram.cc +514 -0
  154. data/ext/libcouchbase/tests/check-all.cc +6 -2
  155. data/ext/libcouchbase/tests/iotests/mock-environment.cc +64 -0
  156. data/ext/libcouchbase/tests/iotests/mock-environment.h +27 -1
  157. data/ext/libcouchbase/tests/iotests/t_confmon.cc +2 -2
  158. data/ext/libcouchbase/tests/iotests/t_forward.cc +8 -0
  159. data/ext/libcouchbase/tests/iotests/t_netfail.cc +124 -0
  160. data/ext/libcouchbase/tests/iotests/t_smoke.cc +1 -1
  161. data/ext/libcouchbase/tests/iotests/t_snappy.cc +316 -0
  162. data/ext/libcouchbase/tests/socktests/socktest.cc +2 -2
  163. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  164. data/ext/libcouchbase/tests/socktests/t_manager.cc +1 -1
  165. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  166. data/ext/libcouchbase/tools/CMakeLists.txt +1 -1
  167. data/ext/libcouchbase/tools/cbc-handlers.h +17 -0
  168. data/ext/libcouchbase/tools/cbc-n1qlback.cc +7 -4
  169. data/ext/libcouchbase/tools/cbc-pillowfight.cc +408 -100
  170. data/ext/libcouchbase/tools/cbc-proxy.cc +134 -3
  171. data/ext/libcouchbase/tools/cbc-subdoc.cc +1 -2
  172. data/ext/libcouchbase/tools/cbc.cc +113 -8
  173. data/ext/libcouchbase/tools/common/histogram.cc +1 -0
  174. data/ext/libcouchbase/tools/common/options.cc +28 -1
  175. data/ext/libcouchbase/tools/common/options.h +5 -0
  176. data/ext/libcouchbase/tools/docgen/docgen.h +36 -10
  177. data/ext/libcouchbase/tools/docgen/loc.h +5 -4
  178. data/ext/libcouchbase/tools/docgen/seqgen.h +28 -0
  179. data/lib/libcouchbase/ext/libcouchbase/enums.rb +10 -0
  180. data/lib/libcouchbase/n1ql.rb +6 -1
  181. data/lib/libcouchbase/version.rb +1 -1
  182. data/spec/connection_spec.rb +6 -6
  183. metadata +38 -5
  184. data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +0 -11
  185. data/ext/libcouchbase/src/mc/compress.c +0 -90
  186. 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 == 0 || colonpos == scratch.size()-1) {
103
- SET_ERROR("First or last character in spec is colon!");
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
- hostlen = colonpos;
106
- port = scratch.substr(colonpos + 1);
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(0, hostlen);
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
+ }