Merge pull request #384 from yitam/azure-ad
Azure AD implementation - preview
This commit is contained in:
commit
d5dcf9b4bc
|
@ -114,9 +114,9 @@ install:
|
|||
- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/releases/php-' + ${env:PHP_VERSION} + '-src.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php.zip')
|
||||
#- echo Downloading PHP deps [%PHP_DEPSVER%]
|
||||
#- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/php-sdk/deps-' + ${env:PHP_DEPSVER} + '-vc' + ${env:PHP_VC} + '-' + ${env:BUILD_PLATFORM} + '.7z', ${env:APPVEYOR_BUILD_FOLDER} + '\..\deps.7z')
|
||||
- echo Downloading MSODBCSQL 13
|
||||
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/1/E/7/1E7B1181-3974-4B29-9A47-CC857B271AA2/English/' + ${env:BUILD_PLATFORM} + '/msodbcsql.msi', 'msodbcsql.msi')
|
||||
- ps: msiexec /i msodbcsql.msi /quiet /qn /norestart
|
||||
- echo Downloading MSODBCSQL 13.1
|
||||
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/' + ${env:BUILD_PLATFORM} + '/msodbcsql.msi', 'msodbcsql.msi')
|
||||
- ps: msiexec /i msodbcsql.msi /quiet /qn
|
||||
- cd ..
|
||||
- cd
|
||||
- 7z x -y php-sdk-binary-tools-20110915.zip -o%PHP_SDK%
|
||||
|
|
|
@ -41,6 +41,7 @@ const char APP[] = "APP";
|
|||
const char ApplicationIntent[] = "ApplicationIntent";
|
||||
const char AttachDBFileName[] = "AttachDbFileName";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
const char Authentication[] = "Authentication";
|
||||
#ifdef _WIN32
|
||||
const char ConnectRetryCount[] = "ConnectRetryCount";
|
||||
const char ConnectRetryInterval[] = "ConnectRetryInterval";
|
||||
|
@ -200,6 +201,15 @@ const connection_option PDO_CONN_OPTS[] = {
|
|||
CONN_ATTR_STRING,
|
||||
conn_str_append_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::Authentication,
|
||||
sizeof( PDOConnOptionNames::Authentication ),
|
||||
SQLSRV_CONN_OPTION_AUTHENTICATION,
|
||||
ODBCConnOptions::Authentication,
|
||||
sizeof( ODBCConnOptions::Authentication ),
|
||||
CONN_ATTR_STRING,
|
||||
conn_str_append_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::ConnectionPooling,
|
||||
sizeof( PDOConnOptionNames::ConnectionPooling ),
|
||||
|
|
|
@ -169,6 +169,31 @@ void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
|
|||
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, static_cast<char*>( key_name ) );
|
||||
}
|
||||
|
||||
void conn_string_parser::add_key_value_pair( const char* value, int len TSRMLS_DC )
|
||||
{
|
||||
// if the keyword is 'Authentication', check whether the user specified option is supported
|
||||
bool valid = true;
|
||||
if ( stricmp( this->current_key_name, ODBCConnOptions::Authentication ) == 0 ) {
|
||||
if (len <= 0)
|
||||
valid = false;
|
||||
else {
|
||||
// extract option from the value by len
|
||||
sqlsrv_malloc_auto_ptr<char> option;
|
||||
option = static_cast<char*>( sqlsrv_malloc( len + 1 ) );
|
||||
memcpy_s( option, len + 1, value, len );
|
||||
option[len] = '\0';
|
||||
|
||||
valid = core_is_authentication_option_valid( option, len );
|
||||
}
|
||||
}
|
||||
if( !valid ) {
|
||||
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, this->current_key_name );
|
||||
}
|
||||
|
||||
string_parser::add_key_value_pair( value, len );
|
||||
}
|
||||
|
||||
|
||||
inline bool sql_string_parser::is_placeholder_char( char c )
|
||||
{
|
||||
// placeholder only accepts numbers, upper and lower case alphabets and underscore
|
||||
|
|
|
@ -377,6 +377,10 @@ pdo_error PDO_ERRORS[] = {
|
|||
PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED,
|
||||
{ IMSSP, (SQLCHAR*) "Statement with emulate prepare on does not support output or input_output parameters.", -72, false }
|
||||
},
|
||||
{
|
||||
PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION,
|
||||
{ IMSSP, (SQLCHAR*) "Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.", -73, false }
|
||||
},
|
||||
{ UINT_MAX, {} }
|
||||
};
|
||||
|
||||
|
|
|
@ -165,6 +165,9 @@ class conn_string_parser : private string_parser
|
|||
int discard_trailing_white_spaces(const char* str, int len);
|
||||
void validate_key(const char *key, int key_len TSRMLS_DC);
|
||||
|
||||
protected:
|
||||
void add_key_value_pair(const char* value, int len TSRMLS_DC);
|
||||
|
||||
public:
|
||||
conn_string_parser( sqlsrv_context& ctx, const char* dsn, int len, _Inout_ HashTable* conn_options_ht );
|
||||
void parse_conn_string( TSRMLS_D );
|
||||
|
@ -390,6 +393,7 @@ enum PDO_ERROR_CODES {
|
|||
PDO_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE,
|
||||
PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE,
|
||||
PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED,
|
||||
PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION
|
||||
};
|
||||
|
||||
extern pdo_error PDO_ERRORS[];
|
||||
|
|
|
@ -550,6 +550,20 @@ bool core_is_conn_opt_value_escaped( const char* value, size_t value_len )
|
|||
return true;
|
||||
}
|
||||
|
||||
// core_is_authentication_option_valid
|
||||
// if the option for the authentication is valid, returns true. This returns false otherwise.
|
||||
bool core_is_authentication_option_valid(const char* value, size_t value_len)
|
||||
{
|
||||
if (value_len <= 0)
|
||||
return false;
|
||||
|
||||
if( ! stricmp( value, AzureADOptions::AZURE_AUTH_SQL_PASSWORD ) || ! stricmp( value, AzureADOptions::AZURE_AUTH_AD_PASSWORD ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// *** internal connection functions and classes ***
|
||||
|
||||
|
|
|
@ -180,6 +180,11 @@ const int SQL_SERVER_2005_DEFAULT_DATETIME_SCALE = 3;
|
|||
const int SQL_SERVER_2008_DEFAULT_DATETIME_PRECISION = 34;
|
||||
const int SQL_SERVER_2008_DEFAULT_DATETIME_SCALE = 7;
|
||||
|
||||
namespace AzureADOptions {
|
||||
const char AZURE_AUTH_SQL_PASSWORD[] = "SqlPassword";
|
||||
const char AZURE_AUTH_AD_PASSWORD[] = "ActiveDirectoryPassword";
|
||||
}
|
||||
|
||||
// types for conversions on output parameters (though they can be used for input parameters, they are ignored)
|
||||
enum SQLSRV_PHPTYPE {
|
||||
MIN_SQLSRV_PHPTYPE = 1, // lowest value for a php type
|
||||
|
@ -1077,6 +1082,7 @@ namespace ODBCConnOptions {
|
|||
const char APP[] = "APP";
|
||||
const char ApplicationIntent[] = "ApplicationIntent";
|
||||
const char AttachDBFileName[] = "AttachDbFileName";
|
||||
const char Authentication[] = "Authentication";
|
||||
const char CharacterSet[] = "CharacterSet";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
#ifdef _WIN32
|
||||
|
@ -1121,6 +1127,7 @@ enum SQLSRV_CONN_OPTIONS {
|
|||
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
|
||||
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
|
||||
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
|
||||
SQLSRV_CONN_OPTION_AUTHENTICATION,
|
||||
#ifdef _WIN32
|
||||
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
|
||||
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
|
||||
|
@ -1190,6 +1197,7 @@ void core_sqlsrv_get_server_version( sqlsrv_conn* conn, _Out_ zval *server_versi
|
|||
void core_sqlsrv_get_client_info( sqlsrv_conn* conn, _Out_ zval *client_info TSRMLS_DC );
|
||||
bool core_is_conn_opt_value_escaped( const char* value, size_t value_len );
|
||||
size_t core_str_zval_is_true( zval* str_zval );
|
||||
bool core_is_authentication_option_valid( const char* value, size_t value_len );
|
||||
|
||||
//*********************************************************************************************************************************
|
||||
// Statement
|
||||
|
|
|
@ -90,7 +90,8 @@
|
|||
#define SQL_COPT_SS_AEKEYSTOREPROVIDER (SQL_COPT_SS_BASE_EX+11) /* Load a keystore provider or read the list of loaded keystore providers */
|
||||
#define SQL_COPT_SS_AEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12) /* Communicate with a loaded keystore provider */
|
||||
#define SQL_COPT_SS_AETRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13) /* List of trusted CMK paths */
|
||||
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14)// Symmetric Key Cache TTL
|
||||
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14) /* Symmetric Key Cache TTL */
|
||||
#define SQL_COPT_SS_AUTHENTICATION (SQL_COPT_SS_BASE_EX+15) /* The authentication method used for the connection */
|
||||
|
||||
/*
|
||||
* SQLColAttributes driver specific defines.
|
||||
|
|
|
@ -186,6 +186,7 @@ const char APP[] = "APP";
|
|||
const char ApplicationIntent[] = "ApplicationIntent";
|
||||
const char AttachDBFileName[] = "AttachDbFileName";
|
||||
const char CharacterSet[] = "CharacterSet";
|
||||
const char Authentication[] = "Authentication";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
#ifdef _WIN32
|
||||
const char ConnectRetryCount[] = "ConnectRetryCount";
|
||||
|
@ -282,6 +283,15 @@ const connection_option SS_CONN_OPTS[] = {
|
|||
CONN_ATTR_STRING,
|
||||
conn_char_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::Authentication,
|
||||
sizeof( SSConnOptionNames::Authentication ),
|
||||
SQLSRV_CONN_OPTION_AUTHENTICATION,
|
||||
ODBCConnOptions::Authentication,
|
||||
sizeof( ODBCConnOptions::Authentication ),
|
||||
CONN_ATTR_STRING,
|
||||
conn_str_append_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::ConnectionPooling,
|
||||
sizeof( SSConnOptionNames::ConnectionPooling ),
|
||||
|
@ -1205,6 +1215,17 @@ int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
|
|||
|
||||
throw ss::SSException();
|
||||
}
|
||||
|
||||
bool valid = true;
|
||||
if( stricmp( SS_CONN_OPTS[i].sqlsrv_name, SSConnOptionNames::Authentication ) == 0 ) {
|
||||
valid = core_is_authentication_option_valid( value, value_len );
|
||||
}
|
||||
|
||||
CHECK_CUSTOM_ERROR( !valid, ctx, SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, SS_CONN_OPTS[ i ].sqlsrv_name ) {
|
||||
|
||||
throw ss::SSException();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,7 +352,8 @@ enum SS_ERROR_CODES {
|
|||
SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING,
|
||||
SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED,
|
||||
SS_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE,
|
||||
SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF
|
||||
SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF,
|
||||
SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION
|
||||
};
|
||||
|
||||
extern ss_error SS_ERRORS[];
|
||||
|
|
|
@ -366,6 +366,10 @@ ss_error SS_ERRORS[] = {
|
|||
"Output or bidirectional variable parameters (SQLSRV_PARAM_OUT and SQLSRV_PARAM_INOUT) passed to sqlsrv_prepare or sqlsrv_query should be passed by reference, not by value."
|
||||
, -61, true }
|
||||
},
|
||||
{
|
||||
SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION,
|
||||
{ IMSSP, (SQLCHAR*)"Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.", -62, false }
|
||||
},
|
||||
|
||||
// internal warning definitions
|
||||
{
|
||||
|
|
63
test/pdo_sqlsrv/pdo_azure_ad_authentication.phpt
Normal file
63
test/pdo_sqlsrv/pdo_azure_ad_authentication.phpt
Normal file
|
@ -0,0 +1,63 @@
|
|||
--TEST--
|
||||
Test the Authentication keyword with options SqlPassword and ActiveDirectoryIntegrated.
|
||||
--SKIPIF--
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("autonomous_setup.php");
|
||||
|
||||
$connectionInfo = " Authentication = SqlPassword; TrustServerCertificate = true;";
|
||||
|
||||
try
|
||||
{
|
||||
$conn = new PDO( "sqlsrv:server = $serverName ; $connectionInfo", $username, $password );
|
||||
echo "Connected successfully with Authentication=SqlPassword.\n";
|
||||
}
|
||||
catch( PDOException $e )
|
||||
{
|
||||
echo "Could not connect with Authentication=SqlPassword.\n";
|
||||
print_r( $e->getMessage() );
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
$stmt = $conn->query( "SELECT name FROM master.dbo.sysdatabases" );
|
||||
if ( $stmt === false )
|
||||
{
|
||||
echo "Query failed.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$first_db = $stmt->fetch();
|
||||
var_dump( $first_db );
|
||||
}
|
||||
|
||||
$conn = null;
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
$connectionInfo = "Authentication = ActiveDirectoryIntegrated; TrustServerCertificate = true;";
|
||||
|
||||
try
|
||||
{
|
||||
$conn = new PDO( "sqlsrv:server = $serverName ; $connectionInfo" );
|
||||
echo "Connected successfully with Authentication=ActiveDirectoryIntegrated.\n";
|
||||
$conn = null;
|
||||
}
|
||||
catch( PDOException $e )
|
||||
{
|
||||
echo "Could not connect with Authentication=ActiveDirectoryIntegrated.\n";
|
||||
print_r( $e->getMessage() );
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Connected successfully with Authentication=SqlPassword.
|
||||
array(2) {
|
||||
["name"]=>
|
||||
string(6) "master"
|
||||
[0]=>
|
||||
string(6) "master"
|
||||
}
|
||||
Could not connect with Authentication=ActiveDirectoryIntegrated.
|
||||
SQLSTATE[IMSSP]: Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.
|
72
test/sqlsrv/sqlsrv_azure_ad_authentication.phpt
Normal file
72
test/sqlsrv/sqlsrv_azure_ad_authentication.phpt
Normal file
|
@ -0,0 +1,72 @@
|
|||
--TEST--
|
||||
Test the Authentication keyword with options SqlPassword and ActiveDirectoryIntegrated.
|
||||
--SKIPIF--
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("autonomous_setup.php");
|
||||
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN')
|
||||
{
|
||||
$connectionInfo = array( "UID"=>$username, "PWD"=>$password,
|
||||
"Authentication"=>"SqlPassword", "TrustServerCertificate"=>true );
|
||||
|
||||
$conn = sqlsrv_connect( $serverName, $connectionInfo );
|
||||
|
||||
if( $conn === false )
|
||||
{
|
||||
echo "Could not connect with Authentication=SqlPassword.\n";
|
||||
print_r( sqlsrv_errors() );
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// echo "Connected successfully with Authentication=SqlPassword.\n";
|
||||
// }
|
||||
|
||||
$stmt = sqlsrv_query( $conn, "SELECT name FROM master.dbo.sysdatabases" );
|
||||
if ( $stmt === false )
|
||||
{
|
||||
echo "Query failed.\n";
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// $first_db = sqlsrv_fetch_array( $stmt );
|
||||
// var_dump( $first_db );
|
||||
// }
|
||||
|
||||
sqlsrv_free_stmt( $stmt );
|
||||
sqlsrv_close( $conn );
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
$connectionInfo = array( "Authentication"=>"ActiveDirectoryIntegrated", "TrustServerCertificate"=>true );
|
||||
|
||||
$conn = sqlsrv_connect( $serverName, $connectionInfo );
|
||||
if( $conn === false )
|
||||
{
|
||||
echo "Could not connect with Authentication=ActiveDirectoryIntegrated.\n";
|
||||
print_r( sqlsrv_errors() );
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Connected successfully with Authentication=ActiveDirectoryIntegrated.\n";
|
||||
sqlsrv_close( $conn );
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Could not connect with Authentication=ActiveDirectoryIntegrated.
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => IMSSP
|
||||
[SQLSTATE] => IMSSP
|
||||
[1] => -62
|
||||
[code] => -62
|
||||
[2] => Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.
|
||||
[message] => Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.
|
||||
)
|
||||
|
||||
)
|
Loading…
Reference in a new issue