Skip to content

Commit ee9e331

Browse files
committed
PHPC-223: Use explicit SSL options rather then stream context
This also adds support for PHPC-185
1 parent 22ca996 commit ee9e331

File tree

5 files changed

+256
-27
lines changed

5 files changed

+256
-27
lines changed

php_phongo.c

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,49 +1199,90 @@ void php_phongo_result_to_zval(zval *retval, php_phongo_result_t *result) /* {{{
11991199

12001200
mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptions TSRMLS_DC) /* {{{ */
12011201
{
1202-
php_stream_context *ctx = NULL;
1203-
mongoc_client_t *client = mongoc_client_new(uri);
1202+
zval **tmp;
1203+
php_stream_context *ctx;
1204+
const char *mech;
1205+
const mongoc_uri_t *muri;
1206+
mongoc_client_t *client = mongoc_client_new(uri);
1207+
12041208

12051209
if (!client) {
12061210
return false;
12071211
}
12081212

1209-
if (driverOptions) {
1210-
zval **tmp;
1213+
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
1214+
ctx = php_stream_context_from_zval(*tmp, 0);
1215+
} else {
1216+
ctx = FG(default_context) ? FG(default_context) : php_stream_context_alloc(TSRMLS_C);
1217+
}
1218+
muri = mongoc_client_get_uri(client);
1219+
1220+
if (driverOptions && mongoc_uri_get_ssl(muri)) {
12111221

1212-
if (zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
1213-
ctx = php_stream_context_from_zval(*tmp, PHP_FILE_NO_DEFAULT_CONTEXT);
1214-
} else if (FG(default_context)) {
1215-
ctx = FG(default_context);
1222+
#define SET_STRING_CTX(name) \
1223+
if (php_array_exists(driverOptions, name)) { \
1224+
zval ztmp; \
1225+
zend_bool ctmp_free; \
1226+
int ctmp_len; \
1227+
char *ctmp; \
1228+
ctmp = php_array_fetchl_string(driverOptions, name, sizeof(name)-1, &ctmp_len, &ctmp_free); \
1229+
ZVAL_STRING(&ztmp, ctmp, ctmp_free); \
1230+
php_stream_context_set_option(ctx, "ssl", name, &ztmp); \
12161231
}
12171232

1218-
if (ctx) {
1219-
const mongoc_uri_t *muri = mongoc_client_get_uri(client);
1220-
const char *mech = mongoc_uri_get_auth_mechanism(muri);
1233+
#define SET_BOOL_CTX(name, defaultvalue) \
1234+
{ \
1235+
zval ztmp; \
1236+
if (php_array_exists(driverOptions, name)) { \
1237+
ZVAL_BOOL(&ztmp, php_array_fetchl_bool(driverOptions, ZEND_STRL(name))); \
1238+
php_stream_context_set_option(ctx, "ssl", name, &ztmp); \
1239+
} \
1240+
else if (php_stream_context_get_option(ctx, "ssl", name, &tmp) == FAILURE) { \
1241+
ZVAL_BOOL(&ztmp, defaultvalue); \
1242+
php_stream_context_set_option(ctx, "ssl", name, &ztmp); \
1243+
} \
1244+
}
12211245

1222-
/* Check if we are doing X509 auth, in which case extract the username (subject) from the cert if no username is provided */
1223-
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(muri)) {
1224-
zval **pem;
1246+
SET_BOOL_CTX("verify_peer", 1);
1247+
SET_BOOL_CTX("verify_peer_name", 1);
1248+
SET_BOOL_CTX("verify_hostname", 1);
1249+
SET_BOOL_CTX("verify_expiry", 1);
1250+
SET_BOOL_CTX("allow_self_signed", 0);
12251251

1226-
if (SUCCESS == php_stream_context_get_option(ctx, "ssl", "local_cert", &pem)) {
1227-
char filename[MAXPATHLEN];
1252+
SET_STRING_CTX("peer_name");
1253+
SET_STRING_CTX("local_pk");
1254+
SET_STRING_CTX("local_cert");
1255+
SET_STRING_CTX("cafile");
1256+
SET_STRING_CTX("capath");
1257+
SET_STRING_CTX("passphrase");
1258+
SET_STRING_CTX("ciphers");
1259+
#undef SET_BOOL_CTX
1260+
#undef SET_STRING_CTX
1261+
}
12281262

1229-
convert_to_string_ex(pem);
1230-
if (VCWD_REALPATH(Z_STRVAL_PP(pem), filename)) {
1231-
mongoc_ssl_opt_t ssl_options;
1263+
mech = mongoc_uri_get_auth_mechanism(muri);
12321264

1233-
ssl_options.pem_file = filename;
1234-
mongoc_client_set_ssl_opts(client, &ssl_options);
1235-
}
1236-
}
1265+
/* Check if we are doing X509 auth, in which case extract the username (subject) from the cert if no username is provided */
1266+
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(muri)) {
1267+
zval **pem;
1268+
1269+
if (SUCCESS == php_stream_context_get_option(ctx, "ssl", "local_cert", &pem)) {
1270+
char filename[MAXPATHLEN];
1271+
1272+
convert_to_string_ex(pem);
1273+
if (VCWD_REALPATH(Z_STRVAL_PP(pem), filename)) {
1274+
mongoc_ssl_opt_t ssl_options;
1275+
1276+
ssl_options.pem_file = filename;
1277+
mongoc_client_set_ssl_opts(client, &ssl_options);
12371278
}
12381279
}
1280+
}
12391281

1240-
if (zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
1241-
convert_to_string(*tmp);
1282+
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
1283+
convert_to_string(*tmp);
12421284

1243-
zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
1244-
}
1285+
zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
12451286
}
12461287

12471288
mongoc_client_set_stream_initiator(client, phongo_stream_initiator, ctx);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
Connect to MongoDB with using SSL without verifying anything
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$SSL_DIR = realpath(__DIR__ . "/" . "./../../scripts/ssl/");
10+
$opts = array(
11+
"verify_peer" => false,
12+
"verify_peer_name" => false,
13+
"allow_self_signed" => true,
14+
);
15+
16+
$dsn = sprintf("%s/?ssl=true", STANDALONE_SSL);
17+
18+
$manager = new MongoDB\Driver\Manager($dsn, array(), $opts);
19+
20+
$bulk = new MongoDB\Driver\BulkWrite;
21+
22+
$bulk->insert(array("my" => "value"));
23+
$bulk->insert(array("my" => "value", "foo" => "bar"));
24+
$bulk->insert(array("my" => "value", "foo" => "bar"));
25+
26+
$bulk->delete(array("my" => "value", "foo" => "bar"), array("limit" => 1));
27+
28+
$bulk->update(array("foo" => "bar"), array('$set' => array("foo" => "baz")), array("limit" => 1, "upsert" => 0));
29+
30+
$retval = $manager->executeBulkWrite(NS, $bulk);
31+
32+
printf("Inserted: %d\n", getInsertCount($retval));
33+
printf("Deleted: %d\n", getDeletedCount($retval));
34+
printf("Updated: %d\n", getModifiedCount($retval));
35+
printf("Upserted: %d\n", getUpsertedCount($retval));
36+
foreach(getWriteErrors($retval) as $error) {
37+
printf("WriteErrors: %", $error);
38+
}
39+
?>
40+
===DONE===
41+
<?php exit(0); ?>
42+
--EXPECT--
43+
Inserted: 3
44+
Deleted: 1
45+
Updated: 1
46+
Upserted: 0
47+
===DONE===
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
Connect to MongoDB with using SSL and verify the stream
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$dsn = sprintf("%s/?ssl=true", STANDALONE_SSL);
10+
11+
$SSL_DIR = realpath(__DIR__ . "/" . "./../../scripts/ssl/");
12+
$opts = array(
13+
"peer_name" => "WRONG PEER NAME",
14+
"verify_peer" => true,
15+
"verify_peer_name" => true,
16+
"allow_self_signed" => false,
17+
"cafile" => $SSL_DIR . "/ca.pem", /* Defaults to openssl.cafile */
18+
"ciphers" => "HIGH:!EXPORT:!aNULL@STRENGTH",
19+
);
20+
21+
$manager = new MongoDB\Driver\Manager($dsn, array(), $opts);
22+
23+
24+
echo throws(function() use($manager) {
25+
$bulk = new MongoDB\Driver\BulkWrite;
26+
$bulk->insert(array("my" => "value"));
27+
$retval = $manager->executeBulkWrite(NS, $bulk);
28+
}, "MongoDB\\Driver\\SSLConnectionException", "executeBulkWrite"), "\n";
29+
30+
31+
echo "Changing to server\n";
32+
$opts["peer_name"] = "server";
33+
$manager = new MongoDB\Driver\Manager($dsn, array(), $opts);
34+
$bulk = new MongoDB\Driver\BulkWrite;
35+
$bulk->insert(array("my" => "value"));
36+
$retval = $manager->executeBulkWrite(NS, $bulk);
37+
printf("Inserted: %d\n", $retval->getInsertedCount());
38+
39+
40+
41+
?>
42+
===DONE===
43+
<?php exit(0); ?>
44+
--EXPECTF--
45+
OK: Got MongoDB\Driver\SSLConnectionException thrown from executeBulkWrite
46+
%s
47+
Changing to server
48+
Inserted: 1
49+
===DONE===
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Connect to MongoDB with using SSL and X.509 auth
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/auth-x509-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$SSL_DIR = realpath(__DIR__ . "/" . "./../../scripts/ssl/");
10+
11+
$opts = array(
12+
"peer_name" => "server",
13+
"verify_peer" => true,
14+
"verify_peer_name" => true,
15+
"allow_self_signed" => false,
16+
"cafile" => $SSL_DIR . "/ca.pem", /* Defaults to openssl.cafile */
17+
"local_cert" => $SSL_DIR . "/client.pem",
18+
);
19+
20+
try {
21+
$dsn = sprintf("%s&ssl=true", STANDALONE_X509);
22+
23+
$manager = new MongoDB\Driver\Manager($dsn, array(), $opts);
24+
25+
$bulk = new MongoDB\Driver\BulkWrite();
26+
$bulk->insert(array("very" => "important"));
27+
$manager->executeBulkWrite(NS, $bulk);
28+
$query = new MongoDB\Driver\Query(array("very" => "important"));
29+
$cursor = $manager->executeQuery(NS, $query);
30+
foreach($cursor as $document) {
31+
var_dump($document["very"]);
32+
}
33+
$command = new MongoDB\Driver\Command(array("drop" => COLLECTION_NAME));
34+
$result = $manager->executeCommand(DATABASE_NAME, $command);
35+
} catch(Exception $e) {
36+
echo get_class($e), ": ", $e->getMessage(), "\n";
37+
}
38+
39+
40+
?>
41+
===DONE===
42+
<?php exit(0); ?>
43+
--EXPECTF--
44+
string(9) "important"
45+
===DONE===
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
Connect to MongoDB with using X509 retrieving username from certificate #002
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/auth-x509-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$SSL_DIR = realpath(__DIR__ . "/" . "./../../scripts/ssl/");
10+
11+
$opts = array(
12+
"peer_name" => "server",
13+
"verify_peer" => true,
14+
"verify_peer_name" => true,
15+
"allow_self_signed" => false,
16+
"cafile" => $SSL_DIR . "/ca.pem", /* Defaults to openssl.cafile */
17+
"capath" => $SSL_DIR, /* Defaults to openssl.capath */
18+
"local_cert" => $SSL_DIR . "/client.pem",
19+
);
20+
21+
try {
22+
/* mongoc will pull the username of the certificate */
23+
$parsed = parse_url(STANDALONE_X509);
24+
$dsn = sprintf("mongodb://%s:%d/%s?ssl=true&authMechanism=MONGODB-X509", $parsed["host"], $parsed["port"], DATABASE_NAME);
25+
26+
$manager = new MongoDB\Driver\Manager($dsn, array(), $opts);
27+
28+
$bulk = new MongoDB\Driver\BulkWrite();
29+
$bulk->insert(array("very" => "important"));
30+
$manager->executeBulkWrite(NS, $bulk);
31+
$query = new MongoDB\Driver\Query(array("very" => "important"));
32+
$cursor = $manager->executeQuery(NS, $query);
33+
foreach($cursor as $document) {
34+
var_dump($document["very"]);
35+
}
36+
$command = new MongoDB\Driver\Command(array("drop" => COLLECTION_NAME));
37+
$result = $manager->executeCommand(DATABASE_NAME, $command);
38+
} catch(Exception $e) {
39+
echo get_class($e), ": ", $e->getMessage(), "\n";
40+
}
41+
42+
?>
43+
===DONE===
44+
<?php exit(0); ?>
45+
--EXPECTF--
46+
string(9) "important"
47+
===DONE===

0 commit comments

Comments
 (0)