obtain the real identity of the connected user - sql-server

dxStatusbar1.Panels1.Text :=
DataModule2.UniConnectDialog1.Connection.Username;
...gives me the username that has connected to sql server.
However the connected user has a different name in the actual database.
Example:
His login name for the sql server is 'John' and is user mapped to 'Northwind' database.
However in 'Northwind' database he is called 'John Smith'.
And this is the name (John Smith) I am trying to have displayed in dxStatusbar1.Panels1.Text
after he connects.
How can I get that ?
edit :
Tried Victoria suggestion :
UserName := DataModule2.UniConnection1.ExecSQL('SELECT :Result = CURRENT_USER', ['Result']);
dxStatusbar1.Panels[1].Text := UserName;
but get :

I couldn't find any UniDAC API way to get currently connected user name (not even for SDAC), so I would just issue a SQL command querying CURRENT_USER and grab the name from the result:
SELECT CURRENT_USER;
Or in the Unified SQL way with the USER function:
SELECT {fn USER};
Since you've mentioned stored procedure in your comment, it sounds to me like you probably want to get this information directly from a connection object without using query object. If that is so, you don't even need to have a stored procedure but execute directly command like this:
var
UserName: string;
begin
UserName := UniConnection1.ExecSQL('SELECT :Result = CURRENT_USER', ['Result']);
...
end;
Or in unified way:
var
UserName: string;
begin
UserName := UniConnection1.ExecSQL('SELECT :Result = {fn USER}', ['Result']);
...
end;

One of these might do the job for you. Haven't tested.
SELECT ORIGINAL_LOGIN()
SELECT SYSTEM_USER
SELECT SUSER_SNAME()
Hope it helps.
ORIGINAL_LOGIN: Returns the name of the login that connected to the instance of SQL Server. You can use this function to return the identity of the original login in sessions in which there are many explicit or implicit context switches.
SYSTEM_USER: Allows a system-supplied value for the current login to be inserted into a table when no default value is specified.
SUSER_SNAME: Returns the login name associated with a security identification number (SID).

Related

Modifying values in master..sysprocesses [Sybase]

Is there a way to modify the column program_name in table master..sysprocesses?
I have found two methods, but both set the name during the creation of the connection:
Using parameter appname when executing an isql command
Adding parameter APP= in a connection string when opening an ODBC connection.
I am looking for a way to modify it AFTER it has been created.
I tried the following example:
sp_configure "allow updates",1
go
UPDATE master..sysprocesses
SET program_name = 'test'
where hostname = 'server'
and hostprocess = '23240'
go
sp_configure "allow updates",0
go
But failed:
Could not execute statement.
Table 'sysprocesses' can't be modified.
Sybase error code=270
Severity Level=16, State=1, Transaction State=0
Line 4
You can continue executing or stop.
Changes to column sysprocesses.program_name are not allowed after its been created. But there are three columns in sysprocesses which can be changed after creation of the connection
sysprocesses.clientname
sysprocesses.clientapplname
sysprocesses.clienthostname
Exerpt from the Sybase Infocenter website:
Changing user session information
The set command includes options
that allow you to assign each client an individual name, host name,
and application name. This is useful for differentiating among clients
in a system where many clients connect to Adaptive Server using the
same name, host name, or application name.
The partial syntax for the set command is:
set [clientname client_name | clienthostname host_name | clientapplname application_name]
where:
client_name – is the name you are assigning the client.
host_name – is the name of the host from which the client is
connecting.
application_name – is the application that is connecting to Adaptive
Server.
These parameters are stored in the clientname, clienthostname, and
clientapplname columns of the sysprocesses table.
For example, if a user logs in to Adaptive Server as "client1", you
can assign them an individual client name, host name, and application
name using commands similar to:
set clientname 'alison'
set clienthostname 'money1'
set clientapplname 'webserver2'
.
.
.
Use the client’s system process ID to view their connection
information. For example, if the user “alison” described above
connects with a spid of 13, issue the following command to view all
the connection information for this user:
select * from sysprocesses where spid = 13
To view the connection information for the current client connection (for example, if the user “alison” wanted to view her own connection information), enter:
select * from sysprocesses where spid = ##spid

How to insert username in VS2008(report edition)

I'm creating a new report (*.rdl), and there I want to add username who runs the script (insert).
I've tried on VS2008 through "built-in-fields" function which is "User ID", but it didn't work:
CREATE TABLE #Some_Table
(
Plan_date date null,
Plan_customer int null,
creator_id nvarchar(55) null
)
INSERT INTO Some_Table
(
[Plan_date] ,
[Plan_customer],
[creator_id]
)
SELECT
#p_plan_monthly,
#p_plan_clients,
#creator_id ="user id" --from built-in-fields
Expected result is: Column creator_id is filling with value of username from active directory who made insert through my report.
To reiterate my comment, as it's is incredibly important:
"You need to use a different account to access your data #whitefang. The sa account should never be used for something as mundane as a report. In truth it should never be used unless you really need sysadmin privileges, or you're doing something like recovering the server. You should have a service account that can do the respective tasks it needs to. If you can suffer injection through those reports, you're service is like an open book to whomever has access."
Now, onto your problem. I would add a further internal parameter on your report. Change the value of the parameter to have the default value of =User!UserID; this will be the ID of the user running the report (perhaps something like StackOverflow\Larnu).
Then map that report parameter to your dataset parameter #creator_id and change your INSERT statement to:
INSERT INTO Some_Table ([Plan_date],
[Plan_customer],
[creator_id])
VALUES (#p_plan_monthly, #p_plan_clients, #creator_id);
Q: "and there I want to add username who runs the script (insert)"
You can use these functions.
-- database user name
SELECT USER_NAME()
-- login identification name
SELECT SUSER_NAME()

SQL Server: Users & Logins — Where does the user name come in?

I am trying to get a better understanding of the distinction between users & logins. I know how to create them, and I understand that they are required, but I don’t yet understand how SQL Server uses this distinction.
As far as I understand, a login has access to the Server, while a user has access to a database and its objects.
If I execute the following:
CREATE LOGIN fred WITH PASSWORD='…';
USE stuff;
CREATE USER wilma FOR LOGIN fred;
USE nonsense;
CREATE USER pebbles FOR LOGIN fred;
Then I have a Login of fred with two user names associated with two databases. My guess is that these user names can be regarded as aliases for fred.
I undersand that it is common to use the same username as the login name, but clearly not necessary.
The next step is to login as fred. I cannot login as one of the users.
At this point, I don’t see what happens next. How do I become one of the users, and what would do for me?
You never authenticate as a user.You authenticate as a login, which then maps to a single user in zero or more databases.
Create the login
CREATE LOGIN fred WITH PASSWORD='fredsecret', CHECK_POLICY = OFF;
GO
Create the users
USE stuff;
CREATE USER wilma FOR LOGIN fred;
GO
USE nonsense;
CREATE USER pebbles FOR LOGIN fred;
GO
Change context so it looks like I'm fred
SELECT SUSER_SNAME() --gbn
EXECUTE AS LOGIN = 'fred'
SELECT SUSER_SNAME() --fred
Note the differences
USE stuff
SELECT SUSER_SNAME(), USER_NAME()
USE nonsense;
SELECT SUSER_SNAME(), USER_NAME()
GO
and go back to me
REVERT
The name of the login (fred in this case) is only used for authentication to SQL Server. After authentication you mostly use the sid value: which links login (server principal) and user (database principal)
SELECT name, sid FROM sys.server_principals
USE stuff
SELECT name, sid FROM sys.database_principals
USE nonsense
SELECT name, sid FROM sys.database_principals
In my case, it is 0xC7C14DE4BFDF2445A7DABE158CC399F0
Note, sid is unique in a database. This will fail
USE nonsense;
CREATE USER barney FOR LOGIN fred;
GO
Msg 15063, Level 16, State 1, Line 10
The login already has an account under a different user name.
You connect to the server under the login, on base stuff will be CURRENT_USER wilma and on nonsense CURRENT_USER = pebbles

Retrieving Oracle Password_Verify_Function

I am an IS auditor and I would like to check how we can retrieve the PASSWORD_VERIFY_FUNCTION assigned to users. I understand the script utlpwdmg.sql can be executed to setup the default password resource limits.
If changes were made using ALTER PROFILE, the script utlpwdmg.sql will not show the latest settings.
Please let me know what SQL commands I can execute to show what is the PASSWORD_VERIFY_FUNCTION stored and used in the system.
You can use this query to see source code of stored proc:
--Source of all password functions.
select *
from dba_source
where owner = 'SYS'
and name in
(
--The name of all password functions in use.
--See DBA_USERS.PROFILE to determine which user is using which profile.
select limit
from dba_profiles
where resource_name = 'PASSWORD_VERIFY_FUNCTION'
--Yes, this is intentionally the string 'NULL', that's what Oracle uses here.
and limit <> 'NULL'
)
order by name, line;
To find out what users are using PASSWORD_VERIFY_FUNCTION, you need to find out which profiles are using the function and then see which users are assigned that profile.
select profile from dba_profiles where limit = 'PASSWORD_VERIFY_FUNCTION';
select username from dba_users where profile = ;

database usernames and passwords in delphi

Using Delphi XE2.
I have a database with a table in it called users. It has a user_id field, username field, a password field and an Active field in it. (the user_id is a unique number that identifies each user... 1,2,3 etc).
I am writing a database software package which requires username and passwords to login to it. (I already have a login form created).
How do I get it to match/check the usernames and passwords in the database then allow user to continue into the software? Also I would like the Active Field to store in the database 'Y' if user is logged in or 'N' if user is not logged in. Is this doable?
I am connected to the users table via TADQuery and TDataSource.
Example below of function which I thought would get me started(calling it at point of clicking the login button on the login form).
function TfrmLogin.CheckUser: Boolean;
begin
while not dmData.qryUser.Eof do
begin
if(editName.Text <> qryUser.FieldByName('uname').AsString) or (editPassword.Text <> qryUser.FieldByName('pword').AsString)
then ShowMessage('Username and/or Password not recognised');
Exit;
End;
Looping through all rows in the database will not suffice, especially when you get more than a handful of users. You need to SELECT from the database for the specific user, and see if you get results back. You can do the SELECT based just on the username:
qryUser.SQL.Text := 'SELECT uname, pword FROM users WHERE uName = :uname';
qryUser.ParamByName('uname').AsString := editName.Text;
try
qryUser.Open;
if qryUser.IsEmpty then // No record found for user
// Handle error
else
begin
if qryUser.FieldByName('pword').AsString <> editPassword.Text then
// Handle password mismatch;
end;
finally
qryUser.Close;
end;
It's not clear from your question which database components you're using (TADQuery might be a typo for TADOQuery, or it might be something else). If in fact it is TADOQuery, you'll need to make a couple of small changes to the code. (Actually, only three minor changes; two in the assignment of the parameter and one that reads the password value.)
qryUser.SQL.Text := 'SELECT uname, pword FROM users WHERE uName = :uname';
qryUser.Params.ParamByName('uname').Value := editName.Text;
try
qryUser.Open;
if qryUser.IsEmpty then // No record found for user
// Handle error
else
begin
if qryUser.FieldByName('pword').Value <> editPassword.Text then
// Handle password mismatch;
end;
finally
qryUser.Close;
end;
I'm with Sam, if possible do not store passwords in the database. If the database supports Active Directory Authentication (MS/SQL, Oracle, DB2, MySQL, SyBase) use the user name and password to validate against Active Directory before trying a connection to the database. Then only store the user name and active flag in the Users table.
This function ask Active Directory if the user and password are valid, before you ever try to make a connection to the database. Then you can build your connection parameters to the database (I assume you are using FireDAC and a TADConnection see here for instructions). Try to open the connection, if it fails the user does not have access to the database at all. If it passes, then query the Users table like Ken suggest but test the active field instead of the password. This way no one can see a users password and you do not have to manage passwords in your application. By using this method someone still needs to know a users Active Directory password to access your application even though your using Active Directory Authentication on the database.
function TfrmPassword.ActiveDirectoryValidate: Boolean;
var
LHandle: THandle;
lDomainName: String;
begin
Screen.Cursor := crHourglass;
try
// Get the Domain Name
lDomainName := GetEnvironmentVariable('USERDOMAIN');
// Test the user Logon
Result := LogonUser(PWideChar(edtUserID.Text),
PWideChar(lDomainName),
PWideChar(edtPassword.Text),
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
LHandle);
// If True, we got a Handle, so close it
if Result then
CloseHandle(LHandle);
finally
Screen.Cursor := crDefault;
end;
end;

Resources