@@ -2511,6 +2511,66 @@ int php_phongo_set_monitoring_callbacks(mongoc_client_t* client)
2511
2511
return retval ;
2512
2512
}
2513
2513
2514
+ static zval * php_phongo_manager_prepare_manager_for_hash (zval * driverOptions , bool * free TSRMLS_DC )
2515
+ {
2516
+ php_phongo_manager_t * manager ;
2517
+ zval * autoEncryptionOpts = NULL ;
2518
+ zval * keyVaultClient = NULL ;
2519
+ zval * driverOptionsClone = NULL ;
2520
+ zval * autoEncryptionOptsClone = NULL ;
2521
+ #if PHP_VERSION_ID >= 70000
2522
+ zval stackAutoEncryptionOptsClone ;
2523
+ #endif
2524
+
2525
+ * free = false;
2526
+
2527
+ if (!driverOptions ) {
2528
+ return NULL ;
2529
+ }
2530
+
2531
+ if (!php_array_existsc (driverOptions , "autoEncryption" )) {
2532
+ goto ref ;
2533
+ }
2534
+
2535
+ autoEncryptionOpts = php_array_fetchc (driverOptions , "autoEncryption" );
2536
+ if (Z_TYPE_P (autoEncryptionOpts ) != IS_ARRAY ) {
2537
+ goto ref ;
2538
+ }
2539
+
2540
+ if (!php_array_existsc (autoEncryptionOpts , "keyVaultClient" )) {
2541
+ goto ref ;
2542
+ }
2543
+
2544
+ keyVaultClient = php_array_fetchc (autoEncryptionOpts , "keyVaultClient" );
2545
+ if (Z_TYPE_P (keyVaultClient ) != IS_OBJECT || !instanceof_function (Z_OBJCE_P (keyVaultClient ), php_phongo_manager_ce TSRMLS_CC )) {
2546
+ goto ref ;
2547
+ }
2548
+
2549
+ * free = true;
2550
+
2551
+ manager = Z_MANAGER_OBJ_P (keyVaultClient );
2552
+
2553
+ #if PHP_VERSION_ID >= 70000
2554
+ driverOptionsClone = ecalloc (sizeof (zval ), 1 );
2555
+ autoEncryptionOptsClone = & stackAutoEncryptionOptsClone ;
2556
+ #else
2557
+ ALLOC_INIT_ZVAL (driverOptionsClone );
2558
+ MAKE_STD_ZVAL (autoEncryptionOptsClone );
2559
+ #endif
2560
+
2561
+ ZVAL_DUP (autoEncryptionOptsClone , autoEncryptionOpts );
2562
+ ADD_ASSOC_STRINGL (autoEncryptionOptsClone , "keyVaultClient" , manager -> client_hash , manager -> client_hash_len );
2563
+
2564
+ ZVAL_DUP (driverOptionsClone , driverOptions );
2565
+ ADD_ASSOC_ZVAL_EX (driverOptionsClone , "autoEncryption" , autoEncryptionOptsClone );
2566
+
2567
+ return driverOptionsClone ;
2568
+
2569
+ ref :
2570
+ Z_ADDREF_P (driverOptions );
2571
+ return driverOptions ;
2572
+ }
2573
+
2514
2574
/* Creates a hash for a client by concatenating the URI string with serialized
2515
2575
* options arrays. On success, a persistent string is returned (i.e. pefree()
2516
2576
* should be used to free it) and hash_len will be set to the string's length.
@@ -2520,6 +2580,8 @@ static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* o
2520
2580
char * hash = NULL ;
2521
2581
smart_str var_buf = { 0 };
2522
2582
php_serialize_data_t var_hash ;
2583
+ zval * serializable_driver_options = NULL ;
2584
+ bool free_driver_options = false;
2523
2585
2524
2586
#if PHP_VERSION_ID >= 70000
2525
2587
zval args ;
@@ -2536,8 +2598,8 @@ static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* o
2536
2598
}
2537
2599
2538
2600
if (driverOptions ) {
2539
- ADD_ASSOC_ZVAL_EX ( & args , " driverOptions" , driverOptions );
2540
- Z_ADDREF_P ( driverOptions );
2601
+ serializable_driver_options = php_phongo_manager_prepare_manager_for_hash ( driverOptions , & free_driver_options TSRMLS_CC );
2602
+ ADD_ASSOC_ZVAL_EX ( & args , " driverOptions" , serializable_driver_options );
2541
2603
} else {
2542
2604
ADD_ASSOC_NULL_EX (& args , "driverOptions" );
2543
2605
}
@@ -2548,10 +2610,15 @@ static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* o
2548
2610
2549
2611
if (!EG (exception )) {
2550
2612
* hash_len = ZSTR_LEN (var_buf .s );
2551
- hash = pestrndup (ZSTR_VAL (var_buf .s ), * hash_len , 1 );
2613
+ hash = estrndup (ZSTR_VAL (var_buf .s ), * hash_len );
2552
2614
}
2553
2615
2554
2616
zval_ptr_dtor (& args );
2617
+
2618
+ if (free_driver_options ) {
2619
+ efree (serializable_driver_options );
2620
+ }
2621
+
2555
2622
#else
2556
2623
zval * args ;
2557
2624
@@ -2568,8 +2635,8 @@ static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* o
2568
2635
}
2569
2636
2570
2637
if (driverOptions ) {
2571
- ADD_ASSOC_ZVAL_EX ( args , " driverOptions" , driverOptions );
2572
- Z_ADDREF_P ( driverOptions );
2638
+ serializable_driver_options = php_phongo_manager_prepare_manager_for_hash ( driverOptions , & free_driver_options TSRMLS_CC );
2639
+ ADD_ASSOC_ZVAL_EX ( args , " driverOptions" , serializable_driver_options );
2573
2640
} else {
2574
2641
ADD_ASSOC_NULL_EX (args , "driverOptions" );
2575
2642
}
@@ -2580,7 +2647,7 @@ static char* php_phongo_manager_make_client_hash(const char* uri_string, zval* o
2580
2647
2581
2648
if (!EG (exception )) {
2582
2649
* hash_len = var_buf .len ;
2583
- hash = pestrndup (var_buf .c , * hash_len , 1 );
2650
+ hash = estrndup (var_buf .c , * hash_len );
2584
2651
}
2585
2652
2586
2653
zval_ptr_dtor (& args );
@@ -2653,23 +2720,156 @@ static mongoc_client_t* php_phongo_find_client(const char* hash, size_t hash_len
2653
2720
return NULL ;
2654
2721
}
2655
2722
2723
+ #ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
2724
+ static bool phongo_manager_set_auto_encryption_opts (php_phongo_manager_t * manager , zval * driverOptions TSRMLS_DC ) /* {{{ */
2725
+ {
2726
+ zval * zAutoEncryptionOpts ;
2727
+ bson_error_t error = { 0 };
2728
+ mongoc_auto_encryption_opts_t * auto_encryption_opts = NULL ;
2729
+ bool retval = false;
2730
+
2731
+ if (!driverOptions || !php_array_existsc (driverOptions , "autoEncryption" )) {
2732
+ return true;
2733
+ }
2734
+
2735
+ zAutoEncryptionOpts = php_array_fetch (driverOptions , "autoEncryption" );
2736
+
2737
+ if (Z_TYPE_P (zAutoEncryptionOpts ) != IS_ARRAY ) {
2738
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Expected \"autoEncryption\" driver option to be array, %s given" , PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P (zAutoEncryptionOpts ));
2739
+ return false;
2740
+ }
2741
+
2742
+ auto_encryption_opts = mongoc_auto_encryption_opts_new ();
2743
+
2744
+ if (php_array_existsc (zAutoEncryptionOpts , "keyVaultClient" )) {
2745
+ zval * key_vault_client = php_array_fetch (zAutoEncryptionOpts , "keyVaultClient" );
2746
+
2747
+ if (Z_TYPE_P (key_vault_client ) != IS_OBJECT || !instanceof_function (Z_OBJCE_P (key_vault_client ), php_phongo_manager_ce TSRMLS_CC )) {
2748
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Expected \"keyVaultClient\" encryption option to be %s, %s given" , ZSTR_VAL (php_phongo_manager_ce -> name ), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P (key_vault_client ));
2749
+ goto cleanup ;
2750
+ }
2751
+
2752
+ mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts , Z_MANAGER_OBJ_P (key_vault_client )-> client );
2753
+ }
2754
+
2755
+ if (php_array_existsc (zAutoEncryptionOpts , "keyVaultNamespace" )) {
2756
+ char * key_vault_ns ;
2757
+ char * db_name ;
2758
+ char * coll_name ;
2759
+ int plen ;
2760
+ zend_bool pfree ;
2761
+
2762
+ key_vault_ns = php_array_fetch_string (zAutoEncryptionOpts , "keyVaultNamespace" , & plen , & pfree );
2763
+
2764
+ if (!phongo_split_namespace (key_vault_ns , & db_name , & coll_name )) {
2765
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Expected \"keyVaultNamespace\" encryption option to contain a full collection name" );
2766
+
2767
+ if (pfree ) {
2768
+ str_efree (key_vault_ns );
2769
+ }
2770
+
2771
+ goto cleanup ;
2772
+ }
2773
+
2774
+ mongoc_auto_encryption_opts_set_keyvault_namespace (auto_encryption_opts , db_name , coll_name );
2775
+
2776
+ efree (db_name );
2777
+ efree (coll_name );
2778
+
2779
+ if (pfree ) {
2780
+ str_efree (key_vault_ns );
2781
+ }
2782
+ }
2783
+
2784
+ if (php_array_existsc (zAutoEncryptionOpts , "kmsProviders" )) {
2785
+ zval * kms_providers = php_array_fetch (zAutoEncryptionOpts , "kmsProviders" );
2786
+ bson_t bson_providers = BSON_INITIALIZER ;
2787
+
2788
+ php_phongo_zval_to_bson (kms_providers , PHONGO_BSON_NONE , & bson_providers , NULL TSRMLS_CC );
2789
+ if (EG (exception )) {
2790
+ goto cleanup ;
2791
+ }
2792
+
2793
+ mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts , & bson_providers );
2794
+
2795
+ bson_destroy (& bson_providers );
2796
+ }
2797
+
2798
+ if (php_array_existsc (zAutoEncryptionOpts , "schemaMap" )) {
2799
+ zval * schema_map = php_array_fetch (zAutoEncryptionOpts , "schemaMap" );
2800
+ bson_t bson_map = BSON_INITIALIZER ;
2801
+
2802
+ php_phongo_zval_to_bson (schema_map , PHONGO_BSON_NONE , & bson_map , NULL TSRMLS_CC );
2803
+ if (EG (exception )) {
2804
+ goto cleanup ;
2805
+ }
2806
+
2807
+ mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts , & bson_map );
2808
+
2809
+ bson_destroy (& bson_map );
2810
+ }
2811
+
2812
+ if (php_array_existsc (zAutoEncryptionOpts , "bypassAutoEncryption" )) {
2813
+ zend_bool bypass_auto_encryption = php_array_fetch_bool (zAutoEncryptionOpts , "bypassAutoEncryption" );
2814
+
2815
+ mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts , bypass_auto_encryption );
2816
+ }
2817
+
2818
+ if (php_array_existsc (zAutoEncryptionOpts , "extraOptions" )) {
2819
+ zval * extra_options = php_array_fetch (zAutoEncryptionOpts , "extraOptions" );
2820
+ bson_t bson_options = BSON_INITIALIZER ;
2821
+
2822
+ php_phongo_zval_to_bson (extra_options , PHONGO_BSON_NONE , & bson_options , NULL TSRMLS_CC );
2823
+ if (EG (exception )) {
2824
+ goto cleanup ;
2825
+ }
2826
+
2827
+ mongoc_auto_encryption_opts_set_extra (auto_encryption_opts , & bson_options );
2828
+
2829
+ bson_destroy (& bson_options );
2830
+ }
2831
+
2832
+ if (!mongoc_client_enable_auto_encryption (manager -> client , auto_encryption_opts , & error )) {
2833
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
2834
+ goto cleanup ;
2835
+ }
2836
+
2837
+ retval = true;
2838
+
2839
+ cleanup :
2840
+ mongoc_auto_encryption_opts_destroy (auto_encryption_opts );
2841
+ return retval ;
2842
+ }
2843
+ /* }}} */
2844
+ #else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
2845
+ static bool phongo_manager_set_auto_encryption_opts (php_phongo_manager_t * manager , zval * driverOptions TSRMLS_DC ) /* {{{ */
2846
+ {
2847
+ if (!driverOptions || !php_array_existsc (driverOptions , "autoEncryption" )) {
2848
+ return true;
2849
+ }
2850
+
2851
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Cannot enable automatic field-level encryption. Please recompile with support for libmongocrypt using the with-mongodb-client-side-encryption configure switch." );
2852
+
2853
+ return false;
2854
+ }
2855
+ /* }}} */
2856
+ #endif
2857
+
2656
2858
void phongo_manager_init (php_phongo_manager_t * manager , const char * uri_string , zval * options , zval * driverOptions TSRMLS_DC ) /* {{{ */
2657
2859
{
2658
- char * hash = NULL ;
2659
- size_t hash_len = 0 ;
2660
2860
bson_t bson_options = BSON_INITIALIZER ;
2661
2861
mongoc_uri_t * uri = NULL ;
2662
2862
#ifdef MONGOC_ENABLE_SSL
2663
2863
mongoc_ssl_opt_t * ssl_opt = NULL ;
2664
2864
#endif
2665
2865
2666
- if (!(hash = php_phongo_manager_make_client_hash (uri_string , options , driverOptions , & hash_len TSRMLS_CC ))) {
2866
+ if (!(manager -> client_hash = php_phongo_manager_make_client_hash (uri_string , options , driverOptions , & manager -> client_hash_len TSRMLS_CC ))) {
2667
2867
/* Exception should already have been thrown and there is nothing to free */
2668
2868
return ;
2669
2869
}
2670
2870
2671
- if ((manager -> client = php_phongo_find_client (hash , hash_len TSRMLS_CC ))) {
2672
- MONGOC_DEBUG ("Found client for hash: %s\n" , hash );
2871
+ if ((manager -> client = php_phongo_find_client (manager -> client_hash , manager -> client_hash_len TSRMLS_CC ))) {
2872
+ MONGOC_DEBUG ("Found client for hash: %s\n" , manager -> client_hash );
2673
2873
goto cleanup ;
2674
2874
}
2675
2875
@@ -2733,14 +2933,15 @@ void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string,
2733
2933
}
2734
2934
#endif
2735
2935
2736
- MONGOC_DEBUG ("Created client hash: %s\n" , hash );
2737
- php_phongo_persist_client (hash , hash_len , manager -> client TSRMLS_CC );
2738
-
2739
- cleanup :
2740
- if (hash ) {
2741
- pefree (hash , 1 );
2936
+ if (!phongo_manager_set_auto_encryption_opts (manager , driverOptions TSRMLS_CC )) {
2937
+ /* Exception should already have been thrown */
2938
+ goto cleanup ;
2742
2939
}
2743
2940
2941
+ MONGOC_DEBUG ("Created client hash: %s\n" , manager -> client_hash );
2942
+ php_phongo_persist_client (manager -> client_hash , manager -> client_hash_len , manager -> client TSRMLS_CC );
2943
+
2944
+ cleanup :
2744
2945
bson_destroy (& bson_options );
2745
2946
2746
2947
if (uri ) {
0 commit comments