зеркало из https://github.com/microsoft/msphpsql.git
Implemented Azure AD plus tests
This commit is contained in:
Родитель
ae0368f8d2
Коммит
1e527865a9
|
@ -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 )
|
||||
{
|
||||
// first need to check if the option for Authention 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,12 @@ 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 +1083,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 +1128,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 +1198,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, ODBCConnOptions::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
|
||||
{
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
--TEST--
|
||||
Test the Authentication keyword and its accepted values: SqlPassword and ActiveDirectoryPassword.
|
||||
--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.
|
|
@ -0,0 +1,74 @@
|
|||
--TEST--
|
||||
Test the Authentication keyword and its accepted values: SqlPassword and ActiveDirectoryPassword.
|
||||
--SKIPIF--
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("autonomous_setup.php");
|
||||
|
||||
$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_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--
|
||||
Connected successfully with Authentication=SqlPassword.
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(6) "master"
|
||||
["name"]=>
|
||||
string(6) "master"
|
||||
}
|
||||
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.
|
||||
)
|
||||
|
||||
)
|
Загрузка…
Ссылка в новой задаче