C++ Validating SQL user credentials



What I want to do is rather simplistic but I am having a lot of trouble
finding any information on the best way to do it.

Essentially I have some custom code I built for use in an installer class.
Since the installer itself can't do what I want it to do , I wrote a helper
DLL with exported functions that the installer can call.

All I want to do is take SQL credentials : server, database, username,
password and check to see if I can connect to the DB and login with them. I
want to be able to use either Windows based authentication ( ie: I specify
the windows user account and password and NOT use what account I am logged in
as ) Or to specify a SQL account ( such as sa ) and password. This has to
work with any incarnation of SQL from 2000 onward and the code is written in
C++ in Visual Studio 2003. I cannot use the .Net framwork or any .Net classes
as since this is for an installer there is the potential that nothing has
been installed yet and that I am working on a fresh machine.

Currently, I am using the CDatabase class to do this. But it is not working
for some strange reason. It all seems simple enough, but the class is
returning success for any user and password I give it, even ones I know are
incorrect. I am not trying to do anything complicated but I am being stymied
in my search for a solution. Everything I am finding is for SQL 2005 or .Net
rather than something earlier.

Can anyone help with this? I really need to get this done. My code is below.

SqlDatabaseHandler::Connect( SqlDatabaseHandler::AuthenticationType
authenticationType, char* server, char* database, char* username, char*
password )
{
bool results = false;

CString connectionString = GetConnectionString( authenticationType, server,
dtabase, username, password );

DWORD options = CDatabase::noOdbcDialog;
DWORD cmdResult = NULL;

TRY
{
cmdResult = sqlConnection.OpenEx( connectionString, options );
CString temp = sqlConnection.GetConnect();

cout << "GetString: " << temp << endl;
if ( cmdResult > 0 ) // Successful...
{
results = true;
}
}
CATCH( CDBException, Ex )
{
SqlErrorCode errorCode( Ex );
int error = errorCode.ParseErrorString( );
CString errorMessage;
errorMessage.Append("Cannot connect to ");
errorMessage.Append( server );
errorMessage.Append("\r\n");

switch( error )
{
case SQL_UNABLE_TO_ESTABLISH_CONNECTION:
{
errorMessage.Append("Server not found");
break;
}
case SQL_INVALID_AUTHORIZATION_SPECIFICATION:
{
errorMessage.Append("Invalid authorization for user:" );
errorMessage.Append( username );
break;
}
case EOF:
default:
{
errorMessage.Append( Ex->m_strError );
break;
}

throw Ex;
}

Disconnect( );
MessageBox( this->hWND, errorMessage, "Database Exception", MB_ICONERROR );
}
END_CATCH

return results;
}

CString SqlDatabaseHandler::GetConnectionString(
SqlDatabaseHandler::AuthenticationType authenticationType, char* server,
char* database, char* username, char* password )
{
CString string;

string.Append("DRIVER={SQL Server};");

string.Append( "SERVER=" );
string.Append( server );
string.Append(";");

string.Append( "DATA SOURCE=" );
string.Append( server );
string.Append(";");

string.Append( "DATABASE=");
string.Append( database );
string.Append( ";" );

string.Append("PERSIST SECURITY INFO=FALSE;");
string.Append( "Trusted_Connection=No;");


string.Append( "Username=" );
string.Append( username );
string.Append( ";" );
string.Append( "Password=" );
string.Append( password );
string.Append( ";" );

cout << endl <<endl << "Connection string: " << string << endl << endl;

return string;
};

When I use the above, I input the following connection string:
"DRIVER={SQL Server};SERVER=<<servername>>;DATA
SOURCE=<<servername>>;DATABASE=master;PERSIST SECURITY
INFO=FALSE;Trusted_Connection=No;Username=<<username>>;Password=<<password>>;"


However, when I check the .GetConnect() on the CDatabase object I am using,
I get the following back from it:
"ODBC;DRIVER=SQL Server;SERVER=<<servername>>;UID=;WSID=<<my workstation
name>>;DATABASE=master;Network=DBMSSOCN;Trusted_Connection=Yes"


Obviously my params are hidden to protect the innocent. However my database
param is set to 'master' as I need to be able to validate credentials whether
or not the database for my app actually exists yet. My username & password
are set first to legitmate credentials and then credentials I know are fake.
The net result of this is that no matter what username & password I put in,
the CDatabase call to .OpenEx() returns 1, meaning successful. Even when the
user or password is very obviously not right.

I believe this is because somehow Trusted_Connection=Yes" is being set to
YES even though I explicitly tell it NO.


Can anyone help with this? Or point me to a better API or tool that can do
what I need?

Thanks,
Ed Kramer
.



Relevant Pages

  • RE: C++ Validating SQL user credentials
    ... All I want to do is take SQL credentials: server, database, username, ... CString connectionString = GetConnectionString(authenticationType, server, ...
    (microsoft.public.data.odbc)
  • Re: Design question
    ... username and password on the App Server and Database server and synchronize ... recommend using the stored procedure for security and performance reasons. ...
    (microsoft.public.dotnet.framework.remoting)
  • Re: Securing a SQL Server Database
    ... you cannot block out the server administrator. ... SQL Server, even the SA User, should not be able to access the database. ... my Access database looks for a secret built in UserName and ...
    (microsoft.public.sqlserver.security)
  • Re: cant connect to sql server with domain users? Help....
    ... if you don't have query analizer try this: ... the same problem - Login failed for user 'username'! ... > database as a user, and I used that user to connect the datebase. ... > servers - database server and web server. ...
    (microsoft.public.dotnet.framework.aspnet)
  • RE: No Outlook Email via RDP
    ... Ensure you join the Terminal Server to SBS domain. ... input one SBS domain user's username and password ... | the Wyse Win Terminals accessing email via RDP. ...
    (microsoft.public.windows.server.sbs)