couchbase 3.2.4 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
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";