List the User mapped to a Login on one particular database - sql

I'm back here with a SQL User/Login problem.
First off all i'm working on SQL server 2008 and i'm not the master on that server.
On that SQL server i have different Login and these Login are mapped to a USER to my database 'DB_MyDataBase'.
Indeed, i have 10 different Login mapped to 10 different User on my database 'DB_MyDataBase'.
For i.e., when i'm connecting to the SQL server with a Login 'Laurent', That SQL Login 'Laurent' is the USER 'Laurel' on my database 'DB_MyDataBase'. For the moment, no problem.
But now for that 10 different Login and want to know their respective USER for my database 'DB_MyDataBase'.
After some research i've found a request that can do "the job"
sp_msloginmappings 'Laurent', 1
Normally, that show mapping user account info in current databases context for login account 'Laurent'
But when i tried it, i had a error message.
Nom d'objet 'dbo.syslogins' non valide.
Error message is : Object name 'dbo.syslogins' is not valid for non French users.
I've found another request which is working "a bit".
SET NOCOUNT ON
CREATE TABLE #temp
(
SERVER_name SYSNAME NULL ,
Database_name SYSNAME NULL ,
UserName SYSNAME ,
GroupName SYSNAME ,
LoginName SYSNAME NULL ,
DefDBName SYSNAME NULL ,
DefSchemaName SYSNAME NULL ,
UserID INT ,
[SID] VARBINARY(85)
)
DECLARE #command VARCHAR(MAX)
--this will contain all the databases (and their sizes!)
--on a server
DECLARE #databases TABLE
(
Database_name VARCHAR(128) ,
Database_size INT ,
remarks VARCHAR(255)
)
INSERT INTO #databases--stock the table with the list of databases
EXEC sp_databases
SELECT #command = COALESCE(#command, '') + '
USE ' + database_name + '
insert into #temp (UserName,GroupName, LoginName,
DefDBName, DefSchemaName,UserID,[SID])
Execute sp_helpuser
UPDATE #TEMP SET database_name=DB_NAME(),
server_name=##ServerName
where database_name is null
'
FROM #databases
EXECUTE ( #command )
SELECT loginname ,
UserName ,
Database_name
FROM #temp
WHERE LoginName = 'Laurent'
So that one is working it's listing all User mapped to that Login on every database BUT (there is always a "but"...) it's only working with the Login i use to connect.
For i.e. When i connect to the SQL server with Login 'Laurent' the previous request is working because i request for the same Login that i used to connect to the SQL server but when i connect with Login 'Laurent' and do the previous request with a different Login (so not 'Laurent' but another one which have a user mapped to my database 'DB_MyDataBase'.) I don't see anything, it returns me blank column....
Maybe it's because i'm not master on that SQL server.
So how i can list User mapped to a Login different from the one i'm connected?
I hope my question is clear enough (sorry for long text) and thanks for your future answer. Don't hesitate to ask me if you need further info to answer me.

What you can see will depend on the permissions of the user you are logged in as. This query against two of the security catalog views should give you what you want provided you have the necessary permission.
select
dp.name as UserName,
sp.name as LoginName
from
sys.database_principals dp
left join sys.server_principals sp on sp.sid = dp.sid
where
dp.type in ('S', 'U')

Related

Identifying a User and a Machine [duplicate]

My work company has a MSSQL server 2005. I have two questions about finding out current log user and any way to send out a warning message:
First question is if there is any T-SQL or SP available to find out current login user name and machine name. If the user is using SQL server sa name to remotely access to SQL server, is there any way to find out that user's windows name (the name to log to the windows)?
My next question is that if I can get the user name or id, is there any way to send out a warning message such as "currently SQL server is clean up or backup, please do not log in at this time". I guess it may be difficult. I may have to send an email out to the user.
The SQL server is only accessible in the company. The SQL server has a list of users as login users: windows users, SQL users and sa.
SELECT SUSER_SNAME(), HOST_NAME()
If the connection is "sa" (or any other SQL login) then you can't find the domain/windows user name. SQL Server only knows it's "sa" or that SQL login.
HOST_NAME may not be reliable either, it can be set in the connection string ("Application Name"). Or it could be vague eg "Microsoft Office" for by default for Access, Excel etc
You could backtrack via client_net_address in sys.dm_exec_connections and match MAC address to IP and find out who is logged on...
An easy way to find out both host and user is
EXEC sp_who2;
where you get some other information that can be good to know, as if the user is active and so on...
It does not resolve the issues that gbn announced.
Thanks for all your suggestions first. I tried all the methods and I think Joakim Backman's method meet my need. Here is summary of what I find out.
Query of sys.syslogins only list login information. The accdate does not give the current login user timestamp. I tried to login from another application to my SQL and this query does not list the login.
SELECT SUSER_SNAME(), HOST_NAME() only list one user on SQL server. For example, I log in in as my name to SQL server. The result of this query only lists my name and machine name. This query does not list current users on the SQL server.
exec sp_who2 lists information I need. It lists current user name machine name, active status, db name user's access, and command used.
In order to get the information I use in SP, I have to filter and join the information with other tables, such as emails. Here is the codes I use:
DECLARE #retTable TABLE (
SPID int not null
, Status varchar (255) not null
, Login varchar (255) not null
, HostName varchar (255) not null
, BlkBy varchar(10) not null
, DBName varchar (255) null
, Command varchar (255) not null
, CPUTime int not null
, DiskIO int not null
, LastBatch varchar (255) not null
, ProgramName varchar (255) null
, SPID2 int not null
, REQUESTID INT
)
INSERT INTO #retTable EXEC sp_who2
SELECT Status, Login, HostName, DBName, Command, CPUTime, ProgramName -- *
FROM #retTable
--WHERE Login not like 'sa%' -- if not interested in sa
ORDER BY Login, HostName

check for commonly used passwords on SQL Server

NCSC has published a list of the 100.000 most used passwords, see 100K passwords
I wondered if any of my users had used one of these passwords, so I wrote a check, inspired by an idea from bp_check.
Am I doing it the correct way?
I had problems with UniCode, but that should have been solved by now.
Here is my code to run such a password check:
-- script to check if any of the passwords on your SQL Server is amongst the 100.000 most used passwords that Troy Hunt and NCSC released
-- see https://www.ncsc.gov.uk/blog-post/passwords-passwords-everywhere
--drop table dbo.PwnedPasswordTop100k
create table dbo.PwnedPasswordTop100k ( pw nvarchar(500) collate Latin1_General_CS_AS not null)
go
bulk insert dbo.PwnedPasswordTop100k
FROM 'c:\temp\PwnedPasswordTop100k.txt'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
, codepage=65001
)
go
SELECT sl.name , ppt.pw
from sys.sql_logins sl
cross join dbo.PwnedPasswordTop100k ppt
where PWDCOMPARE(ppt.pw, sl.password_hash) = 1
union all
SELECT s.name, 'password is NULL' FROM sys.sql_logins s -- password is null (from idea from BP_Check http://aka.ms/BPCheck;)
where password_hash is null
AND exists(SELECT * FROM fn_my_permissions(NULL, 'SERVER') where permission_name='CONTROL SERVER')
and name NOT IN ('MSCRMSqlClrLogin','##MS_SmoExtendedSigningCertificate##','##MS_PolicySigningCertificate##','##MS_SQLResourceSigningCertificate##','##MS_SQLReplicationSigningCertificate##','##MS_SQLAuthenticatorCertificate##','##MS_AgentSigningCertificate##','##MS_SQLEnableSystemAssemblyLoadingUser##')
union all
SELECT s.name, s.Name FROM sys.sql_logins s -- password the same as login (from idea from BP_Check http://aka.ms/BPCheck;)
where PWDCOMPARE(s.name, s.name) = 1
union all
select 'not SYSADM', 'You do not have CONTROL SERVER permissions, and cannot see any password_hashes'
where not exists(SELECT * FROM fn_my_permissions(NULL, 'SERVER') where permission_name='CONTROL SERVER')
--select top (10000) * from dbo.PwnedPasswordTop100k where pw like N'пїЅпїЅпїЅпїЅ'
begin try
drop table dbo.PwnedPasswordTop100k
end try
begin catch
end catch
The PwnedPasswordTop100k.txt file must be copied to c:\temp on the SQL Server, and the account that runs SQL Server, must have access to the file. Alternatively, change the path to a place which the SQL Server can see.
Not everyone has access to a share that SQL Server can see. So I've also written a script with all the passwords:
Script with 100.000 passwords
It is a SELECT Statement that is 1500 kB. Quite big, but you can run it in SQL Server Management Studio.
My SQL Server can check about 6 users per minute, so the script is not very fast.

Find all databases where particular user exists and its role

I have a huge instance containing 1000+ databases. I need to find a way to query entire instance and find databases that contain particular user and what role this user has. I am not interested whether the user is orphanded. I just want to know which databases have this user and which do not.
Lets say that my user is called TestUser. Databases that do not contain this user should return NULL.
I would like the results in the following format:
Column1 - Database Name
Column2 - UserName (if exists or else NULL)
Column3 - UserRole (if exists or else NULL)
Under the assumption that you are not looking for issuing 1000+ selects, one (extremely ugly) solution would be:
SELECT 'DB_1' , UserName , UserRole
FROM DB_1.UsersTable
WHERE Username = 'TestUser'
UNION
SELECT 'DB_2' , UserName , UserRole
FROM DB_2.UsersTable
WHERE Username = 'TestUser'
:
:
Another solution is to use DYNAMIC SQL:
Collect the list of all the DBs that you to check,
Build a string hosting a select statement like the one above,
Execute the statement.
Again, both methods are shameful.
create table #temp
(
dbname sysname,
dbrole sysname,
dbuser sysname
)
Exec sp_msforeachdb '
if db_id()>4
Begin
insert into #temp
select db_name(), rp.name as database_role, mp.name as database_user
from sys.database_role_members drm
join sys.database_principals rp on (drm.role_principal_id = rp.principal_id)
join sys.database_principals mp on (drm.member_principal_id = mp.principal_id)
End
'
The Roles Part is referenced from here:
Get list of all database users with specified role

Changes to sysusers and sysxlogins in SQL 2008

I am currently updating a MS SQL 2000 server to SQL 2008. One of the issues highlighted by the Upgrade advisor is that the undocumented table sysxlogins has been removed.
I currently have a procedure that is run by a user 'foo' to determine if the user 'bar' exists in the database blah. If the user exists the user's password is compared to the password that was passed in to the procedure in order to determine if bar is allowed to log in to an application, it looks like this:
#UserName Varchar(50),
#Password Varchar(50)
As
Set NoCount On
------------------------------------------------------------------------------------
-- Check username
------------------------------------------------------------------------------------
If Exists
(
select top 1 name
from blah.dbo.sysusers With (NoLock)
where name = #UserName
)
Begin
------------------------------------------------------------------------------------
-- Check Password
------------------------------------------------------------------------------------
If Not Exists
(
Select *
From master.dbo.sysxlogins With (NoLock)
Where srvid IS NULL
And name = #Username
And ( ((#Password is null) or (#Password = '') and password is null)
Or (pwdcompare(#Password, password, (CASE WHEN xstatus&2048 = 2048 THEN 1 ELSE 0 END)) = 1))
)
Begin
Return 2
End
Else
Begin
------------------------------------------------------------------------------------
-- Check Role
------------------------------------------------------------------------------------
Select usg.name
From blah.dbo.sysusers usu
left outer join (blah.dbo.sysmembers mem inner join blah.dbo.sysusers usg on mem.groupuid = usg.uid) on usu.uid = mem.memberuid
left outer join syslogins lo on usu.sid = lo.sid
where usu.name = #Username
and usg.name not like 'db_%'
Return 0 -- Username and password correct
End
End
Else
Begin
Return 1 -- Username incorrect
End
This all works fine under SQL 2000, yet I must now pay the price of using undocumented system tables and make it work under 2008.
There are two problems with this, the first problem is that foo can no longer see all of the database users when executing:
select * from blah.dbo.sysusers
or Microsoft's recommended alternative:
select * from blah.sys.database_principals
I understand that this is due to the fact that members of the public role no longer have access to object meta data unless they are a member of sysadmin or have the View Definition permission on the object.
It is not possible for foo to be a member of sysadmin, so as far as I understand I need to grant foo the View Definition permission, but on which object? I don't think I do it on the system view, so do I do it on every single user?
Secondly, and similarly, I need to change my reference to sysxlogins to sys.sql_logins. Again foo can only see itself and sa when executing
select * from sys.sql_logins
How can I get foo to see all of the server logins in this list?
There will no doubt be similar problems when accessing sysmembers and syslogins later on in the code but hopefully an understanding of the two examples above will help me to sort the rest out.
Thanks in advance,
You can grant the SELECT right directly on sys.database_principals, as long as the login has a user in the master database. For example:
use master
create user MyUser for login MyUser
grant select on sys.database_principals to MyUser
Then, in SQL Server 2008, passwords are encrypted, even for the administrator. You can, however, verify a password by trying to change it. The change procedure will give an error if the old password is incorrect.
declare #rc int
begin try
exec #rc = sp_password 'welcome', 'welcome', 'MyUser'
end try
begin catch
set #rc = ERROR_NUMBER()
end catch
-- Should be 0 on success
select #rc
For this to work, you have to disable Enforce password policy in the Login Properties dialog. Otherwise, the policy would prevent you from changing your password too often.
I think GRANT SELECT ON... is more troublesome as one have to add the user to the master database. The below was the solution for me:
USE master
GRANT VIEW ANY DEFINITION TO foo
If you have an app that works on various versions of SQL you need to check if the server version is higher then 8 (GRANT VIEW ANY DEFINITION works from SQL 2005 though it seemes not be needed there).

How to find out user name and machine name to access to SQL server

My work company has a MSSQL server 2005. I have two questions about finding out current log user and any way to send out a warning message:
First question is if there is any T-SQL or SP available to find out current login user name and machine name. If the user is using SQL server sa name to remotely access to SQL server, is there any way to find out that user's windows name (the name to log to the windows)?
My next question is that if I can get the user name or id, is there any way to send out a warning message such as "currently SQL server is clean up or backup, please do not log in at this time". I guess it may be difficult. I may have to send an email out to the user.
The SQL server is only accessible in the company. The SQL server has a list of users as login users: windows users, SQL users and sa.
SELECT SUSER_SNAME(), HOST_NAME()
If the connection is "sa" (or any other SQL login) then you can't find the domain/windows user name. SQL Server only knows it's "sa" or that SQL login.
HOST_NAME may not be reliable either, it can be set in the connection string ("Application Name"). Or it could be vague eg "Microsoft Office" for by default for Access, Excel etc
You could backtrack via client_net_address in sys.dm_exec_connections and match MAC address to IP and find out who is logged on...
An easy way to find out both host and user is
EXEC sp_who2;
where you get some other information that can be good to know, as if the user is active and so on...
It does not resolve the issues that gbn announced.
Thanks for all your suggestions first. I tried all the methods and I think Joakim Backman's method meet my need. Here is summary of what I find out.
Query of sys.syslogins only list login information. The accdate does not give the current login user timestamp. I tried to login from another application to my SQL and this query does not list the login.
SELECT SUSER_SNAME(), HOST_NAME() only list one user on SQL server. For example, I log in in as my name to SQL server. The result of this query only lists my name and machine name. This query does not list current users on the SQL server.
exec sp_who2 lists information I need. It lists current user name machine name, active status, db name user's access, and command used.
In order to get the information I use in SP, I have to filter and join the information with other tables, such as emails. Here is the codes I use:
DECLARE #retTable TABLE (
SPID int not null
, Status varchar (255) not null
, Login varchar (255) not null
, HostName varchar (255) not null
, BlkBy varchar(10) not null
, DBName varchar (255) null
, Command varchar (255) not null
, CPUTime int not null
, DiskIO int not null
, LastBatch varchar (255) not null
, ProgramName varchar (255) null
, SPID2 int not null
, REQUESTID INT
)
INSERT INTO #retTable EXEC sp_who2
SELECT Status, Login, HostName, DBName, Command, CPUTime, ProgramName -- *
FROM #retTable
--WHERE Login not like 'sa%' -- if not interested in sa
ORDER BY Login, HostName