@@ -1500,6 +1500,25 @@ static bool php_phongo_uri_finalize_auth(mongoc_uri_t* uri TSRMLS_DC) /* {{{ */
15001500 return true;
15011501} /* }}} */
15021502
1503+ static bool php_phongo_uri_finalize_tls (mongoc_uri_t * uri TSRMLS_DC ) /* {{{ */
1504+ {
1505+ const bson_t * options ;
1506+ bson_iter_t iter ;
1507+
1508+ if (!(options = mongoc_uri_get_options (uri ))) {
1509+ return true;
1510+ }
1511+
1512+ if (bson_iter_init_find_case (& iter , options , MONGOC_URI_TLSINSECURE ) &&
1513+ (bson_iter_init_find_case (& iter , options , MONGOC_URI_TLSALLOWINVALIDCERTIFICATES ) ||
1514+ bson_iter_init_find_case (& iter , options , MONGOC_URI_TLSALLOWINVALIDHOSTNAMES ))) {
1515+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse URI options: %s may not be combined with %s or %s." , MONGOC_URI_TLSINSECURE , MONGOC_URI_TLSALLOWINVALIDCERTIFICATES , MONGOC_URI_TLSALLOWINVALIDHOSTNAMES );
1516+ return false;
1517+ }
1518+
1519+ return true;
1520+ } /* }}} */
1521+
15031522static bool php_phongo_apply_options_to_uri (mongoc_uri_t * uri , bson_t * options TSRMLS_DC ) /* {{{ */
15041523{
15051524 bson_iter_t iter ;
@@ -2049,15 +2068,16 @@ static bool php_phongo_apply_wc_options_to_uri(mongoc_uri_t* uri, bson_t* option
20492068
20502069static void php_phongo_mongoc_ssl_opts_from_uri (mongoc_ssl_opt_t * ssl_opt , mongoc_uri_t * uri , bool * any_ssl_option_set )
20512070{
2052- const char * pem_file = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE , NULL );
2053- const char * pem_pwd = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD , NULL );
2054- const char * ca_file = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE , NULL );
2071+ bool insecure = mongoc_uri_get_option_as_bool (uri , MONGOC_URI_TLSINSECURE , false);
2072+ const char * pem_file = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_TLSCERTIFICATEKEYFILE , NULL );
2073+ const char * pem_pwd = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD , NULL );
2074+ const char * ca_file = mongoc_uri_get_option_as_utf8 (uri , MONGOC_URI_TLSCAFILE , NULL );
20552075
20562076 ssl_opt -> pem_file = pem_file ? estrdup (pem_file ) : NULL ;
20572077 ssl_opt -> pem_pwd = pem_pwd ? estrdup (pem_pwd ) : NULL ;
20582078 ssl_opt -> ca_file = ca_file ? estrdup (ca_file ) : NULL ;
2059- ssl_opt -> weak_cert_validation = mongoc_uri_get_option_as_bool (uri , MONGOC_URI_SSLALLOWINVALIDCERTIFICATES , false );
2060- ssl_opt -> allow_invalid_hostname = mongoc_uri_get_option_as_bool (uri , MONGOC_URI_SSLALLOWINVALIDHOSTNAMES , false );
2079+ ssl_opt -> weak_cert_validation = mongoc_uri_get_option_as_bool (uri , MONGOC_URI_TLSALLOWINVALIDCERTIFICATES , insecure );
2080+ ssl_opt -> allow_invalid_hostname = mongoc_uri_get_option_as_bool (uri , MONGOC_URI_TLSALLOWINVALIDHOSTNAMES , insecure );
20612081
20622082 /* Boolean options default to false, so we cannot consider them for
20632083 * any_ssl_option_set. This isn't actually a problem as libmongoc will
@@ -2069,14 +2089,14 @@ static void php_phongo_mongoc_ssl_opts_from_uri(mongoc_ssl_opt_t* ssl_opt, mongo
20692089 }
20702090}
20712091
2072- static inline char * php_phongo_fetch_ssl_opt_string (zval * zoptions , const char * key , int key_len )
2092+ static inline char * php_phongo_fetch_ssl_opt_string (zval * zoptions , const char * key )
20732093{
20742094 int plen ;
20752095 zend_bool pfree ;
20762096 char * pval ;
20772097 char * value ;
20782098
2079- pval = php_array_fetchl_string (zoptions , key , key_len , & plen , & pfree );
2099+ pval = php_array_fetch_string (zoptions , key , & plen , & pfree );
20802100 value = pfree ? pval : estrndup (pval , plen );
20812101
20822102 return value ;
@@ -2119,51 +2139,14 @@ static mongoc_ssl_opt_t* php_phongo_make_ssl_opt(mongoc_uri_t* uri, zval* zoptio
21192139 php_phongo_mongoc_ssl_opts_from_uri (ssl_opt , uri , & any_ssl_option_set );
21202140 }
21212141
2122- /* Check canonical option names first and fall back to SSL context options
2123- * for backwards compatibility. */
2124- if (php_array_existsc (zoptions , "allow_invalid_hostname" )) {
2125- ssl_opt -> allow_invalid_hostname = php_array_fetchc_bool (zoptions , "allow_invalid_hostname" );
2126- any_ssl_option_set = true;
2127- }
2128-
2129- if (php_array_existsc (zoptions , "weak_cert_validation" )) {
2130- ssl_opt -> weak_cert_validation = php_array_fetchc_bool (zoptions , "weak_cert_validation" );
2131- any_ssl_option_set = true;
2132- } else if (php_array_existsc (zoptions , "allow_self_signed" )) {
2133- ssl_opt -> weak_cert_validation = php_array_fetchc_bool (zoptions , "allow_self_signed" );
2134- any_ssl_option_set = true;
2135- }
2136-
21372142#define PHONGO_SSL_OPTION_SWAP_STRING (o , n ) \
21382143 if ((o)) { \
21392144 efree((char*) (o)); \
21402145 } \
2141- (o) = php_phongo_fetch_ssl_opt_string(zoptions, ZEND_STRL((n)));
2142-
2143- if (php_array_existsc (zoptions , "pem_file" )) {
2144- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> pem_file , "pem_file" );
2145- any_ssl_option_set = true;
2146- } else if (php_array_existsc (zoptions , "local_cert" )) {
2147- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> pem_file , "local_cert" );
2148- any_ssl_option_set = true;
2149- }
2150-
2151- if (php_array_existsc (zoptions , "pem_pwd" )) {
2152- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> pem_pwd , "pem_pwd" );
2153- any_ssl_option_set = true;
2154- } else if (php_array_existsc (zoptions , "passphrase" )) {
2155- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> pem_pwd , "passphrase" );
2156- any_ssl_option_set = true;
2157- }
2158-
2159- if (php_array_existsc (zoptions , "ca_file" )) {
2160- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> ca_file , "ca_file" );
2161- any_ssl_option_set = true;
2162- } else if (php_array_existsc (zoptions , "cafile" )) {
2163- PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> ca_file , "cafile" );
2164- any_ssl_option_set = true;
2165- }
2146+ (o) = php_phongo_fetch_ssl_opt_string(zoptions, n);
21662147
2148+ /* Apply driver options that don't have a corresponding URI option. These
2149+ * are set directly on the SSL options struct. */
21672150 if (php_array_existsc (zoptions , "ca_dir" )) {
21682151 PHONGO_SSL_OPTION_SWAP_STRING (ssl_opt -> ca_dir , "ca_dir" );
21692152 any_ssl_option_set = true;
@@ -2211,6 +2194,92 @@ static void php_phongo_free_ssl_opt(mongoc_ssl_opt_t* ssl_opt)
22112194
22122195 efree (ssl_opt );
22132196}
2197+
2198+ static inline bool php_phongo_apply_driver_option_to_uri (mongoc_uri_t * uri , zval * zoptions , const char * driverOptionKey , const char * optionKey )
2199+ {
2200+ bool ret ;
2201+ char * value ;
2202+
2203+ value = php_phongo_fetch_ssl_opt_string (zoptions , driverOptionKey );
2204+ ret = mongoc_uri_set_option_as_utf8 (uri , optionKey , value );
2205+ efree (value );
2206+
2207+ return ret ;
2208+ }
2209+
2210+ static bool php_phongo_apply_driver_options_to_uri (mongoc_uri_t * uri , zval * zoptions TSRMLS_DC )
2211+ {
2212+ if (!zoptions ) {
2213+ return true;
2214+ }
2215+
2216+ /* Map TLS driver options to the canonical tls options in the URI. */
2217+ if (php_array_existsc (zoptions , "allow_invalid_hostname" )) {
2218+ if (!mongoc_uri_set_option_as_bool (uri , MONGOC_URI_TLSALLOWINVALIDHOSTNAMES , php_array_fetchc_bool (zoptions , "allow_invalid_hostname" ))) {
2219+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "allow_invalid_hostname" );
2220+
2221+ return false;
2222+ }
2223+ }
2224+
2225+ if (php_array_existsc (zoptions , "weak_cert_validation" )) {
2226+ if (!mongoc_uri_set_option_as_bool (uri , MONGOC_URI_TLSALLOWINVALIDCERTIFICATES , php_array_fetchc_bool (zoptions , "weak_cert_validation" ))) {
2227+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "weak_cert_validation" );
2228+
2229+ return false;
2230+ }
2231+ } else if (php_array_existsc (zoptions , "allow_self_signed" )) {
2232+ if (!mongoc_uri_set_option_as_bool (uri , MONGOC_URI_TLSALLOWINVALIDCERTIFICATES , php_array_fetchc_bool (zoptions , "allow_self_signed" ))) {
2233+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "allow_self_signed" );
2234+
2235+ return false;
2236+ }
2237+ }
2238+
2239+ if (php_array_existsc (zoptions , "pem_file" )) {
2240+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "pem_file" , MONGOC_URI_TLSCERTIFICATEKEYFILE )) {
2241+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "pem_file" );
2242+
2243+ return false;
2244+ }
2245+ } else if (php_array_existsc (zoptions , "local_cert" )) {
2246+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "local_cert" , MONGOC_URI_TLSCERTIFICATEKEYFILE )) {
2247+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "local_cert" );
2248+
2249+ return false;
2250+ }
2251+ }
2252+
2253+ if (php_array_existsc (zoptions , "pem_pwd" )) {
2254+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "pem_pwd" , MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD )) {
2255+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "pem_pwd" );
2256+
2257+ return false;
2258+ }
2259+ } else if (php_array_existsc (zoptions , "passphrase" )) {
2260+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "passphrase" , MONGOC_URI_TLSCERTIFICATEKEYFILEPASSWORD )) {
2261+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "passphrase" );
2262+
2263+ return false;
2264+ }
2265+ }
2266+
2267+ if (php_array_existsc (zoptions , "ca_file" )) {
2268+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "ca_file" , MONGOC_URI_TLSCAFILE )) {
2269+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "ca_file" );
2270+
2271+ return false;
2272+ }
2273+ } else if (php_array_existsc (zoptions , "cafile" )) {
2274+ if (!php_phongo_apply_driver_option_to_uri (uri , zoptions , "cafile" , MONGOC_URI_TLSCAFILE )) {
2275+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Failed to parse \"%s\" driver option" , "cafile" );
2276+
2277+ return false;
2278+ }
2279+ }
2280+
2281+ return true;
2282+ }
22142283#endif
22152284
22162285/* APM callbacks */
@@ -2599,12 +2668,22 @@ void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string,
25992668 }
26002669
26012670#ifdef MONGOC_ENABLE_SSL
2671+ if (!php_phongo_apply_driver_options_to_uri (uri , driverOptions TSRMLS_CC )) {
2672+ /* Exception should already have been thrown */
2673+ goto cleanup ;
2674+ }
2675+
26022676 ssl_opt = php_phongo_make_ssl_opt (uri , driverOptions TSRMLS_CC );
26032677
26042678 /* An exception may be thrown during SSL option creation */
26052679 if (EG (exception )) {
26062680 goto cleanup ;
26072681 }
2682+
2683+ if (!php_phongo_uri_finalize_tls (uri TSRMLS_CC )) {
2684+ /* Exception should already have been thrown */
2685+ goto cleanup ;
2686+ }
26082687#else
26092688 if (mongoc_uri_get_tls (uri )) {
26102689 phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Cannot create SSL client. SSL is not enabled in this build." );
0 commit comments