libmongocrypt-helper 1.20.1.0.1001 → 1.20.3.0.1001

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f3bd46869436cf55ec31236a73965ec1f198f75809d53e084aebb6c056bead0
4
- data.tar.gz: 4868779b572f103a7f7f6ae88ea15032dd829e31c5a85e1f41364bd0d7f17d60
3
+ metadata.gz: b7037c7cdeb5a2f1fe94446f583e7c953539328df98580028a07f46c296689ec
4
+ data.tar.gz: 52a6c553f0e7ee8e0c6aca713184fe9c13f7e5babf97c18e4eff17235b8e7109
5
5
  SHA512:
6
- metadata.gz: 57f84ed485336784bd0dd5008a4d2f893146f3cb4128c121d5e91dc5bb8c80c07f8d7a6e44edd869327876c1b0410b1790b84a0548bb0459b6e7bc53a7151a83
7
- data.tar.gz: 27917b4a2c97d98db62661d48f0c3dace264f84f83ba9fd1f9de351dc11a20bb0f29445c51ffa94b82b51716adb1bf925bf18804358d5bac1b701651bc735846
6
+ metadata.gz: 190dff33114c3f35a8ba07776144bdfde51523e75277176c4c0bf5bdef0be4d500500c3b11eed1520635e43d7b8201faec4faca54da7c99bd119da8d7c3f606e
7
+ data.tar.gz: 20446b82d1838e42ce90980bea22112b4af933cd66daa0984e15b00f1dde2867f408d87f5ed2f86ec146db64b4f0201c0a9be9cdcc30923e48acff5793ab1aa5
@@ -1,5 +1,14 @@
1
1
  # ChangeLog
2
2
 
3
+ ## 1.20.3
4
+
5
+ ### Fixed
6
+ - Validate database and collection name arguments against "." and NUL bytes
7
+ ## 1.20.2
8
+
9
+ ### Changed
10
+ - Add checks when creating GCP requests.
11
+
3
12
  ## 1.20.1
4
13
 
5
14
  ## Changed
@@ -438,12 +438,12 @@ test-deb-packages-from-ppa:
438
438
  RUN ./test.out
439
439
 
440
440
  # `sign` uses Garasign to sign a file with the libmongocrypt key.
441
- # Requires prior authentication with Artifactory.
441
+ # Requires prior authentication with the DevProd Platforms ECR registry (see doc/releasing.md).
442
442
  # See: https://docs.devprod.prod.corp.mongodb.com/release-tools-container-images/garasign/garasign_signing/.
443
443
  sign:
444
444
  ARG --required file_to_sign
445
445
  ARG --required output_file
446
- FROM artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-gpg
446
+ FROM 901841024863.dkr.ecr.us-east-1.amazonaws.com/release-infrastructure/garasign-gpg
447
447
  WORKDIR /s
448
448
  COPY ${file_to_sign} /s/file
449
449
  RUN --secret garasign_username --secret garasign_password \
@@ -460,8 +460,9 @@ sign:
460
460
  # An environment with the `silkbomb` command.
461
461
  #
462
462
  # See https://docs.devprod.prod.corp.mongodb.com/mms/python/src/sbom/silkbomb/ for documentation of silkbomb.
463
+ # Requires prior authentication with the DevProd Platforms ECR registry (see doc/releasing.md).
463
464
  silkbomb:
464
- FROM artifactory.corp.mongodb.com/release-tools-container-registry-public-local/silkbomb:2.0
465
+ FROM 901841024863.dkr.ecr.us-east-1.amazonaws.com/release-infrastructure/silkbomb:2.0
465
466
  # Alias the silkbomb executable to a simpler name:
466
467
  RUN ln -s /python/src/sbom/silkbomb/bin /usr/local/bin/silkbomb
467
468
 
@@ -28,6 +28,18 @@ bash scripts/update-version.sh <new-version>
28
28
  This will set the version in `scripts/libmongocrypt-version.sh` and update `sbom.json` to reflect
29
29
  the new vendored version of `libmongocrypt`.
30
30
 
31
+ This pulls the `silkbomb` image from the DevProd Platforms ECR registry. Authenticate to the ECR
32
+ registry with the container launcher (`docker` or `podman`) before running the script:
33
+
34
+ ```bash
35
+ aws sso login --profile ECRScopedAccess-901841024863
36
+
37
+ # Authenticate "podman" or "docker"
38
+ CONTAINER_LAUNCHER="podman"
39
+
40
+ aws ecr get-login-password --region us-east-1 --profile ECRScopedAccess-901841024863 | $CONTAINER_LAUNCHER login --username AWS --password-stdin 901841024863.dkr.ecr.us-east-1.amazonaws.com
41
+ ```
42
+
31
43
  ## Building wheels
32
44
 
33
45
  To build wheels, run `scripts/release.sh`. It will build the appropriate wheel for the current system
@@ -21,7 +21,7 @@ else
21
21
  fi
22
22
 
23
23
  echo "pkg:github/mongodb/libmongocrypt@$LIBMONGOCRYPT_VERSION" > purls.txt
24
- $DOCKER run --platform="linux/amd64" -it --rm -v $(pwd):$(pwd) artifactory.corp.mongodb.com/release-tools-container-registry-public-local/silkbomb:2.0 update --purls=$(pwd)/purls.txt -o $(pwd)/sbom.json
24
+ $DOCKER run --platform="linux/amd64" -it --rm -v $(pwd):$(pwd) 901841024863.dkr.ecr.us-east-1.amazonaws.com/release-infrastructure/silkbomb:2.0 update --purls=$(pwd)/purls.txt -o $(pwd)/sbom.json
25
25
  rm purls.txt
26
26
 
27
27
  popd
@@ -93,6 +93,15 @@ Do the following when releasing:
93
93
  ```bash
94
94
  ./.evergreen/earthly.sh +sbom-generate-new-serial-number
95
95
  ```
96
+ This pulls the `silkbomb` image from the DevProd Platforms ECR registry. Authenticate to the ECR registry with the container launcher (`docker` or `podman`):
97
+ ```bash
98
+ aws sso login --profile ECRScopedAccess-901841024863
99
+
100
+ # Authenticate "podman" or "docker"
101
+ CONTAINER_LAUNCHER="podman"
102
+
103
+ aws ecr get-login-password --region us-east-1 --profile ECRScopedAccess-901841024863 | $CONTAINER_LAUNCHER login --username AWS --password-stdin 901841024863.dkr.ecr.us-east-1.amazonaws.com
104
+ ```
96
105
  Commit resulting `etc/cyclonedx.sbom.json` and push to `rx.y`.
97
106
  - Remove yourself from the [releases team](https://github.com/orgs/mongodb/teams/dbx-c-cxx-releases) on GitHub via [MANA](https://mana.corp.mongodb.com/resources/68029673d39aa9f7de6399f9).
98
107
  - If this is a new non-patch release (e.g. `x.y.0`):
@@ -130,6 +139,7 @@ Do the following when releasing:
130
139
  ```bash
131
140
  ./.evergreen/earthly.sh +sbom-generate-new-serial-number
132
141
  ```
142
+ Requires AWS SSO access to the `ECRScopedAccess-901841024863` profile (see note above).
133
143
  Commit resulting `etc/cyclonedx.sbom.json`.
134
144
  - Update the release on the [Jira releases page](https://jira.mongodb.org/projects/MONGOCRYPT/versions).
135
145
  - Record the release on [C/C++ Release Info](https://docs.google.com/spreadsheets/d/1yHfGmDnbA5-Qt8FX4tKWC5xk9AhzYZx1SKF4AD36ecY/edit?usp=sharing). This is done to leave commentary about the process.
@@ -57,7 +57,7 @@
57
57
  }
58
58
  ],
59
59
  "metadata": {
60
- "timestamp": "2026-07-14T13:56:19.068748+00:00",
60
+ "timestamp": "2026-08-07T17:48:10.053548+00:00",
61
61
  "tools": [
62
62
  {
63
63
  "externalReferences": [
@@ -100,7 +100,7 @@
100
100
  }
101
101
  ]
102
102
  },
103
- "serialNumber": "urn:uuid:870a42e2-38df-4271-afee-8ffa5c28bcf7",
103
+ "serialNumber": "urn:uuid:464d2591-6478-4559-a1c4-9a726248fc1e",
104
104
  "version": 1,
105
105
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
106
106
  "bomFormat": "CycloneDX",
@@ -20,6 +20,8 @@
20
20
  #include "kms_message_private.h"
21
21
  #include "kms_request_opt_private.h"
22
22
 
23
+ #include <ctype.h>
24
+
23
25
  /* Set a default expiration of 5 minutes for JSON Web Tokens (GCP allows up to
24
26
  * one hour) */
25
27
  #define JWT_EXPIRATION_SECS 5 * 60
@@ -145,6 +147,38 @@ done:
145
147
  return req;
146
148
  }
147
149
 
150
+ /* _check_key_identifier returns true if `value` is safe to use as a URL path segment.
151
+ *
152
+ * Key identifiers may originate from key vault documents or caller-supplied options. They are
153
+ * formatted into the request path, so an unescaped '/', '?', '#', space, or CR/LF would rewrite
154
+ * the request target or inject header lines into the request.
155
+ *
156
+ * Only the RFC 3986 unreserved characters are permitted. This is a superset of what GCP itself
157
+ * accepts, so it does not reject any identifier that would otherwise work:
158
+ * - keyRing and keyName must match `[a-zA-Z0-9_-]{1,63}`. See
159
+ * https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings/create and
160
+ * https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/create
161
+ * - projectId is 6-30 characters of lowercase letters, numbers, and hyphens. See
162
+ * https://cloud.google.com/resource-manager/docs/creating-managing-projects
163
+ * - location is a Cloud location name (e.g. "global", "us-east1").
164
+ * - keyVersion is a positive integer.
165
+ *
166
+ * `value` is not included in the error message: it is untrusted, and the error may be logged. */
167
+ static bool
168
+ _check_key_identifier (kms_request_t *req, const char *name, const char *value)
169
+ {
170
+ const char *c;
171
+
172
+ for (c = value; *c != '\0'; c++) {
173
+ if (!isalnum ((unsigned char) *c) && *c != '-' && *c != '.' && *c != '_' &&
174
+ *c != '~') {
175
+ KMS_ERROR (req, "Invalid character in GCP KMS key identifier: %s", name);
176
+ return false;
177
+ }
178
+ }
179
+ return true;
180
+ }
181
+
148
182
  static kms_request_t *
149
183
  _encrypt_decrypt_common (const char *encrypt_decrypt,
150
184
  const char *host,
@@ -192,6 +226,14 @@ _encrypt_decrypt_common (const char *encrypt_decrypt,
192
226
  goto done;
193
227
  }
194
228
 
229
+ if (!_check_key_identifier (req, "projectId", project_id) ||
230
+ !_check_key_identifier (req, "location", location) ||
231
+ !_check_key_identifier (req, "keyRing", key_ring_name) ||
232
+ !_check_key_identifier (req, "keyName", key_name) ||
233
+ (key_version && !_check_key_identifier (req, "keyVersion", key_version))) {
234
+ goto done;
235
+ }
236
+
195
237
  value_base64 = kms_message_raw_to_b64 (value, value_len);
196
238
  if (!value_base64) {
197
239
  KMS_ERROR (req, "Could not bases64-encode plaintext");
@@ -323,7 +323,11 @@ bool mc_schema_broker_satisfy_from_collinfo(mc_schema_broker_t *sb,
323
323
  CLIENT_ERR("failed to find 'name' in collinfo in database: %s", sb->db);
324
324
  return false;
325
325
  }
326
- coll = bson_iter_utf8(&name_iter, NULL);
326
+ uint32_t coll_len;
327
+ coll = bson_iter_utf8(&name_iter, &coll_len);
328
+ if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "collection name in collinfo", status)) {
329
+ return false;
330
+ }
327
331
  }
328
332
 
329
333
  // Cache the received collinfo.
@@ -508,7 +512,11 @@ bool mc_schema_broker_satisfy_from_create_or_collMod(mc_schema_broker_t *sb,
508
512
  CLIENT_ERR("Failed to get collection name from command");
509
513
  return false;
510
514
  }
511
- const char *coll = bson_iter_utf8(&iter, NULL);
515
+ uint32_t coll_len;
516
+ const char *coll = bson_iter_utf8(&iter, &coll_len);
517
+ if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "collection name", status)) {
518
+ return false;
519
+ }
512
520
 
513
521
  // Check if schema was requested.
514
522
  mc_schema_entry_t *found = NULL;
@@ -2303,7 +2303,11 @@ static bool _check_cmd_for_auto_encrypt_bulkWrite(mongocrypt_binary_t *cmd,
2303
2303
  return false;
2304
2304
  }
2305
2305
 
2306
- const char *target_ns = bson_iter_utf8(&ns_iter, NULL /* length */);
2306
+ uint32_t target_ns_len;
2307
+ const char *target_ns = bson_iter_utf8(&ns_iter, &target_ns_len);
2308
+ if (!_mongocrypt_check_no_embedded_nul(target_ns, target_ns_len, "namespace in `bulkWrite` command", status)) {
2309
+ return false;
2310
+ }
2307
2311
  // Parse `target_ns` into "<db>.<coll>"
2308
2312
  const char *dot = strstr(target_ns, ".");
2309
2313
  if (!dot) {
@@ -2375,7 +2379,12 @@ _check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **targe
2375
2379
  }
2376
2380
 
2377
2381
  if (BSON_ITER_HOLDS_UTF8(&target_coll_iter)) {
2378
- *target_coll = bson_strdup(bson_iter_utf8(&target_coll_iter, NULL));
2382
+ uint32_t target_coll_len;
2383
+ const char *target_coll_str = bson_iter_utf8(&target_coll_iter, &target_coll_len);
2384
+ if (!_mongocrypt_check_no_embedded_nul(target_coll_str, target_coll_len, "collection name", status)) {
2385
+ return false;
2386
+ }
2387
+ *target_coll = bson_strdup(target_coll_str);
2379
2388
  } else {
2380
2389
  *target_coll = NULL;
2381
2390
  }
@@ -2572,7 +2581,11 @@ static bool find_collections_in_pipeline(mc_schema_broker_t *sb,
2572
2581
  stage_key);
2573
2582
  return false;
2574
2583
  }
2575
- const char *from = bson_iter_utf8(&lookup_iter, NULL);
2584
+ uint32_t from_len;
2585
+ const char *from = bson_iter_utf8(&lookup_iter, &from_len);
2586
+ if (!_mongocrypt_check_no_embedded_nul(from, from_len, "'from' collection name", status)) {
2587
+ return false;
2588
+ }
2576
2589
  if (!mc_schema_broker_request(sb, db, from, status)) {
2577
2590
  return false;
2578
2591
  }
@@ -2631,7 +2644,11 @@ static bool find_collections_in_pipeline(mc_schema_broker_t *sb,
2631
2644
  stage_key);
2632
2645
  return false;
2633
2646
  }
2634
- const char *coll = bson_iter_utf8(&unionWith_iter, NULL);
2647
+ uint32_t coll_len;
2648
+ const char *coll = bson_iter_utf8(&unionWith_iter, &coll_len);
2649
+ if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "'coll' collection name", status)) {
2650
+ return false;
2651
+ }
2635
2652
  if (!mc_schema_broker_request(sb, db, coll, status)) {
2636
2653
  return false;
2637
2654
  }
@@ -2722,6 +2739,10 @@ bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t
2722
2739
  return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db");
2723
2740
  }
2724
2741
 
2742
+ if (strchr(ectx->cmd_db, '.')) {
2743
+ return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db: must not contain a dot");
2744
+ }
2745
+
2725
2746
  if (0 == strcmp(ectx->cmd_name, "bulkWrite")) {
2726
2747
  // Handle `bulkWrite` as a special case.
2727
2748
  // `bulkWrite` includes the target namespaces in an `nsInfo` field.
@@ -161,6 +161,11 @@ typedef enum {
161
161
 
162
162
  bool _mongocrypt_validate_and_copy_string(const char *in, int32_t in_len, char **out) MONGOCRYPT_WARN_UNUSED_RESULT;
163
163
 
164
+ /* _mongocrypt_check_no_embedded_nul returns false and sets @status if @str contains an embedded null byte. See
165
+ * MONGOCRYPT-977. */
166
+ bool _mongocrypt_check_no_embedded_nul(const char *str, uint32_t len, const char *what, mongocrypt_status_t *status)
167
+ MONGOCRYPT_WARN_UNUSED_RESULT;
168
+
164
169
  char *_mongocrypt_new_string_from_bytes(const void *in, int len);
165
170
 
166
171
  /* _mongocrypt_needs_credentials returns true if @crypt was configured to
@@ -913,6 +913,17 @@ uint64_t mongocrypt_crypt_shared_lib_version(const mongocrypt_t *crypt) {
913
913
  return crypt->csfle.get_version();
914
914
  }
915
915
 
916
+ bool _mongocrypt_check_no_embedded_nul(const char *str, uint32_t len, const char *what, mongocrypt_status_t *status) {
917
+ BSON_ASSERT_PARAM(str);
918
+ BSON_ASSERT_PARAM(what);
919
+
920
+ if (strlen(str) != (size_t)len) {
921
+ CLIENT_ERR("%s must not contain an embedded null byte", what);
922
+ return false;
923
+ }
924
+ return true;
925
+ }
926
+
916
927
  bool _mongocrypt_validate_and_copy_string(const char *in, int32_t in_len, char **out) {
917
928
  BSON_ASSERT_PARAM(out);
918
929
 
@@ -242,7 +242,58 @@ static void _test_encrypt_with_accesstoken(_mongocrypt_tester_t *tester) {
242
242
  mongocrypt_destroy(crypt);
243
243
  }
244
244
 
245
+ // Test a CRLF in a key vault document's keyName. Regression test for MONGOCRYPT-960.
246
+ static void _test_crlf_in_gcp_masterkey(_mongocrypt_tester_t *tester) {
247
+ mongocrypt_t *crypt;
248
+ mongocrypt_ctx_t *ctx;
249
+ mongocrypt_binary_t *uuid;
250
+ const char *uuid_data = "\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61";
251
+
252
+ // A key vault document whose masterKey.keyName contains a CRLF.
253
+ // clang-format off
254
+ const char *key_doc = BSON_STR({
255
+ "status" : 1,
256
+ "_id" : {"$binary" : {"base64" : "YWFhYWFhYWFhYWFhYWFhYQ==", "subType" : "04"}},
257
+ "masterKey" : {
258
+ "provider" : "gcp",
259
+ "projectId" : "test",
260
+ "location" : "global",
261
+ "keyRing" : "test",
262
+ "keyName" : "test\r\nFOOBAR: injected"
263
+ },
264
+ "updateDate" : {"$date" : {"$numberLong" : "1557827033449"}},
265
+ "creationDate" : {"$date" : {"$numberLong" : "1557827033449"}},
266
+ "keyMaterial" : {
267
+ "$binary" : {
268
+ "base64" : "PwwOESbKs57YTJtGSCsuAJbv9VWRHjLdPdziUVxH0K9woZUka4SghSwJlw9n6TU/dYHFODvSa4p7bfKzS6U8kGFvOnd7LcPU63IkTek4qZEbGpTRwI5lMT4FFWdpYpUf",
269
+ "subType" : "00"
270
+ }
271
+ }
272
+ });
273
+ // clang-format on
274
+
275
+ crypt = mongocrypt_new();
276
+ ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'gcp': {'accessToken': 'foobar'}}")), crypt);
277
+ ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt);
278
+ ctx = mongocrypt_ctx_new(crypt);
279
+ uuid = mongocrypt_binary_new_from_data((uint8_t *)uuid_data, UUID_LEN);
280
+ ASSERT_OK(mongocrypt_ctx_setopt_key_id(ctx, uuid), ctx);
281
+ ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx);
282
+ ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON("{'v': 1}")), ctx);
283
+
284
+ ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS);
285
+ /* Constructing the KMS request fails. No request is sent. */
286
+ ASSERT_FAILS(mongocrypt_ctx_mongo_feed(ctx, TEST_BSON_STR(key_doc)),
287
+ ctx,
288
+ "Invalid character in GCP KMS key identifier: keyName");
289
+
290
+ mongocrypt_binary_destroy(uuid);
291
+ mongocrypt_ctx_destroy(ctx);
292
+ mongocrypt_destroy(crypt);
293
+ }
294
+
245
295
  void _mongocrypt_tester_install_gcp_auth(_mongocrypt_tester_t *tester) {
296
+ INSTALL_TEST(_test_crlf_in_gcp_masterkey);
246
297
  INSTALL_TEST(_test_createdatakey_with_credentials);
247
298
  INSTALL_TEST(_test_encrypt_with_credentials);
248
299
  INSTALL_TEST(_test_createdatakey_with_accesstoken);
@@ -362,6 +362,119 @@ static void _test_encrypt_init(_mongocrypt_tester_t *tester) {
362
362
  mongocrypt_destroy(crypt);
363
363
  }
364
364
 
365
+ /* Test that a db name containing a dot or an embedded NUL is rejected.
366
+ * A db name like "a.b" would otherwise produce the namespace "a.b.coll",
367
+ * retargeting the operation at database "a" and collection "b.coll".
368
+ * Regression test for MONGOCRYPT-977. */
369
+ static void _test_encrypt_init_invalid_db_collection(_mongocrypt_tester_t *tester) {
370
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
371
+
372
+ {
373
+ /* Dot in db name. */
374
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
375
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "a.b", -1, TEST_FILE("./test/example/cmd.json")),
376
+ ctx,
377
+ "invalid db");
378
+ mongocrypt_ctx_destroy(ctx);
379
+ }
380
+
381
+ {
382
+ /* Embedded NUL in db name. */
383
+ const char db[] = "a\0b";
384
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
385
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, db, 3, TEST_FILE("./test/example/cmd.json")), ctx, "invalid db");
386
+ mongocrypt_ctx_destroy(ctx);
387
+ }
388
+
389
+ {
390
+ /* A dot in a collection name is legal, and must keep working. */
391
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
392
+ ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_BSON("{'find': 'a.b'}")), ctx);
393
+ mongocrypt_ctx_destroy(ctx);
394
+ }
395
+
396
+ {
397
+ /* Embedded NUL in the collection name of the command. */
398
+ bson_t *cmd = bson_new();
399
+ BSON_ASSERT(bson_append_utf8(cmd, "find", -1, "a\0b", 3));
400
+ mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
401
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
402
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
403
+ ctx,
404
+ "collection name must not contain an embedded null byte");
405
+ mongocrypt_ctx_destroy(ctx);
406
+ mongocrypt_binary_destroy(bin);
407
+ bson_destroy(cmd);
408
+ }
409
+
410
+ {
411
+ /* Embedded NUL in the `bulkWrite` nsInfo namespace. */
412
+ bson_t *cmd = bson_new();
413
+ bson_array_builder_t *nsInfo;
414
+ bson_t ns0;
415
+ BSON_ASSERT(BSON_APPEND_INT32(cmd, "bulkWrite", 1));
416
+ BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "nsInfo", &nsInfo));
417
+ BSON_ASSERT(bson_array_builder_append_document_begin(nsInfo, &ns0));
418
+ BSON_ASSERT(bson_append_utf8(&ns0, "ns", -1, "db.coll\0evil", 12));
419
+ BSON_ASSERT(bson_array_builder_append_document_end(nsInfo, &ns0));
420
+ BSON_ASSERT(bson_append_array_builder_end(cmd, nsInfo));
421
+ mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
422
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
423
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin), ctx, "must not contain an embedded null byte");
424
+ mongocrypt_ctx_destroy(ctx);
425
+ mongocrypt_binary_destroy(bin);
426
+ bson_destroy(cmd);
427
+ }
428
+
429
+ {
430
+ /* Embedded NUL in a $lookup 'from' collection name. */
431
+ bson_t *cmd = bson_new();
432
+ bson_array_builder_t *pipeline;
433
+ bson_t stage, lookup;
434
+ BSON_ASSERT(BSON_APPEND_UTF8(cmd, "aggregate", "coll"));
435
+ BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "pipeline", &pipeline));
436
+ BSON_ASSERT(bson_array_builder_append_document_begin(pipeline, &stage));
437
+ BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(&stage, "$lookup", &lookup));
438
+ BSON_ASSERT(bson_append_utf8(&lookup, "from", -1, "a\0b", 3));
439
+ BSON_ASSERT(bson_append_document_end(&stage, &lookup));
440
+ BSON_ASSERT(bson_array_builder_append_document_end(pipeline, &stage));
441
+ BSON_ASSERT(bson_append_array_builder_end(cmd, pipeline));
442
+ mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
443
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
444
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
445
+ ctx,
446
+ "'from' collection name must not contain an embedded null byte");
447
+ mongocrypt_ctx_destroy(ctx);
448
+ mongocrypt_binary_destroy(bin);
449
+ bson_destroy(cmd);
450
+ }
451
+
452
+ {
453
+ /* Embedded NUL in a $unionWith 'coll' collection name. */
454
+ bson_t *cmd = bson_new();
455
+ bson_array_builder_t *pipeline;
456
+ bson_t stage, unionWith;
457
+ BSON_ASSERT(BSON_APPEND_UTF8(cmd, "aggregate", "coll"));
458
+ BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "pipeline", &pipeline));
459
+ BSON_ASSERT(bson_array_builder_append_document_begin(pipeline, &stage));
460
+ BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(&stage, "$unionWith", &unionWith));
461
+ BSON_ASSERT(bson_append_utf8(&unionWith, "coll", -1, "a\0b", 3));
462
+ BSON_ASSERT(bson_append_document_end(&stage, &unionWith));
463
+ BSON_ASSERT(bson_array_builder_append_document_end(pipeline, &stage));
464
+ BSON_ASSERT(bson_append_array_builder_end(cmd, pipeline));
465
+ mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
466
+ mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
467
+ ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
468
+ ctx,
469
+ "'coll' collection name must not contain an embedded null byte");
470
+ mongocrypt_ctx_destroy(ctx);
471
+ mongocrypt_binary_destroy(bin);
472
+ bson_destroy(cmd);
473
+ }
474
+
475
+ mongocrypt_destroy(crypt);
476
+ }
477
+
365
478
  static void _test_encrypt_need_collinfo(_mongocrypt_tester_t *tester) {
366
479
  mongocrypt_t *crypt;
367
480
  mongocrypt_ctx_t *ctx;
@@ -6830,6 +6943,7 @@ static void _test_qe_keyAltName_kms(_mongocrypt_tester_t *tester) {
6830
6943
  void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) {
6831
6944
  INSTALL_TEST(_test_explicit_encrypt_init);
6832
6945
  INSTALL_TEST(_test_encrypt_init);
6946
+ INSTALL_TEST(_test_encrypt_init_invalid_db_collection);
6833
6947
  INSTALL_TEST(_test_encrypt_need_collinfo);
6834
6948
  INSTALL_TEST(_test_encrypt_need_markings);
6835
6949
  INSTALL_TEST(_test_encrypt_csfle_no_needs_markings);
@@ -1,5 +1,5 @@
1
1
  module LibmongocryptHelper
2
- VERSION = '1.20.1.0.1001'
2
+ VERSION = '1.20.3.0.1001'
3
3
 
4
- LIBMONGOCRYPT_VERSION = '1.20.1'
4
+ LIBMONGOCRYPT_VERSION = '1.20.3'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libmongocrypt-helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.20.1.0.1001
4
+ version: 1.20.3.0.1001
5
5
  platform: ruby
6
6
  authors:
7
7
  - The MongoDB Ruby Team
@@ -1250,7 +1250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1250
1250
  - !ruby/object:Gem::Version
1251
1251
  version: '0'
1252
1252
  requirements: []
1253
- rubygems_version: 4.0.17
1253
+ rubygems_version: 4.0.19
1254
1254
  specification_version: 4
1255
1255
  summary: libmongocrypt convenience package
1256
1256
  test_files: []