couchbase 3.2.4 → 3.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/binding.gyp +5 -0
  2. package/deps/lcb/CMakeLists.txt +28 -6
  3. package/deps/lcb/README.markdown +5 -9
  4. package/deps/lcb/RELEASE_NOTES.markdown +80 -5
  5. package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
  6. package/deps/lcb/doc/Doxyfile +1 -1
  7. package/deps/lcb/doc/cbc.markdown +10 -0
  8. package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
  9. package/deps/lcb/include/libcouchbase/couchbase.h +52 -0
  10. package/deps/lcb/include/libcouchbase/error.h +5 -2
  11. package/deps/lcb/libcouchbase.gyp +7 -1
  12. package/deps/lcb/packaging/rpm/libcouchbase.spec.in +1 -1
  13. package/deps/lcb/plugins/io/iocp/iocp_iops.h +1 -1
  14. package/deps/lcb/plugins/io/iocp/iocp_loop.c +3 -3
  15. package/deps/lcb/plugins/io/iocp/iocp_util.c +2 -2
  16. package/deps/lcb/src/bucketconfig/bc_file.cc +29 -15
  17. package/deps/lcb/src/capi/cmd_counter.hh +12 -0
  18. package/deps/lcb/src/capi/cmd_exists.hh +12 -0
  19. package/deps/lcb/src/capi/cmd_get.hh +12 -0
  20. package/deps/lcb/src/capi/cmd_get_replica.hh +14 -1
  21. package/deps/lcb/src/capi/cmd_query.cc +13 -0
  22. package/deps/lcb/src/capi/cmd_query.hh +22 -14
  23. package/deps/lcb/src/capi/cmd_remove.hh +12 -0
  24. package/deps/lcb/src/capi/cmd_store.hh +12 -0
  25. package/deps/lcb/src/capi/cmd_subdoc.hh +12 -0
  26. package/deps/lcb/src/capi/cmd_touch.hh +12 -0
  27. package/deps/lcb/src/capi/cmd_unlock.hh +12 -0
  28. package/deps/lcb/src/capi/collection_qualifier.hh +4 -9
  29. package/deps/lcb/src/instance.cc +19 -0
  30. package/deps/lcb/src/internal.h +2 -1
  31. package/deps/lcb/src/mcserver/negotiate.cc +3 -0
  32. package/deps/lcb/src/n1ql/n1ql.cc +5 -1
  33. package/deps/lcb/src/n1ql/query_handle.cc +55 -30
  34. package/deps/lcb/src/n1ql/query_handle.hh +14 -2
  35. package/deps/lcb/src/operations/counter.cc +12 -0
  36. package/deps/lcb/src/operations/exists.cc +12 -0
  37. package/deps/lcb/src/operations/get.cc +12 -0
  38. package/deps/lcb/src/operations/get_replica.cc +18 -6
  39. package/deps/lcb/src/operations/ping.cc +2 -2
  40. package/deps/lcb/src/operations/remove.cc +12 -0
  41. package/deps/lcb/src/operations/store.cc +12 -0
  42. package/deps/lcb/src/operations/subdoc.cc +12 -0
  43. package/deps/lcb/src/operations/touch.cc +12 -0
  44. package/deps/lcb/src/operations/unlock.cc +12 -0
  45. package/deps/lcb/src/search/search_handle.cc +1 -2
  46. package/deps/lcb/src/settings.cc +1 -0
  47. package/deps/lcb/src/ssl/ssl_common.c +111 -22
  48. package/deps/lcb/src/utilities.cc +21 -0
  49. package/deps/lcb/src/utilities.h +3 -0
  50. package/deps/lcb/src/vbucket/vbucket.c +16 -7
  51. package/deps/lcb/tests/CMakeLists.txt +1 -1
  52. package/deps/lcb/tests/iotests/mock-environment.cc +13 -1
  53. package/deps/lcb/tests/iotests/mock-environment.h +3 -1
  54. package/deps/lcb/tests/iotests/serverparams.h +7 -2
  55. package/deps/lcb/tests/iotests/t_ratelimit.cc +739 -0
  56. package/deps/lcb/tests/iotests/testutil.cc +174 -0
  57. package/deps/lcb/tests/iotests/testutil.h +53 -0
  58. package/deps/lcb/tools/CMakeLists.txt +1 -1
  59. package/deps/lcb/tools/cbc-handlers.h +39 -0
  60. package/deps/lcb/tools/cbc-n1qlback.cc +1 -0
  61. package/deps/lcb/tools/cbc-pillowfight.cc +45 -35
  62. package/deps/lcb/tools/cbc.cc +31 -0
  63. package/deps/lcb/tools/docgen/docgen.h +11 -10
  64. package/dist/analyticsexecutor.js +2 -2
  65. package/dist/analyticsindexmanager.js +3 -3
  66. package/dist/binarycollection.d.ts +17 -0
  67. package/dist/binding.js +1 -1
  68. package/dist/bindingutilities.js +5 -1
  69. package/dist/bucketmanager.d.ts +1 -22
  70. package/dist/bucketmanager.js +5 -5
  71. package/dist/cluster.js +1 -1
  72. package/dist/collection.js +6 -6
  73. package/dist/collectionmanager.js +2 -2
  74. package/dist/connection.js +3 -3
  75. package/dist/connspec.js +5 -1
  76. package/dist/couchbase.js +5 -1
  77. package/dist/httpexecutor.d.ts +1 -0
  78. package/dist/httpexecutor.js +5 -1
  79. package/dist/logging.js +1 -1
  80. package/dist/queryexecutor.js +3 -3
  81. package/dist/searchindexmanager.js +1 -1
  82. package/dist/usermanager.js +2 -2
  83. package/dist/utilities.d.ts +1 -2
  84. package/dist/utilities.js +9 -2
  85. package/dist/viewexecutor.js +1 -1
  86. package/package.json +1 -1
  87. package/src/uv-plugin-all.cpp +1 -0
  88. package/dist/cas.d.ts +0 -0
  89. package/dist/cas.js +0 -1
@@ -129,6 +129,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_on_behalf_of(lcb_CMDGET *cmd, const char
129
129
  return cmd->on_behalf_of(std::string(data, data_len));
130
130
  }
131
131
 
132
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_on_behalf_of_extra_privilege(lcb_CMDGET *cmd, const char *privilege,
133
+ size_t privilege_len)
134
+ {
135
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
136
+ }
137
+
132
138
  static lcb_STATUS get_validate(lcb_INSTANCE *instance, const lcb_CMDGET *cmd)
133
139
  {
134
140
  if (cmd->key().empty()) {
@@ -159,6 +165,12 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
159
165
  if (err != LCB_SUCCESS) {
160
166
  return err;
161
167
  }
168
+ for (const auto &privilege : cmd->extra_privileges()) {
169
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
170
+ if (err != LCB_SUCCESS) {
171
+ return err;
172
+ }
173
+ }
162
174
  }
163
175
 
164
176
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -144,6 +144,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_on_behalf_of(lcb_CMDGETREPLICA *cm
144
144
  return cmd->on_behalf_of(std::string(data, data_len));
145
145
  }
146
146
 
147
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_on_behalf_of_extra_privilege(lcb_CMDGETREPLICA *cmd,
148
+ const char *privilege, size_t privilege_len)
149
+ {
150
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
151
+ }
152
+
147
153
  struct RGetCookie : mc_REQDATAEX {
148
154
  RGetCookie(void *cookie, lcb_INSTANCE *instance, get_replica_mode, int vb);
149
155
  void decref()
@@ -349,20 +355,26 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
349
355
  return LCB_ERR_NO_MATCHING_SERVER;
350
356
  }
351
357
 
352
- /* Initialize the cookie */
353
- auto *rck = new RGetCookie(cmd->cookie(), instance, cmd->mode(), vbid);
354
- rck->start = cmd->start_time_or_default_in_nanoseconds(gethrtime());
355
- rck->deadline =
356
- rck->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
357
-
358
358
  std::vector<std::uint8_t> framing_extras;
359
359
  if (cmd->want_impersonation()) {
360
360
  lcb_STATUS err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
361
361
  if (err != LCB_SUCCESS) {
362
362
  return err;
363
363
  }
364
+ for (const auto &privilege : cmd->extra_privileges()) {
365
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
366
+ if (err != LCB_SUCCESS) {
367
+ return err;
368
+ }
369
+ }
364
370
  }
365
371
 
372
+ /* Initialize the cookie */
373
+ auto *rck = new RGetCookie(cmd->cookie(), instance, cmd->mode(), vbid);
374
+ rck->start = cmd->start_time_or_default_in_nanoseconds(gethrtime());
375
+ rck->deadline =
376
+ rck->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
377
+
366
378
  /* Initialize the packet */
367
379
  req.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
368
380
  req.request.opcode = PROTOCOL_BINARY_CMD_GET_REPLICA;
@@ -69,7 +69,7 @@ LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_id(const lcb_RESPPING *resp, siz
69
69
  return LCB_ERR_OPTIONS_CONFLICT;
70
70
  }
71
71
  *endpoint_id = resp->services[index].id;
72
- *endpoint_id_len = strlen(*endpoint_id);
72
+ *endpoint_id_len = *endpoint_id == nullptr ? 0 : strlen(*endpoint_id);
73
73
  return LCB_SUCCESS;
74
74
  }
75
75
 
@@ -100,7 +100,7 @@ LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_local(const lcb_RESPPING *resp,
100
100
  return LCB_ERR_OPTIONS_CONFLICT;
101
101
  }
102
102
  *address = resp->services[index].local;
103
- *address_len = strlen(*address);
103
+ *address_len = *address == nullptr ? 0 : strlen(*address);
104
104
  return LCB_SUCCESS;
105
105
  }
106
106
 
@@ -117,6 +117,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_on_behalf_of(lcb_CMDREMOVE *cmd, const
117
117
  return cmd->on_behalf_of(std::string(data, data_len));
118
118
  }
119
119
 
120
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_on_behalf_of_extra_privilege(lcb_CMDREMOVE *cmd, const char *privilege,
121
+ size_t privilege_len)
122
+ {
123
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
124
+ }
125
+
120
126
  static lcb_STATUS remove_validate(lcb_INSTANCE *instance, const lcb_CMDREMOVE *cmd)
121
127
  {
122
128
  if (cmd->key().empty()) {
@@ -159,6 +165,12 @@ static lcb_STATUS remove_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
159
165
  if (err != LCB_SUCCESS) {
160
166
  return err;
161
167
  }
168
+ for (const auto &privilege : cmd->extra_privileges()) {
169
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
170
+ if (err != LCB_SUCCESS) {
171
+ return err;
172
+ }
173
+ }
162
174
  }
163
175
 
164
176
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -234,6 +234,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_on_behalf_of(lcb_CMDSTORE *cmd, const c
234
234
  return cmd->on_behalf_of(std::string(data, data_len));
235
235
  }
236
236
 
237
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_on_behalf_of_extra_privilege(lcb_CMDSTORE *cmd, const char *privilege,
238
+ size_t privilege_len)
239
+ {
240
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
241
+ }
242
+
237
243
  struct DurStoreCtx : mc_REQDATAEX {
238
244
  lcb_INSTANCE *instance;
239
245
  lcb_U16 persist_to;
@@ -400,6 +406,12 @@ static lcb_STATUS store_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
400
406
  if (err != LCB_SUCCESS) {
401
407
  return err;
402
408
  }
409
+ for (const auto &privilege : cmd->extra_privileges()) {
410
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
411
+ if (err != LCB_SUCCESS) {
412
+ return err;
413
+ }
414
+ }
403
415
  }
404
416
  auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
405
417
  hdr.request.magic = (ffextlen == 0) ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -409,6 +409,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_on_behalf_of(lcb_CMDSUBDOC *cmd, const
409
409
  return cmd->on_behalf_of(std::string(data, data_len));
410
410
  }
411
411
 
412
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_on_behalf_of_extra_privilege(lcb_CMDSUBDOC *cmd, const char *privilege,
413
+ size_t privilege_len)
414
+ {
415
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
416
+ }
417
+
412
418
  namespace SubdocCmdTraits
413
419
  {
414
420
  enum Options {
@@ -798,6 +804,12 @@ static lcb_STATUS subdoc_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
798
804
  if (rc != LCB_SUCCESS) {
799
805
  return rc;
800
806
  }
807
+ for (const auto &privilege : cmd->extra_privileges()) {
808
+ rc = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
809
+ if (rc != LCB_SUCCESS) {
810
+ return rc;
811
+ }
812
+ }
801
813
  }
802
814
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
803
815
  auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
@@ -117,6 +117,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_on_behalf_of(lcb_CMDTOUCH *cmd, const c
117
117
  return cmd->on_behalf_of(std::string(data, data_len));
118
118
  }
119
119
 
120
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_on_behalf_of_extra_privilege(lcb_CMDTOUCH *cmd, const char *privilege,
121
+ size_t privilege_len)
122
+ {
123
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
124
+ }
125
+
120
126
  static lcb_STATUS touch_validate(lcb_INSTANCE *instance, const lcb_CMDTOUCH *cmd)
121
127
  {
122
128
  if (cmd->key().empty()) {
@@ -142,6 +148,12 @@ static lcb_STATUS touch_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
142
148
  if (err != LCB_SUCCESS) {
143
149
  return err;
144
150
  }
151
+ for (const auto &privilege : cmd->extra_privileges()) {
152
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
153
+ if (err != LCB_SUCCESS) {
154
+ return err;
155
+ }
156
+ }
145
157
  }
146
158
 
147
159
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -106,6 +106,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_on_behalf_of(lcb_CMDUNLOCK *cmd, const
106
106
  return cmd->on_behalf_of(std::string(data, data_len));
107
107
  }
108
108
 
109
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_on_behalf_of_extra_privilege(lcb_CMDUNLOCK *cmd, const char *privilege,
110
+ size_t privilege_len)
111
+ {
112
+ return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
113
+ }
114
+
109
115
  static lcb_STATUS unlock_validate(lcb_INSTANCE *instance, const lcb_CMDUNLOCK *cmd)
110
116
  {
111
117
  if (cmd->key().empty()) {
@@ -137,6 +143,12 @@ static lcb_STATUS unlock_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
137
143
  if (err != LCB_SUCCESS) {
138
144
  return err;
139
145
  }
146
+ for (const auto &privilege : cmd->extra_privileges()) {
147
+ err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
148
+ if (err != LCB_SUCCESS) {
149
+ return err;
150
+ }
151
+ }
140
152
  }
141
153
 
142
154
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -97,8 +97,7 @@ void lcb_SEARCH_HANDLE_::invoke_row(lcb_RESPSEARCH *resp)
97
97
  } else if (resp->ctx.http_response_code == 400) {
98
98
  if (error_message_.find("not_found") != std::string::npos) {
99
99
  resp->ctx.rc = LCB_ERR_INDEX_NOT_FOUND;
100
- } else if (error_message_.find("CreateIndex, Prepare failed, err: num_fts_indexes") !=
101
- std::string::npos) {
100
+ } else if (error_message_.find("num_fts_indexes") != std::string::npos) {
102
101
  resp->ctx.rc = LCB_ERR_QUOTA_LIMITED;
103
102
  }
104
103
  } else if (resp->ctx.http_response_code == 429) {
@@ -106,6 +106,7 @@ void lcb_settings_unref(lcb_settings *settings)
106
106
  }
107
107
  free(settings->bucket);
108
108
  free(settings->sasl_mech_force);
109
+ free(settings->truststorepath);
109
110
  free(settings->certpath);
110
111
  free(settings->keypath);
111
112
  free(settings->client_string);
@@ -32,6 +32,26 @@
32
32
  #define LOGARGS(ssl, lvl) ((lcbio_SOCKET *)SSL_get_app_data(ssl))->settings, "SSL", lvl, __FILE__, __LINE__
33
33
  static char *global_event = "dummy event for ssl";
34
34
 
35
+ static const char *capella_ca_cert = "-----BEGIN CERTIFICATE-----\n"
36
+ "MIIDFTCCAf2gAwIBAgIRANLVkgOvtaXiQJi0V6qeNtswDQYJKoZIhvcNAQELBQAw\n"
37
+ "JDESMBAGA1UECgwJQ291Y2hiYXNlMQ4wDAYDVQQLDAVDbG91ZDAeFw0xOTEyMDYy\n"
38
+ "MjEyNTlaFw0yOTEyMDYyMzEyNTlaMCQxEjAQBgNVBAoMCUNvdWNoYmFzZTEOMAwG\n"
39
+ "A1UECwwFQ2xvdWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfvOIi\n"
40
+ "enG4Dp+hJu9asdxEMRmH70hDyMXv5ZjBhbo39a42QwR59y/rC/sahLLQuNwqif85\n"
41
+ "Fod1DkqgO6Ng3vecSAwyYVkj5NKdycQu5tzsZkghlpSDAyI0xlIPSQjoORA/pCOU\n"
42
+ "WOpymA9dOjC1bo6rDyw0yWP2nFAI/KA4Z806XeqLREuB7292UnSsgFs4/5lqeil6\n"
43
+ "rL3ooAw/i0uxr/TQSaxi1l8t4iMt4/gU+W52+8Yol0JbXBTFX6itg62ppb/Eugmn\n"
44
+ "mQRMgL67ccZs7cJ9/A0wlXencX2ohZQOR3mtknfol3FH4+glQFn27Q4xBCzVkY9j\n"
45
+ "KQ20T1LgmGSngBInAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE\n"
46
+ "FJQOBPvrkU2In1Sjoxt97Xy8+cKNMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0B\n"
47
+ "AQsFAAOCAQEARgM6XwcXPLSpFdSf0w8PtpNGehmdWijPM3wHb7WZiS47iNen3oq8\n"
48
+ "m2mm6V3Z57wbboPpfI+VEzbhiDcFfVnK1CXMC0tkF3fnOG1BDDvwt4jU95vBiNjY\n"
49
+ "xdzlTP/Z+qr0cnVbGBSZ+fbXstSiRaaAVcqQyv3BRvBadKBkCyPwo+7svQnScQ5P\n"
50
+ "Js7HEHKVms5tZTgKIw1fbmgR2XHleah1AcANB+MAPBCcTgqurqr5G7W2aPSBLLGA\n"
51
+ "fRIiVzm7VFLc7kWbp7ENH39HVG6TZzKnfl9zJYeiklo5vQQhGSMhzBsO70z4RRzi\n"
52
+ "DPFAN/4qZAgD5q3AFNIq2WWADFQGSwVJhg==\n"
53
+ "-----END CERTIFICATE-----\n";
54
+
35
55
  /******************************************************************************
36
56
  ******************************************************************************
37
57
  ** Boilerplate lcbio_TABLE Wrappers **
@@ -221,6 +241,9 @@ static void log_callback(const SSL *ssl, int where, int ret)
221
241
  {
222
242
  int should_log = 0;
223
243
  lcbio_SOCKET *sock = SSL_get_app_data(ssl);
244
+ if (sock == NULL) {
245
+ return;
246
+ }
224
247
  /* Ignore low-level SSL stuff */
225
248
 
226
249
  if (where & SSL_CB_ALERT) {
@@ -298,6 +321,48 @@ static long decode_ssl_protocol(const char *protocol)
298
321
  return disallow;
299
322
  }
300
323
 
324
+ static lcb_STATUS add_certificate_authority(const lcb_settings *settings, SSL_CTX *ctx, const char *certificate_value,
325
+ int certificate_length)
326
+ {
327
+ lcb_STATUS rc = LCB_SUCCESS;
328
+ ERR_clear_error();
329
+
330
+ BIO *bio = BIO_new_mem_buf(certificate_value, certificate_length);
331
+ if (bio) {
332
+ X509_STORE *store = SSL_CTX_get_cert_store(ctx);
333
+ if (store) {
334
+ for (int added = 0;; added = 1) {
335
+ X509 *cert = PEM_read_bio_X509(bio, 0, 0, 0);
336
+ if (!cert) {
337
+ unsigned long err = ERR_get_error();
338
+ if (added && ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
339
+ break;
340
+ }
341
+ lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR),
342
+ "Unable to load default certificate: lib=%s, func=%s, reason=%s", ERR_lib_error_string(err),
343
+ ERR_func_error_string(err), ERR_reason_error_string(err));
344
+ rc = LCB_ERR_SSL_ERROR;
345
+ goto GT_CLEANUP;
346
+ }
347
+
348
+ int ok = X509_STORE_add_cert(store, cert);
349
+ X509_free(cert);
350
+ if (ok != 1) {
351
+ unsigned long err = ERR_get_error();
352
+ lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR),
353
+ "Unable to add default certificate: lib=%s, func=%s, reason=%s", ERR_lib_error_string(err),
354
+ ERR_func_error_string(err), ERR_reason_error_string(err));
355
+ rc = LCB_ERR_SSL_ERROR;
356
+ goto GT_CLEANUP;
357
+ }
358
+ }
359
+ }
360
+ }
361
+ GT_CLEANUP:
362
+ BIO_free(bio);
363
+ return rc;
364
+ }
365
+
301
366
  lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *keyfile, int noverify, lcb_STATUS *errp,
302
367
  lcb_settings *settings)
303
368
  {
@@ -351,28 +416,41 @@ lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *
351
416
  }
352
417
  #endif
353
418
 
354
- if (cafile || tsfile) {
419
+ if (tsfile) {
355
420
  lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Load verify locations from \"%s\"", tsfile ? tsfile : cafile);
356
421
  if (!SSL_CTX_load_verify_locations(ret->ctx, tsfile ? tsfile : cafile, NULL)) {
357
422
  *errp = LCB_ERR_SSL_ERROR;
358
423
  goto GT_ERR;
359
424
  }
360
- if (cafile && keyfile) {
361
- lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Authenticate with key \"%s\", cert \"%s\"", keyfile, cafile);
362
- if (!SSL_CTX_use_certificate_file(ret->ctx, cafile, SSL_FILETYPE_PEM)) {
363
- *errp = LCB_ERR_SSL_ERROR;
364
- goto GT_ERR;
365
- }
366
- if (!SSL_CTX_use_PrivateKey_file(ret->ctx, keyfile, SSL_FILETYPE_PEM)) {
367
- lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to load private key \"%s\"", keyfile);
368
- *errp = LCB_ERR_SSL_ERROR;
369
- goto GT_ERR;
370
- }
371
- if (!SSL_CTX_check_private_key(ret->ctx)) {
372
- lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to verify private key \"%s\"", keyfile);
373
- *errp = LCB_ERR_SSL_ERROR;
374
- goto GT_ERR;
375
- }
425
+ } else {
426
+ lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Use default CA for TLS verify");
427
+ if (SSL_CTX_set_default_verify_paths(ret->ctx) != 1) {
428
+ unsigned long err = ERR_get_error();
429
+ lcb_log(LOGARGS_S(settings, LCB_LOG_WARN), "Unable to load system certificates: lib=%s, reason=%s",
430
+ ERR_lib_error_string(err), ERR_reason_error_string(err));
431
+ }
432
+ // add the capella Root CA if no other CA was specified.
433
+ *errp = add_certificate_authority(settings, ret->ctx, capella_ca_cert, strlen(capella_ca_cert));
434
+ if (*errp != LCB_SUCCESS) {
435
+ goto GT_ERR;
436
+ }
437
+ }
438
+
439
+ if (cafile && keyfile) {
440
+ lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Authenticate with key \"%s\", cert \"%s\"", keyfile, cafile);
441
+ if (!SSL_CTX_use_certificate_chain_file(ret->ctx, cafile)) {
442
+ *errp = LCB_ERR_SSL_ERROR;
443
+ goto GT_ERR;
444
+ }
445
+ if (!SSL_CTX_use_PrivateKey_file(ret->ctx, keyfile, SSL_FILETYPE_PEM)) {
446
+ lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to load private key \"%s\"", keyfile);
447
+ *errp = LCB_ERR_SSL_ERROR;
448
+ goto GT_ERR;
449
+ }
450
+ if (!SSL_CTX_check_private_key(ret->ctx)) {
451
+ lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to verify private key \"%s\"", keyfile);
452
+ *errp = LCB_ERR_SSL_ERROR;
453
+ goto GT_ERR;
376
454
  }
377
455
  }
378
456
 
@@ -422,15 +500,25 @@ GT_ERR:
422
500
  return NULL;
423
501
  }
424
502
 
503
+ struct proto_ctx_ssl {
504
+ lcbio_PROTOCTX proto;
505
+ SSL *ssl;
506
+ };
507
+
425
508
  static void noop_dtor(lcbio_PROTOCTX *arg)
426
509
  {
427
- free(arg);
510
+ if (!arg) {
511
+ return;
512
+ }
513
+ struct proto_ctx_ssl *sproto = (struct proto_ctx_ssl *)arg;
514
+ SSL_set_app_data(sproto->ssl, NULL);
515
+ free(sproto);
428
516
  }
429
517
 
430
518
  lcb_STATUS lcbio_ssl_apply(lcbio_SOCKET *sock, lcbio_pSSLCTX sctx)
431
519
  {
432
520
  lcbio_pTABLE old_iot = sock->io, new_iot;
433
- lcbio_PROTOCTX *sproto;
521
+ struct proto_ctx_ssl *sproto;
434
522
 
435
523
  if (old_iot->model == LCB_IOMODEL_EVENT) {
436
524
  new_iot = lcbio_Essl_new(old_iot, sock->u.fd, sctx->ctx);
@@ -440,12 +528,13 @@ lcb_STATUS lcbio_ssl_apply(lcbio_SOCKET *sock, lcbio_pSSLCTX sctx)
440
528
 
441
529
  if (new_iot) {
442
530
  sproto = calloc(1, sizeof(*sproto));
443
- sproto->id = LCBIO_PROTOCTX_SSL;
444
- sproto->dtor = noop_dtor;
445
- lcbio_protoctx_add(sock, sproto);
531
+ sproto->proto.id = LCBIO_PROTOCTX_SSL;
532
+ sproto->proto.dtor = noop_dtor;
533
+ lcbio_protoctx_add(sock, &sproto->proto);
446
534
  lcbio_table_unref(old_iot);
447
535
  sock->io = new_iot;
448
536
  /* just for logging */
537
+ sproto->ssl = ((lcbio_XSSL *)new_iot)->ssl;
449
538
  SSL_set_app_data(((lcbio_XSSL *)new_iot)->ssl, sock);
450
539
  return LCB_SUCCESS;
451
540
 
@@ -214,3 +214,24 @@ lcb_STATUS lcb::flexible_framing_extras::encode_impersonate_user(const std::stri
214
214
  }
215
215
  return LCB_SUCCESS;
216
216
  }
217
+
218
+ lcb_STATUS lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(
219
+ const std::string &privilege, std::vector<std::uint8_t> &flexible_framing_extras)
220
+ {
221
+ auto privilege_len = privilege.size();
222
+ if (privilege_len > std::numeric_limits<std::uint8_t>::max() + 0xfU) {
223
+ return LCB_ERR_INVALID_ARGUMENT;
224
+ }
225
+ std::uint8_t frame_id = 0x06;
226
+ if (privilege_len < 15) {
227
+ auto frame_size = static_cast<std::uint8_t>(privilege_len);
228
+ flexible_framing_extras.emplace_back(frame_id << 4U | frame_size);
229
+ } else {
230
+ flexible_framing_extras.emplace_back(frame_id << 4U | 0xfU);
231
+ flexible_framing_extras.emplace_back(privilege_len - 0xfU);
232
+ }
233
+ for (const auto byte : privilege) {
234
+ flexible_framing_extras.emplace_back(byte);
235
+ }
236
+ return LCB_SUCCESS;
237
+ }
@@ -29,6 +29,9 @@ namespace lcb
29
29
  namespace flexible_framing_extras
30
30
  {
31
31
  lcb_STATUS encode_impersonate_user(const std::string &username, std::vector<std::uint8_t> &flexible_framing_extras);
32
+
33
+ lcb_STATUS encode_impersonate_users_extra_privilege(const std::string &privilege,
34
+ std::vector<std::uint8_t> &flexible_framing_extras);
32
35
  } // namespace flexible_framing_extras
33
36
  } // namespace lcb
34
37
 
@@ -932,12 +932,19 @@ char *lcbvb_save_json(lcbvb_CONFIG *cfg)
932
932
  cJSON *tmp = NULL, *nodes = NULL;
933
933
  cJSON *root = cJSON_CreateObject();
934
934
 
935
- if (cfg->dtype == LCBVB_DIST_VBUCKET) {
936
- tmp = cJSON_CreateString("vbucket");
937
- } else {
938
- tmp = cJSON_CreateString("ketama");
935
+ switch (cfg->dtype) {
936
+ case LCBVB_DIST_VBUCKET:
937
+ tmp = cJSON_CreateString("vbucket");
938
+ break;
939
+ case LCBVB_DIST_KETAMA:
940
+ tmp = cJSON_CreateString("ketama");
941
+ break;
942
+ default:
943
+ break;
944
+ }
945
+ if (tmp) {
946
+ cJSON_AddItemToObject(root, "nodeLocator", tmp);
939
947
  }
940
- cJSON_AddItemToObject(root, "nodeLocator", tmp);
941
948
 
942
949
  if (cfg->buuid) {
943
950
  tmp = cJSON_CreateString(cfg->buuid);
@@ -951,8 +958,10 @@ char *lcbvb_save_json(lcbvb_CONFIG *cfg)
951
958
  tmp = cJSON_CreateInt64(cfg->revid);
952
959
  cJSON_AddItemToObject(root, "rev", tmp);
953
960
  }
954
- tmp = cJSON_CreateString(cfg->bname);
955
- cJSON_AddItemToObject(root, "name", tmp);
961
+ if (cfg->bname != NULL) {
962
+ tmp = cJSON_CreateString(cfg->bname);
963
+ cJSON_AddItemToObject(root, "name", tmp);
964
+ }
956
965
 
957
966
  nodes = cJSON_CreateArray();
958
967
  cJSON_AddItemToObject(root, "nodesExt", nodes);
@@ -173,7 +173,7 @@ MACRO(DEFINE_MOCKTEST plugin test)
173
173
  --gtest_filter="ContaminatingUnitTest.*"
174
174
  --gtest_throw_on_failure=1
175
175
  --gtest_print_time=1
176
- --gtest_output=xml:"${PROJECT_BINARY_DIR}/REPORT_${plugin}_${test}.xml")
176
+ --gtest_output=xml:"${PROJECT_BINARY_DIR}/REPORT_${plugin}_${test}_contaminating.xml")
177
177
  SET_TESTS_PROPERTIES(check-contaminating-${plugin}-${test} PROPERTIES LABELS "contaminating" )
178
178
  ENDMACRO()
179
179
 
@@ -423,7 +423,19 @@ static void statsCallback(lcb_INSTANCE *instance, lcb_CALLBACK_TYPE, const lcb_R
423
423
  }
424
424
  break;
425
425
  case 7:
426
- version = MockEnvironment::VERSION_70;
426
+ switch (minor) {
427
+ case 0:
428
+ version = MockEnvironment::VERSION_70;
429
+ break;
430
+ case 1:
431
+ version = MockEnvironment::VERSION_71;
432
+ break;
433
+ case 2:
434
+ version = MockEnvironment::VERSION_72;
435
+ break;
436
+ default:
437
+ break;
438
+ }
427
439
  break;
428
440
  default:
429
441
  break;
@@ -246,7 +246,9 @@ class MockEnvironment : public ::testing::Environment
246
246
  VERSION_60 = 10,
247
247
  VERSION_65 = 11,
248
248
  VERSION_66 = 12,
249
- VERSION_70 = 13
249
+ VERSION_70 = 13,
250
+ VERSION_71 = 14,
251
+ VERSION_72 = 15,
250
252
  };
251
253
 
252
254
  void SetUp() override;
@@ -37,10 +37,15 @@ class ServerParams
37
37
  void makeConnectParams(lcb_CREATEOPTS *&crst, lcb_io_opt_t io, lcb_INSTANCE_TYPE type = LCB_TYPE_BUCKET)
38
38
  {
39
39
  lcb_createopts_create(&crst, type);
40
- if (host.find("couchbase://") == 0) {
40
+ if (host.find("couchbase") == 0) {
41
41
  connstr = host;
42
42
  // deactivate dnssrv and compression, use cccp bootstrap
43
- connstr += "?dnssrv=off&bootstrap_on=cccp&compression=off";
43
+ if (host.find("?") == std::string::npos) {
44
+ connstr += "?";
45
+ } else {
46
+ connstr += "&";
47
+ }
48
+ connstr += "dnssrv=off&bootstrap_on=cccp&compression=off";
44
49
  } else {
45
50
  if (mcNodes.empty() || type == LCB_TYPE_CLUSTER) {
46
51
  connstr = "couchbase://" + host + "=http";