diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 36018b7efd6..2f93d14474c 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -489,10 +489,10 @@ elseif (NOT ENABLE_CLIENT_SIDE_ENCRYPTION STREQUAL OFF) find_package (mongocrypt QUIET) endif () - if (mongocrypt_FOUND AND "${mongocrypt_VERSION}" VERSION_LESS 1.15.0) + if (mongocrypt_FOUND AND "${mongocrypt_VERSION}" VERSION_LESS 1.15.1) message (STATUS " libmongocrypt found at ${mongocrypt_DIR}") message (STATUS " libmongocrypt version ${mongocrypt_VERSION} found") - message (STATUS " libmongocrypt version 1.15.0 is required to enable In-Use Encryption Support.") + message (STATUS " libmongocrypt version 1.15.1 is required to enable In-Use Encryption Support.") set (REQUIRED_MONGOCRYPT_VERSION_FOUND OFF) elseif (mongocrypt_FOUND) set (REQUIRED_MONGOCRYPT_VERSION_FOUND ON) diff --git a/src/libmongoc/doc/mongoc_client_encryption_encrypt_opts_set_text_opts.rst b/src/libmongoc/doc/mongoc_client_encryption_encrypt_opts_set_text_opts.rst new file mode 100644 index 00000000000..cb282c9c9a2 --- /dev/null +++ b/src/libmongoc/doc/mongoc_client_encryption_encrypt_opts_set_text_opts.rst @@ -0,0 +1,31 @@ +:man_page: mongoc_client_encryption_encrypt_opts_set_text_opts + +mongoc_client_encryption_encrypt_opts_set_text_opts() +==================================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_client_encryption_encrypt_opts_set_text_opts( + mongoc_client_encryption_encrypt_opts_t *opts, + const mongoc_encrypt_text_opts_t *text_opts); + +.. versionadded:: 2.2.0 + +Sets the text search encryption options for explicit encryption. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_client_encryption_encrypt_opts_t`. +* ``text_opts``: A :symbol:`mongoc_encrypt_text_opts_t` specifying text search options. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_t` + | :symbol:`mongoc_encrypt_text_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_prefix` + | :symbol:`mongoc_encrypt_text_opts_set_suffix` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_destroy.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_destroy.rst new file mode 100644 index 00000000000..95ecb84d5c8 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_destroy.rst @@ -0,0 +1,24 @@ +:man_page: mongoc_encrypt_text_opts_destroy + +mongoc_encrypt_text_opts_destroy() +================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_destroy(mongoc_encrypt_text_opts_t *topts); + +.. versionadded:: 2.2.0 + +Frees a :symbol:`mongoc_encrypt_text_opts_t` created with :symbol:`mongoc_encrypt_text_opts_new()`. + +Parameters +---------- + +* ``topts``: A :symbol:`mongoc_encrypt_text_opts_t` to destroy. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_new.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_new.rst new file mode 100644 index 00000000000..1f7c6481ac7 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_new.rst @@ -0,0 +1,25 @@ +:man_page: mongoc_encrypt_text_opts_new + +mongoc_encrypt_text_opts_new() +============================== + +Synopsis +-------- + +.. code-block:: c + + mongoc_encrypt_text_opts_t * + mongoc_encrypt_text_opts_new(void); + +.. versionadded:: 2.2.0 + +Returns +------- + +A new :symbol:`mongoc_encrypt_text_opts_t` that must be freed with :symbol:`mongoc_encrypt_text_opts_destroy()`. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_destroy` + | :symbol:`mongoc_encrypt_text_opts_set_prefix` + | :symbol:`mongoc_encrypt_text_opts_set_suffix` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_set_case_sensitive.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_case_sensitive.rst new file mode 100644 index 00000000000..2c36fb68606 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_case_sensitive.rst @@ -0,0 +1,27 @@ +:man_page: mongoc_encrypt_text_opts_set_case_sensitive + +mongoc_encrypt_text_opts_set_case_sensitive() +============================================ + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_set_case_sensitive( + mongoc_encrypt_text_opts_t *opts, + bool case_sensitive); + +.. versionadded:: 2.2.0 + +Sets whether text search is case sensitive. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_opts_t`. +* ``case_sensitive``: If true, text search is case sensitive. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_t` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_set_diacritic_sensitive.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_diacritic_sensitive.rst new file mode 100644 index 00000000000..d9a7ca814f8 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_diacritic_sensitive.rst @@ -0,0 +1,27 @@ +:man_page: mongoc_encrypt_text_opts_set_diacritic_sensitive + +mongoc_encrypt_text_opts_set_diacritic_sensitive() +================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_set_diacritic_sensitive( + mongoc_encrypt_text_opts_t *opts, + bool diacritic_sensitive); + +.. versionadded:: 2.2.0 + +Sets whether text search is diacritic sensitive. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_opts_t`. +* ``diacritic_sensitive``: If true, text search is diacritic sensitive. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_t` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_set_prefix.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_prefix.rst new file mode 100644 index 00000000000..c1423a6bf68 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_prefix.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_opts_set_prefix + +mongoc_encrypt_text_opts_set_prefix() +===================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_set_prefix( + mongoc_encrypt_text_opts_t *opts, + mongoc_encrypt_text_prefix_opts_t *popts); + +.. versionadded:: 2.2.0 + +Sets the prefix options for text search encryption. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_opts_t`. +* ``popts``: A :symbol:`mongoc_encrypt_text_prefix_opts_t` to set as prefix options. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_new` + | :symbol:`mongoc_encrypt_text_prefix_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_set_substring.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_substring.rst new file mode 100644 index 00000000000..c81e6af0efa --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_substring.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_opts_set_substring + +mongoc_encrypt_text_opts_set_substring() +======================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_set_substring( + mongoc_encrypt_text_opts_t *opts, + mongoc_encrypt_text_substring_opts_t *ssopts); + +.. versionadded:: 2.2.0 + +Sets the substring options for text search encryption. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_opts_t`. +* ``ssopts``: A :symbol:`mongoc_encrypt_text_substring_opts_t` to set as substring options. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_new` + | :symbol:`mongoc_encrypt_text_substring_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_set_suffix.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_suffix.rst new file mode 100644 index 00000000000..3d6c5aa625e --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_set_suffix.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_opts_set_suffix + +mongoc_encrypt_text_opts_set_suffix() +===================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_opts_set_suffix( + mongoc_encrypt_text_opts_t *opts, + mongoc_encrypt_text_suffix_opts_t *sopts); + +.. versionadded:: 2.2.0 + +Sets the suffix options for text search encryption. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_opts_t`. +* ``sopts``: A :symbol:`mongoc_encrypt_text_suffix_opts_t` to set as suffix options. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_opts_new` + | :symbol:`mongoc_encrypt_text_suffix_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_opts_t.rst b/src/libmongoc/doc/mongoc_encrypt_text_opts_t.rst new file mode 100644 index 00000000000..1f89f2b513d --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_opts_t.rst @@ -0,0 +1,53 @@ +:man_page: mongoc_encrypt_text_opts_t + +mongoc_encrypt_text_opts_t +============================================= + +Synopsis +-------- + +.. code-block:: c + + typedef struct _mongoc_encrypt_text_opts_t mongoc_encrypt_text_opts_t; + +.. versionadded:: 2.2.0 + +TextOpts specifies index options for a Queryable Encryption field supporting "textPreview" queries. Used to set options for :symbol:`mongoc_client_encryption_encrypt()`. + +Case sensitive and diacritic sensitive must be set. If prefix or suffix are set, substring must not be set. + +.. only:: html + + Functions + --------- + + .. toctree:: + :titlesonly: + :maxdepth: 1 + + mongoc_encrypt_text_opts_new + mongoc_encrypt_text_opts_destroy + mongoc_encrypt_text_opts_set_case_sensitive + mongoc_encrypt_text_opts_set_diacritic_sensitive + mongoc_encrypt_text_opts_set_prefix + mongoc_encrypt_text_opts_set_suffix + mongoc_encrypt_text_opts_set_substring + mongoc_encrypt_text_prefix_opts_new + mongoc_encrypt_text_prefix_opts_destroy + mongoc_encrypt_text_prefix_opts_set_str_max_query_length + mongoc_encrypt_text_prefix_opts_set_str_min_query_length + mongoc_encrypt_text_suffix_opts_new + mongoc_encrypt_text_suffix_opts_destroy + mongoc_encrypt_text_suffix_opts_set_str_max_query_length + mongoc_encrypt_text_suffix_opts_set_str_min_query_length + mongoc_encrypt_text_substring_opts_new + mongoc_encrypt_text_substring_opts_destroy + mongoc_encrypt_text_substring_opts_set_str_max_length + mongoc_encrypt_text_substring_opts_set_str_max_query_length + mongoc_encrypt_text_substring_opts_set_str_min_query_length + mongoc_client_encryption_encrypt_opts_set_text_opts + +.. seealso:: + + | :symbol:`mongoc_client_encryption_encrypt()` + | :symbol:`mongoc_client_encryption_encrypt_opts_t()` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_destroy.rst b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_destroy.rst new file mode 100644 index 00000000000..51b88834e59 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_destroy.rst @@ -0,0 +1,24 @@ +:man_page: mongoc_encrypt_text_prefix_opts_destroy + +mongoc_encrypt_text_prefix_opts_destroy() +======================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_prefix_opts_destroy(mongoc_encrypt_text_prefix_opts_t *opts); + +.. versionadded:: 2.2.0 + +Frees a :symbol:`mongoc_encrypt_text_prefix_opts_t` created with :symbol:`mongoc_encrypt_text_prefix_opts_new()`. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_prefix_opts_t` to destroy. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_prefix_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_max_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_max_query_length.rst new file mode 100644 index 00000000000..6447ffac66e --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_max_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_prefix_opts_set_str_max_query_length + +mongoc_encrypt_text_prefix_opts_set_str_max_query_length() +========================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_prefix_opts_set_str_max_query_length( + mongoc_encrypt_text_prefix_opts_t *opts, + int32_t str_max_query_length); + +.. versionadded:: 2.2.0 + +Sets the maximum query length for prefix text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_prefix_opts_t`. +* ``str_max_query_length``: The maximum query length for prefix search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_prefix_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_prefix` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_min_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_min_query_length.rst new file mode 100644 index 00000000000..bb2df423b5e --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_prefix_opts_set_str_min_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_prefix_opts_set_str_min_query_length + +mongoc_encrypt_text_prefix_opts_set_str_min_query_length() +========================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_prefix_opts_set_str_min_query_length( + mongoc_encrypt_text_prefix_opts_t *opts, + int32_t str_min_query_length); + +.. versionadded:: 2.2.0 + +Sets the minimum query length for prefix text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_prefix_opts_t`. +* ``str_min_query_length``: The minimum query length for prefix search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_prefix_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_prefix` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_destroy.rst b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_destroy.rst new file mode 100644 index 00000000000..98959852fc3 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_destroy.rst @@ -0,0 +1,24 @@ +:man_page: mongoc_encrypt_text_substring_opts_destroy + +mongoc_encrypt_text_substring_opts_destroy() +============================================ + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_substring_opts_destroy(mongoc_encrypt_text_substring_opts_t *opts); + +.. versionadded:: 2.2.0 + +Frees a :symbol:`mongoc_encrypt_text_substring_opts_t` created with :symbol:`mongoc_encrypt_text_substring_opts_new()`. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_substring_opts_t` to destroy. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_substring_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_new.rst b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_new.rst new file mode 100644 index 00000000000..31852f9f416 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_new.rst @@ -0,0 +1,23 @@ +:man_page: mongoc_encrypt_text_substring_opts_new + +mongoc_encrypt_text_substring_opts_new() +======================================= + +Synopsis +-------- + +.. code-block:: c + + mongoc_encrypt_text_substring_opts_t * + mongoc_encrypt_text_substring_opts_new(void); + +.. versionadded:: 2.2.0 + +Returns +------- + +A new :symbol:`mongoc_encrypt_text_substring_opts_t` that must be freed with :symbol:`mongoc_encrypt_text_substring_opts_destroy()`. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_substring_opts_destroy` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_length.rst new file mode 100644 index 00000000000..45b6b2198d3 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_substring_opts_set_str_max_length + +mongoc_encrypt_text_substring_opts_set_str_max_length() +======================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_substring_opts_set_str_max_length( + mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_max_length); + +.. versionadded:: 2.2.0 + +Sets the maximum string length for substring text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_substring_opts_t`. +* ``str_max_length``: The maximum string length for substring search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_substring_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_query_length.rst new file mode 100644 index 00000000000..9ad2478bacf --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_max_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_substring_opts_set_str_max_query_length + +mongoc_encrypt_text_substring_opts_set_str_max_query_length() +============================================================ + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_substring_opts_set_str_max_query_length( + mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_max_query_length); + +.. versionadded:: 2.2.0 + +Sets the maximum query length for substring text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_substring_opts_t`. +* ``str_max_query_length``: The maximum query length for substring search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_substring_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_min_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_min_query_length.rst new file mode 100644 index 00000000000..cbbc66a86fd --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_substring_opts_set_str_min_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_substring_opts_set_str_min_query_length + +mongoc_encrypt_text_substring_opts_set_str_min_query_length() +============================================================ + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_substring_opts_set_str_min_query_length( + mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_min_query_length); + +.. versionadded:: 2.2.0 + +Sets the minimum query length for substring text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_substring_opts_t`. +* ``str_min_query_length``: The minimum query length for substring search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_substring_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_substring` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_destroy.rst b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_destroy.rst new file mode 100644 index 00000000000..369fd3b0db8 --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_destroy.rst @@ -0,0 +1,24 @@ +:man_page: mongoc_encrypt_text_suffix_opts_destroy + +mongoc_encrypt_text_suffix_opts_destroy() +======================================== + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_suffix_opts_destroy(mongoc_encrypt_text_suffix_opts_t *opts); + +.. versionadded:: 2.2.0 + +Frees a :symbol:`mongoc_encrypt_text_suffix_opts_t` created with :symbol:`mongoc_encrypt_text_suffix_opts_new()`. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_suffix_opts_t` to destroy. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_suffix_opts_new` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_new.rst b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_new.rst new file mode 100644 index 00000000000..2b4dab5364e --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_new.rst @@ -0,0 +1,23 @@ +:man_page: mongoc_encrypt_text_suffix_opts_new + +mongoc_encrypt_text_suffix_opts_new() +==================================== + +Synopsis +-------- + +.. code-block:: c + + mongoc_encrypt_text_suffix_opts_t * + mongoc_encrypt_text_suffix_opts_new(void); + +.. versionadded:: 2.2.0 + +Returns +------- + +A new :symbol:`mongoc_encrypt_text_suffix_opts_t` that must be freed with :symbol:`mongoc_encrypt_text_suffix_opts_destroy()`. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_suffix_opts_destroy` + | :symbol:`mongoc_encrypt_text_opts_set_suffix` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_max_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_max_query_length.rst new file mode 100644 index 00000000000..1decfe28d4f --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_max_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_suffix_opts_set_str_max_query_length + +mongoc_encrypt_text_suffix_opts_set_str_max_query_length() +========================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_suffix_opts_set_str_max_query_length( + mongoc_encrypt_text_suffix_opts_t *opts, + int32_t str_max_query_length); + +.. versionadded:: 2.2.0 + +Sets the maximum query length for suffix text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_suffix_opts_t`. +* ``str_max_query_length``: The maximum query length for suffix search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_suffix_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_suffix` diff --git a/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_min_query_length.rst b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_min_query_length.rst new file mode 100644 index 00000000000..945dfeeadbd --- /dev/null +++ b/src/libmongoc/doc/mongoc_encrypt_text_suffix_opts_set_str_min_query_length.rst @@ -0,0 +1,28 @@ +:man_page: mongoc_encrypt_text_suffix_opts_set_str_min_query_length + +mongoc_encrypt_text_suffix_opts_set_str_min_query_length() +========================================================= + +Synopsis +-------- + +.. code-block:: c + + void + mongoc_encrypt_text_suffix_opts_set_str_min_query_length( + mongoc_encrypt_text_suffix_opts_t *opts, + int32_t str_min_query_length); + +.. versionadded:: 2.2.0 + +Sets the minimum query length for suffix text search encryption options. + +Parameters +---------- + +* ``opts``: A :symbol:`mongoc_encrypt_text_suffix_opts_t`. +* ``str_min_query_length``: The minimum query length for suffix search. Must be greater than zero. + +.. seealso:: + | :symbol:`mongoc_encrypt_text_suffix_opts_new` + | :symbol:`mongoc_encrypt_text_opts_set_suffix` diff --git a/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c b/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c index 27f5b145daa..b0beae6911f 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c +++ b/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #ifndef _WIN32 #include @@ -462,6 +463,31 @@ struct _mongoc_client_encryption_encrypt_range_opts_t { } precision; }; +typedef struct { + bool set; + int32_t value; +} mc_optional_int32_t; + +typedef struct { + bool set; + bool value; +} mc_optional_bool; + +struct _encrypt_text_per_index_opts_t { + mc_optional_int32_t str_max_length; + mc_optional_int32_t str_max_query_length; + mc_optional_int32_t str_min_query_length; +}; + +struct _mongoc_encrypt_text_opts_t { + mc_optional_bool case_sensitive; + mc_optional_bool diacritic_sensitive; + + mongoc_encrypt_text_substring_opts_t *substring; + mongoc_encrypt_text_prefix_opts_t *prefix; + mongoc_encrypt_text_suffix_opts_t *suffix; +}; + struct _mongoc_client_encryption_encrypt_opts_t { bson_value_t keyid; char *algorithm; @@ -472,6 +498,7 @@ struct _mongoc_client_encryption_encrypt_opts_t { } contention_factor; char *query_type; mongoc_client_encryption_encrypt_range_opts_t *range_opts; + mongoc_encrypt_text_opts_t *text_opts; }; mongoc_client_encryption_encrypt_opts_t * @@ -480,6 +507,146 @@ mongoc_client_encryption_encrypt_opts_new(void) return bson_malloc0(sizeof(mongoc_client_encryption_encrypt_opts_t)); } +mongoc_encrypt_text_prefix_opts_t * +mongoc_encrypt_text_prefix_opts_new(void) +{ + return bson_malloc0(sizeof(mongoc_encrypt_text_prefix_opts_t)); +} + +void +mongoc_encrypt_text_prefix_opts_destroy(mongoc_encrypt_text_prefix_opts_t *opts) +{ + bson_free(opts); +} + +void +mongoc_encrypt_text_prefix_opts_set_str_max_query_length(mongoc_encrypt_text_prefix_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_max_query_length.set = true; + opts->str_max_query_length.value = val; +} + +void +mongoc_encrypt_text_prefix_opts_set_str_min_query_length(mongoc_encrypt_text_prefix_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_min_query_length.set = true; + opts->str_min_query_length.value = val; +} + +// Suffix opts +mongoc_encrypt_text_suffix_opts_t * +mongoc_encrypt_text_suffix_opts_new(void) +{ + return bson_malloc0(sizeof(mongoc_encrypt_text_suffix_opts_t)); +} + +void +mongoc_encrypt_text_suffix_opts_destroy(mongoc_encrypt_text_suffix_opts_t *opts) +{ + bson_free(opts); +} + +void +mongoc_encrypt_text_suffix_opts_set_str_max_query_length(mongoc_encrypt_text_suffix_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_max_query_length.set = true; + opts->str_max_query_length.value = val; +} + +void +mongoc_encrypt_text_suffix_opts_set_str_min_query_length(mongoc_encrypt_text_suffix_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_min_query_length.set = true; + opts->str_min_query_length.value = val; +} + +// Substring opts +mongoc_encrypt_text_substring_opts_t * +mongoc_encrypt_text_substring_opts_new(void) +{ + return bson_malloc0(sizeof(mongoc_encrypt_text_substring_opts_t)); +} + +void +mongoc_encrypt_text_substring_opts_destroy(mongoc_encrypt_text_substring_opts_t *opts) +{ + bson_free(opts); +} + +void +mongoc_encrypt_text_substring_opts_set_str_max_length(mongoc_encrypt_text_substring_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_max_length.set = true; + opts->str_max_length.value = val; +} + +void +mongoc_encrypt_text_substring_opts_set_str_max_query_length(mongoc_encrypt_text_substring_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_max_query_length.set = true; + opts->str_max_query_length.value = val; +} + +void +mongoc_encrypt_text_substring_opts_set_str_min_query_length(mongoc_encrypt_text_substring_opts_t *opts, int32_t val) +{ + BSON_ASSERT_PARAM(opts); + opts->str_min_query_length.set = true; + opts->str_min_query_length.value = val; +} + +// Setters for text opts +void +mongoc_encrypt_text_opts_set_prefix(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_prefix_opts_t *popts) +{ + BSON_ASSERT_PARAM(opts); + BSON_ASSERT_PARAM(popts); + opts->prefix = mongoc_encrypt_text_prefix_opts_new(); + *opts->prefix = *popts; +} + +void +mongoc_encrypt_text_opts_set_suffix(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_suffix_opts_t *sopts) +{ + BSON_ASSERT_PARAM(opts); + BSON_ASSERT_PARAM(sopts); + opts->suffix = mongoc_encrypt_text_suffix_opts_new(); + *opts->suffix = *sopts; +} + +void +mongoc_encrypt_text_opts_set_substring(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_substring_opts_t *ssopts) +{ + BSON_ASSERT_PARAM(opts); + BSON_ASSERT_PARAM(ssopts); + opts->substring = mongoc_encrypt_text_substring_opts_new(); + *opts->substring = *ssopts; +} + +mongoc_encrypt_text_opts_t * +mongoc_encrypt_text_opts_new(void) +{ + return bson_malloc0(sizeof(mongoc_encrypt_text_opts_t)); +} + +void +mongoc_encrypt_text_opts_destroy(mongoc_encrypt_text_opts_t *topts) +{ + if (!topts) { + return; + } + mongoc_encrypt_text_prefix_opts_destroy(topts->prefix); + mongoc_encrypt_text_suffix_opts_destroy(topts->suffix); + mongoc_encrypt_text_substring_opts_destroy(topts->substring); + bson_free(topts); +} + void mongoc_client_encryption_encrypt_range_opts_destroy(mongoc_client_encryption_encrypt_range_opts_t *range_opts) { @@ -503,6 +670,7 @@ mongoc_client_encryption_encrypt_opts_destroy(mongoc_client_encryption_encrypt_o return; } mongoc_client_encryption_encrypt_range_opts_destroy(opts->range_opts); + mongoc_encrypt_text_opts_destroy(opts->text_opts); bson_value_destroy(&opts->keyid); bson_free(opts->algorithm); bson_free(opts->keyaltname); @@ -671,6 +839,48 @@ mongoc_client_encryption_encrypt_opts_set_range_opts(mongoc_client_encryption_en opts->range_opts = copy_range_opts(range_opts); } +/*-------------------------------------------------------------------------- + * Explicit Encryption TextPreview Options + *-------------------------------------------------------------------------- + */ +void +mongoc_client_encryption_encrypt_opts_set_text_opts(mongoc_client_encryption_encrypt_opts_t *opts, + const mongoc_encrypt_text_opts_t *text_opts) +{ + BSON_ASSERT_PARAM(opts); + mongoc_encrypt_text_opts_t *t = mongoc_encrypt_text_opts_new(); + *t = *text_opts; + if (text_opts->substring) { + t->substring = mongoc_encrypt_text_substring_opts_new(); + *t->substring = *text_opts->substring; + } + if (text_opts->prefix) { + t->prefix = mongoc_encrypt_text_prefix_opts_new(); + *t->prefix = *text_opts->prefix; + } + if (text_opts->suffix) { + t->suffix = mongoc_encrypt_text_suffix_opts_new(); + *t->suffix = *text_opts->suffix; + } + opts->text_opts = t; +} + +void +mongoc_encrypt_text_opts_set_case_sensitive(mongoc_encrypt_text_opts_t *opts, bool case_sensitive) +{ + BSON_ASSERT_PARAM(opts); + opts->case_sensitive.set = true; + opts->case_sensitive.value = case_sensitive; +} + +void +mongoc_encrypt_text_opts_set_diacritic_sensitive(mongoc_encrypt_text_opts_t *opts, bool diacritic_sensitive) +{ + BSON_ASSERT_PARAM(opts); + opts->diacritic_sensitive.set = true; + opts->diacritic_sensitive.value = diacritic_sensitive; +} + /*-------------------------------------------------------------------------- * RewrapManyDataKeyResult. *-------------------------------------------------------------------------- @@ -1038,6 +1248,54 @@ append_bson_range_opts(bson_t *bson_range_opts, const mongoc_client_encryption_e } } +static void +append_bson_text_per_index_opts(bson_t *out, const struct _encrypt_text_per_index_opts_t *opts) +{ + BSON_ASSERT_PARAM(out); + if (opts->str_max_length.set) { + BSON_ASSERT(bson_append_int32(out, "strMaxLength", -1, opts->str_max_length.value)); + } + if (opts->str_max_query_length.set) { + BSON_ASSERT(bson_append_int32(out, "strMaxQueryLength", -1, opts->str_max_query_length.value)); + } + if (opts->str_min_query_length.set) { + BSON_ASSERT(bson_append_int32(out, "strMinQueryLength", -1, opts->str_min_query_length.value)); + } +} + +static void +append_bson_text_opts(bson_t *bson_text_opts, const mongoc_encrypt_text_opts_t *opts) +{ + BSON_ASSERT_PARAM(bson_text_opts); + BSON_ASSERT_PARAM(opts); + + if (opts->case_sensitive.set) { + BSON_ASSERT(BSON_APPEND_BOOL(bson_text_opts, "caseSensitive", opts->case_sensitive.value)); + } + if (opts->diacritic_sensitive.set) { + BSON_ASSERT(BSON_APPEND_BOOL(bson_text_opts, "diacriticSensitive", opts->diacritic_sensitive.value)); + } + + if (opts->prefix) { + bson_t per_index_spec; + BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(bson_text_opts, "prefix", &per_index_spec)); + append_bson_text_per_index_opts(&per_index_spec, opts->prefix); + BSON_ASSERT(bson_append_document_end(bson_text_opts, &per_index_spec)); + } + if (opts->suffix) { + bson_t per_index_spec; + BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(bson_text_opts, "suffix", &per_index_spec)); + append_bson_text_per_index_opts(&per_index_spec, opts->suffix); + BSON_ASSERT(bson_append_document_end(bson_text_opts, &per_index_spec)); + } + if (opts->substring) { + bson_t per_index_spec; + BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(bson_text_opts, "substring", &per_index_spec)); + append_bson_text_per_index_opts(&per_index_spec, opts->substring); + BSON_ASSERT(bson_append_document_end(bson_text_opts, &per_index_spec)); + } +} + /*-------------------------------------------------------------------------- * * _prep_for_auto_encryption -- @@ -2641,7 +2899,7 @@ mongoc_client_encryption_encrypt(mongoc_client_encryption_t *client_encryption, bson_error_t *error) { bool ret = false; - bson_t *range_opts = NULL; + bson_t *range_opts = NULL, *text_opts = NULL; ENTRY; @@ -2667,6 +2925,11 @@ mongoc_client_encryption_encrypt(mongoc_client_encryption_t *client_encryption, append_bson_range_opts(range_opts, opts); } + if (opts->text_opts) { + text_opts = bson_new(); + append_bson_text_opts(text_opts, opts->text_opts); + } + if (!_mongoc_crypt_explicit_encrypt(client_encryption->crypt, client_encryption->keyvault_coll, opts->algorithm, @@ -2675,6 +2938,7 @@ mongoc_client_encryption_encrypt(mongoc_client_encryption_t *client_encryption, opts->query_type, opts->contention_factor.set ? &opts->contention_factor.value : NULL, range_opts, + text_opts, value, ciphertext, error)) { @@ -2683,6 +2947,7 @@ mongoc_client_encryption_encrypt(mongoc_client_encryption_t *client_encryption, ret = true; fail: + bson_destroy(text_opts); bson_destroy(range_opts); RETURN(ret); } @@ -2711,6 +2976,12 @@ mongoc_client_encryption_encrypt_expression(mongoc_client_encryption_t *client_e append_bson_range_opts(range_opts, opts); } + bson_t *text_opts = NULL; + if (opts->text_opts) { + text_opts = bson_new(); + append_bson_text_opts(text_opts, opts->text_opts); + } + if (!_mongoc_crypt_explicit_encrypt_expression(client_encryption->crypt, client_encryption->keyvault_coll, opts->algorithm, @@ -2719,6 +2990,7 @@ mongoc_client_encryption_encrypt_expression(mongoc_client_encryption_t *client_e opts->query_type, opts->contention_factor.set ? &opts->contention_factor.value : NULL, range_opts, + text_opts, expr, expr_out, error)) { diff --git a/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h b/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h index b0ace91023f..6181441bebf 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h +++ b/src/libmongoc/src/mongoc/mongoc-client-side-encryption.h @@ -37,10 +37,14 @@ struct _mongoc_database_t; #define MONGOC_ENCRYPT_ALGORITHM_UNINDEXED "Unindexed" #define MONGOC_ENCRYPT_ALGORITHM_RANGE "Range" #define MONGOC_ENCRYPT_ALGORITHM_RANGEPREVIEW "RangePreview" +#define MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW "TextPreview" #define MONGOC_ENCRYPT_QUERY_TYPE_EQUALITY "equality" #define MONGOC_ENCRYPT_QUERY_TYPE_RANGE "range" #define MONGOC_ENCRYPT_QUERY_TYPE_RANGEPREVIEW "rangePreview" +#define MONGOC_ENCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW "substringPreview" +#define MONGOC_ENCRYPT_QUERY_TYPE_PREFIXPREVIEW "prefixPreview" +#define MONGOC_ENCRYPT_QUERY_TYPE_SUFFIXPREVIEW "suffixPreview" BSON_BEGIN_DECLS @@ -104,6 +108,10 @@ mongoc_auto_encryption_opts_set_kms_credential_provider_callback(mongoc_auto_enc typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t; typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t; typedef struct _mongoc_client_encryption_encrypt_range_opts_t mongoc_client_encryption_encrypt_range_opts_t; +typedef struct _encrypt_text_per_index_opts_t mongoc_encrypt_text_prefix_opts_t; +typedef struct _encrypt_text_per_index_opts_t mongoc_encrypt_text_suffix_opts_t; +typedef struct _encrypt_text_per_index_opts_t mongoc_encrypt_text_substring_opts_t; +typedef struct _mongoc_encrypt_text_opts_t mongoc_encrypt_text_opts_t; typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t; typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t; typedef struct _mongoc_client_encryption_rewrap_many_datakey_result_t @@ -182,6 +190,67 @@ mongoc_client_encryption_get_key(mongoc_client_encryption_t *client_encryption, bson_t *key_doc, bson_error_t *error); +MONGOC_EXPORT(mongoc_encrypt_text_prefix_opts_t *) +mongoc_encrypt_text_prefix_opts_new(void); + +MONGOC_EXPORT(mongoc_encrypt_text_suffix_opts_t *) +mongoc_encrypt_text_suffix_opts_new(void); + +MONGOC_EXPORT(mongoc_encrypt_text_substring_opts_t *) +mongoc_encrypt_text_substring_opts_new(void); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_prefix_opts_destroy(mongoc_encrypt_text_prefix_opts_t *); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_suffix_opts_destroy(mongoc_encrypt_text_suffix_opts_t *); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_substring_opts_destroy(mongoc_encrypt_text_substring_opts_t *); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_prefix_opts_set_str_max_query_length(mongoc_encrypt_text_prefix_opts_t *opts, + int32_t str_max_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_prefix_opts_set_str_min_query_length(mongoc_encrypt_text_prefix_opts_t *opts, + int32_t str_min_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_suffix_opts_set_str_max_query_length(mongoc_encrypt_text_suffix_opts_t *opts, + int32_t str_max_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_suffix_opts_set_str_min_query_length(mongoc_encrypt_text_suffix_opts_t *opts, + int32_t str_min_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_substring_opts_set_str_max_length(mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_max_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_substring_opts_set_str_max_query_length(mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_max_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_substring_opts_set_str_min_query_length(mongoc_encrypt_text_substring_opts_t *opts, + int32_t str_min_query_length); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_set_prefix(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_prefix_opts_t *popts); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_set_suffix(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_suffix_opts_t *sopts); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_set_substring(mongoc_encrypt_text_opts_t *opts, mongoc_encrypt_text_substring_opts_t *ssopts); + +MONGOC_EXPORT(mongoc_encrypt_text_opts_t *) +mongoc_encrypt_text_opts_new(void); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_destroy(mongoc_encrypt_text_opts_t *topts); + MONGOC_EXPORT(struct _mongoc_cursor_t *) mongoc_client_encryption_get_keys(mongoc_client_encryption_t *client_encryption, bson_error_t *error); @@ -247,6 +316,16 @@ MONGOC_EXPORT(void) mongoc_client_encryption_encrypt_opts_set_contention_factor(mongoc_client_encryption_encrypt_opts_t *opts, int64_t contention_factor); +MONGOC_EXPORT(void) +mongoc_client_encryption_encrypt_opts_set_text_opts(mongoc_client_encryption_encrypt_opts_t *opts, + const mongoc_encrypt_text_opts_t *text_opts); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_set_case_sensitive(mongoc_encrypt_text_opts_t *opts, bool case_sensitive); + +MONGOC_EXPORT(void) +mongoc_encrypt_text_opts_set_diacritic_sensitive(mongoc_encrypt_text_opts_t *opts, bool diacritic_sensitive); + MONGOC_EXPORT(void) mongoc_client_encryption_encrypt_opts_set_query_type(mongoc_client_encryption_encrypt_opts_t *opts, const char *query_type); diff --git a/src/libmongoc/src/mongoc/mongoc-crypt-private.h b/src/libmongoc/src/mongoc/mongoc-crypt-private.h index d17a2c18f4f..e1f9b2e400b 100644 --- a/src/libmongoc/src/mongoc/mongoc-crypt-private.h +++ b/src/libmongoc/src/mongoc/mongoc-crypt-private.h @@ -99,6 +99,7 @@ _mongoc_crypt_explicit_encrypt(_mongoc_crypt_t *crypt, const char *query_type /* may be NULL */, const int64_t *contention_factor /* may be NULL */, const bson_t *range_opts /* may be NULL */, + const bson_t *text_opts /* may be NULL */, const bson_value_t *value_in, bson_value_t *value_out, bson_error_t *error); @@ -116,6 +117,7 @@ _mongoc_crypt_explicit_encrypt_expression(_mongoc_crypt_t *crypt, const char *query_type /* may be NULL */, const int64_t *contention_factor /* may be NULL */, const bson_t *range_opts /* may be NULL */, + const bson_t *text_opts /* may be NULL */, const bson_t *expr_in, bson_t *expr_out, bson_error_t *error); diff --git a/src/libmongoc/src/mongoc/mongoc-crypt.c b/src/libmongoc/src/mongoc/mongoc-crypt.c index 183badb41e0..d85b99125f4 100644 --- a/src/libmongoc/src/mongoc/mongoc-crypt.c +++ b/src/libmongoc/src/mongoc/mongoc-crypt.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #define MONGOC_LOG_DOMAIN "client-side-encryption" #include @@ -1643,6 +1644,7 @@ _create_explicit_state_machine(_mongoc_crypt_t *crypt, const char *query_type, const int64_t *contention_factor, const bson_t *range_opts, + const bson_t *text_opts, bson_error_t *error) { BSON_ASSERT_PARAM(crypt); @@ -1652,6 +1654,7 @@ _create_explicit_state_machine(_mongoc_crypt_t *crypt, BSON_OPTIONAL_PARAM(keyaltname); BSON_OPTIONAL_PARAM(query_type); BSON_OPTIONAL_PARAM(range_opts); + BSON_OPTIONAL_PARAM(text_opts); BSON_OPTIONAL_PARAM(error); _state_machine_t *state_machine = NULL; @@ -1683,6 +1686,18 @@ _create_explicit_state_machine(_mongoc_crypt_t *crypt, mongocrypt_binary_destroy(binary_range_opts); } + if (text_opts != NULL) { + /* mongocrypt error checks and parses text options */ + mongocrypt_binary_t *binary_text_opts = + mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(text_opts), text_opts->len); + if (!mongocrypt_ctx_setopt_algorithm_text(state_machine->ctx, binary_text_opts)) { + mongocrypt_binary_destroy(binary_text_opts); + _ctx_check_error(state_machine->ctx, error, true); + goto fail; + } + mongocrypt_binary_destroy(binary_text_opts); + } + if (query_type != NULL) { if (!mongocrypt_ctx_setopt_query_type(state_machine->ctx, query_type, -1)) { goto fail; @@ -1749,6 +1764,7 @@ _mongoc_crypt_explicit_encrypt(_mongoc_crypt_t *crypt, const char *query_type, const int64_t *contention_factor, const bson_t *range_opts, + const bson_t *text_opts, const bson_value_t *value_in, bson_value_t *value_out, bson_error_t *error) @@ -1774,7 +1790,7 @@ _mongoc_crypt_explicit_encrypt(_mongoc_crypt_t *crypt, value_out->value_type = BSON_TYPE_EOD; state_machine = _create_explicit_state_machine( - crypt, keyvault_coll, algorithm, keyid, keyaltname, query_type, contention_factor, range_opts, error); + crypt, keyvault_coll, algorithm, keyid, keyaltname, query_type, contention_factor, range_opts, text_opts, error); if (!state_machine) { goto fail; } @@ -1824,6 +1840,7 @@ _mongoc_crypt_explicit_encrypt_expression(_mongoc_crypt_t *crypt, const char *query_type, const int64_t *contention_factor, const bson_t *range_opts, + const bson_t *text_opts, const bson_t *expr_in, bson_t *expr_out, bson_error_t *error) @@ -1835,6 +1852,7 @@ _mongoc_crypt_explicit_encrypt_expression(_mongoc_crypt_t *crypt, BSON_OPTIONAL_PARAM(keyaltname); BSON_OPTIONAL_PARAM(query_type); BSON_OPTIONAL_PARAM(range_opts); + BSON_OPTIONAL_PARAM(text_opts); BSON_ASSERT_PARAM(expr_in); BSON_ASSERT_PARAM(expr_out); BSON_OPTIONAL_PARAM(error); @@ -1849,7 +1867,7 @@ _mongoc_crypt_explicit_encrypt_expression(_mongoc_crypt_t *crypt, bson_init(expr_out); state_machine = _create_explicit_state_machine( - crypt, keyvault_coll, algorithm, keyid, keyaltname, query_type, contention_factor, range_opts, error); + crypt, keyvault_coll, algorithm, keyid, keyaltname, query_type, contention_factor, range_opts, text_opts, error); if (!state_machine) { goto fail; } diff --git a/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-prefix-suffix.json b/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-prefix-suffix.json new file mode 100644 index 00000000000..ec4489fa09b --- /dev/null +++ b/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-prefix-suffix.json @@ -0,0 +1,38 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "prefixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + }, + { + "queryType": "suffixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] +} diff --git a/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-substring.json b/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-substring.json new file mode 100644 index 00000000000..ee22def77b8 --- /dev/null +++ b/src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/encryptedFields-substring.json @@ -0,0 +1,30 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "substringPreview", + "strMaxLength": { + "$numberInt": "10" + }, + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json-test.c b/src/libmongoc/tests/json-test.c index 22e0953e891..dadb8d49163 100644 --- a/src/libmongoc/tests/json-test.c +++ b/src/libmongoc/tests/json-test.c @@ -654,7 +654,7 @@ collect_tests_from_dir(char (*paths)[MAX_TEST_NAME_LENGTH] /* OUT */, *----------------------------------------------------------------------- */ bson_t * -get_bson_from_json_file(char *filename) +get_bson_from_json_file(const char *filename) { FILE *const file = fopen(filename, "rb"); if (!file) { diff --git a/src/libmongoc/tests/json-test.h b/src/libmongoc/tests/json-test.h index ac9b2fa7b33..0c4424915e9 100644 --- a/src/libmongoc/tests/json-test.h +++ b/src/libmongoc/tests/json-test.h @@ -54,7 +54,7 @@ typedef struct _json_test_config_t { #define JSON_TEST_CONFIG_INIT {NULL, NULL, NULL, NULL, NULL, NULL, false, false, NULL, NULL} bson_t * -get_bson_from_json_file(char *filename); +get_bson_from_json_file(const char *filename); int collect_tests_from_dir(char (*paths)[MAX_TEST_NAME_LENGTH] /* OUT */, diff --git a/src/libmongoc/tests/test-libmongoc.c b/src/libmongoc/tests/test-libmongoc.c index 0c622efbc1b..a0b188d5e7a 100644 --- a/src/libmongoc/tests/test-libmongoc.c +++ b/src/libmongoc/tests/test-libmongoc.c @@ -2268,6 +2268,8 @@ WIRE_VERSION_CHECKS(24) WIRE_VERSION_CHECKS(25) /* wire version 26 begins with the 8.1 release. */ WIRE_VERSION_CHECKS(26) +/* wire version 27 begins with the 8.2 release. */ +WIRE_VERSION_CHECKS(27) int test_framework_skip_if_no_dual_ip_hostname(void) diff --git a/src/libmongoc/tests/test-libmongoc.h b/src/libmongoc/tests/test-libmongoc.h index e3d05d2db06..c092962abdb 100644 --- a/src/libmongoc/tests/test-libmongoc.h +++ b/src/libmongoc/tests/test-libmongoc.h @@ -214,6 +214,8 @@ WIRE_VERSION_CHECK_DECLS(24) WIRE_VERSION_CHECK_DECLS(25) /* wire version 26 begins with the 8.1 release. */ WIRE_VERSION_CHECK_DECLS(26) +/* wire version 27 begins with the 8.2 release. */ +WIRE_VERSION_CHECK_DECLS(27) #undef WIRE_VERSION_CHECK_DECLS diff --git a/src/libmongoc/tests/test-mongoc-client-side-encryption.c b/src/libmongoc/tests/test-mongoc-client-side-encryption.c index 4c666c30207..1074949eb28 100644 --- a/src/libmongoc/tests/test-mongoc-client-side-encryption.c +++ b/src/libmongoc/tests/test-mongoc-client-side-encryption.c @@ -19,6 +19,9 @@ #include +#include +#include + #include #include @@ -3373,15 +3376,11 @@ typedef struct { } ee_fixture; static ee_fixture * -explicit_encryption_setup(void) +explicit_encryption_setup_full(const char *encrypted_fields_path, const char *key_path) { ee_fixture *eef = (ee_fixture *)bson_malloc0(sizeof(ee_fixture)); - bson_t *encryptedFields = - get_bson_from_json_file("./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" - "encryptedFields.json"); - bson_t *key1Document = - get_bson_from_json_file("./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" - "key1-document.json"); + bson_t *encryptedFields = get_bson_from_json_file(encrypted_fields_path); + bson_t *key1Document = get_bson_from_json_file(key_path); mongoc_client_t *setupClient = test_framework_new_default_client(); @@ -3492,6 +3491,15 @@ explicit_encryption_setup(void) return eef; } +static ee_fixture * +explicit_encryption_setup(void) +{ + return explicit_encryption_setup_full("./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "encryptedFields.json", + "./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "key1-document.json"); +} + static void explicit_encryption_destroy(ee_fixture *eef) { @@ -4498,6 +4506,349 @@ test_explicit_encryption_case5(void *unused) explicit_encryption_destroy(eef); } +static void +test_explicit_encryption_text(void *unused) +{ + bson_error_t error; + bool ok; + bson_value_t plaintext = {0}; + ee_fixture *eef = + explicit_encryption_setup_full("./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "encryptedFields-prefix-suffix.json", + "./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "key1-document.json"); + + BSON_UNUSED(unused); + + plaintext.value_type = BSON_TYPE_UTF8; + plaintext.value.v_utf8.str = "foobarbaz"; + plaintext.value.v_utf8.len = (uint32_t)strlen(plaintext.value.v_utf8.str); + + mongoc_encrypt_text_prefix_opts_t *popts = mongoc_encrypt_text_prefix_opts_new(); + mongoc_encrypt_text_prefix_opts_set_str_max_query_length(popts, 10); + mongoc_encrypt_text_prefix_opts_set_str_min_query_length(popts, 2); + mongoc_encrypt_text_suffix_opts_t *sopts = mongoc_encrypt_text_suffix_opts_new(); + mongoc_encrypt_text_suffix_opts_set_str_max_query_length(sopts, 10); + mongoc_encrypt_text_suffix_opts_set_str_min_query_length(sopts, 2); + mongoc_encrypt_text_substring_opts_t *ssopts = mongoc_encrypt_text_substring_opts_new(); + mongoc_encrypt_text_substring_opts_set_str_max_length(ssopts, 10); + mongoc_encrypt_text_substring_opts_set_str_max_query_length(ssopts, 10); + mongoc_encrypt_text_substring_opts_set_str_min_query_length(ssopts, 2); + + /* Prefix and suffix tests */ + /* Insert 'foobarbaz' with both prefix and suffix indexing */ + { + bson_value_t insertPayload; + bson_t to_insert = BSON_INITIALIZER; + + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_prefix(topts, popts); + mongoc_encrypt_text_opts_set_suffix(topts, sopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &insertPayload, &error); + ASSERT_OR_PRINT(ok, error); + + ASSERT(BSON_APPEND_VALUE(&to_insert, "encryptedText", &insertPayload)); + + ok = mongoc_collection_insert_one(eef->encryptedColl, &to_insert, NULL /* opts */, NULL /* reply */, &error); + ASSERT_OR_PRINT(ok, error); + + bson_value_destroy(&insertPayload); + bson_destroy(&to_insert); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Find the document using the 'foo' prefix */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_PREFIXPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_prefix(topts, popts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "foo"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrStartsWith", doc(kv("input", cstr("$encryptedText")), kv("prefix", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(mongoc_cursor_next(cursor, &got)); + ASSERT_OR_PRINT(!mongoc_cursor_error(cursor, &error), error); + ASSERT_MATCH(got, "{ 'encryptedText': 'foobarbaz' }"); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected one document to be returned, got more than one"); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Find the document using the 'baz' suffix */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_SUFFIXPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_suffix(topts, sopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "baz"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrEndsWith", doc(kv("input", cstr("$encryptedText")), kv("suffix", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(mongoc_cursor_next(cursor, &got)); + ASSERT_OR_PRINT(!mongoc_cursor_error(cursor, &error), error); + ASSERT_MATCH(got, "{ 'encryptedText': 'foobarbaz' }"); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected one document to be returned, got more than one"); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Ensure querying for a 'foo' suffix returns no documents */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_SUFFIXPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_suffix(topts, sopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "foo"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrEndsWith", doc(kv("input", cstr("$encryptedText")), kv("suffix", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected no documents to be returned, got some"); + mongoc_cursor_next(cursor, &got); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Ensure querying for a 'baz' prefix returns no documents */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_PREFIXPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_prefix(topts, popts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "baz"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrStartsWith", doc(kv("input", cstr("$encryptedText")), kv("prefix", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected no documents to be returned, got some"); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + + /* Substring tests */ + explicit_encryption_destroy(eef); + eef = explicit_encryption_setup_full("./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "encryptedFields-substring.json", + "./src/libmongoc/tests/client_side_encryption_prose/explicit_encryption/" + "key1-document.json"); + /* Insert 'foobarbaz' with substring indexing */ + { + bson_value_t insertPayload; + bson_t to_insert = BSON_INITIALIZER; + + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_substring(topts, ssopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "foobarbaz"; + plaintext.value.v_utf8.len = 9; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &insertPayload, &error); + ASSERT_OR_PRINT(ok, error); + + ASSERT(BSON_APPEND_VALUE(&to_insert, "encryptedText", &insertPayload)); + + ok = mongoc_collection_insert_one(eef->encryptedColl, &to_insert, NULL /* opts */, NULL /* reply */, &error); + ASSERT_OR_PRINT(ok, error); + + bson_value_destroy(&insertPayload); + bson_destroy(&to_insert); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Find the document using the 'bar' substring */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_substring(topts, ssopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "bar"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrContains", doc(kv("input", cstr("$encryptedText")), kv("substring", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(mongoc_cursor_next(cursor, &got)); + ASSERT_OR_PRINT(!mongoc_cursor_error(cursor, &error), error); + ASSERT_MATCH(got, "{ 'encryptedText': 'foobarbaz' }"); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected one document to be returned, got more than one"); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + + /* Ensure querying for a 'qux' substring returns no documents */ + { + bson_value_t findPayload; + mongoc_client_encryption_encrypt_opts_t *eo = mongoc_client_encryption_encrypt_opts_new(); + mongoc_client_encryption_encrypt_opts_set_keyid(eo, &eef->key1ID); + mongoc_client_encryption_encrypt_opts_set_algorithm(eo, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + mongoc_client_encryption_encrypt_opts_set_query_type(eo, MONGOC_ENCRYPT_QUERY_TYPE_PREFIXPREVIEW); + mongoc_client_encryption_encrypt_opts_set_contention_factor(eo, 0); + + mongoc_encrypt_text_opts_t *topts = mongoc_encrypt_text_opts_new(); + mongoc_encrypt_text_opts_set_substring(topts, ssopts); + mongoc_encrypt_text_opts_set_diacritic_sensitive(topts, true); + mongoc_encrypt_text_opts_set_case_sensitive(topts, true); + mongoc_client_encryption_encrypt_opts_set_text_opts(eo, topts); + + plaintext.value.v_utf8.str = "qux"; + plaintext.value.v_utf8.len = 3; + ok = mongoc_client_encryption_encrypt(eef->clientEncryption, &plaintext, eo, &findPayload, &error); + + bsonBuildDecl( + expr, + kv("$expr", + doc(kv("$encStrContains", doc(kv("input", cstr("$encryptedText")), kv("substring", value(findPayload))))))); + ASSERT_OR_PRINT(ok, error); + + mongoc_cursor_t *cursor; + const bson_t *got; + + cursor = mongoc_collection_find_with_opts(eef->encryptedColl, &expr, NULL /* opts */, NULL /* read_prefs */); + ASSERT(!mongoc_cursor_next(cursor, &got) && "expected no documents to be returned, got some"); + + bson_value_destroy(&findPayload); + mongoc_cursor_destroy(cursor); + bson_destroy(&expr); + mongoc_encrypt_text_opts_destroy(topts); + mongoc_client_encryption_encrypt_opts_destroy(eo); + } + mongoc_encrypt_text_prefix_opts_destroy(popts); + mongoc_encrypt_text_suffix_opts_destroy(sopts); + mongoc_encrypt_text_substring_opts_destroy(ssopts); + explicit_encryption_destroy(eef); +} + static void _test_unique_index_on_keyaltnames_setup(void (*test_case)(mongoc_client_encryption_t *, const bson_value_t *keyid)) { @@ -7397,5 +7748,13 @@ test_client_side_encryption_install(TestSuite *suite) test_framework_skip_if_max_wire_version_less_than_21 /* require server > 7.0 for QE support */, test_framework_skip_if_single, /* QE not supported on standalone */ test_framework_skip_if_no_client_side_encryption); + TestSuite_AddFull(suite, + "/client_side_encryption/explicit_encryption/text", + test_explicit_encryption_text, + NULL, + NULL, + test_framework_skip_if_max_wire_version_less_than_27 /* require server > 8.2 for QE support */, + test_framework_skip_if_single, /* QE not supported on standalone */ + test_framework_skip_if_no_client_side_encryption); } }