SQL Server user name functions - sql

Consider this T-SQL:
CREATE USER my_test_user WITHOUT LOGIN;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
EXECUTE AS USER = 'my_test_user' WITH NO REVERT;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
I'm looking at using these accounts WITHOUT LOGIN for auditing purposes. Basically, my "get a database connection" code returns a connection on which the EXECUTE AS USER...WITH NO REVERT has already been executed.
The problem is that I can't get consistent results from any of these user name functions. The two lines of output are:
dbo dbo original_user original_user original_user
my_test_user my_test_user S-1-9-3-XXXXX.. S-1-9-3-XXXXX.. S-1-9-3-XXXXX..
The USER functions produce correct output AFTER the 'EXECUTE AS', but beforehand they're showing dbo rather than the user name
The SUSER functions are just the opposite -- they're correct initially but after impersonation they're showing some sort of ID
The MSDN docs for SUSER_SNAME explicitly give an example where this is supposed to work.
UPDATE: What I'm looking for is a function that will produce 'original_user' in the first case and 'my_test_user' in the second.

Update: you need the ORIGINAL_LOGIN fn here too
Original:
Afterwards, there is no matching system level user. So, it can't resolve the database level sid, so it simply returns the sid from sys.database_principals
CREATE USER my_test_user WITHOUT LOGIN;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
EXECUTE AS USER = 'my_test_user' WITH NO REVERT;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name(),
SUSER_SID();
SELECT * FROM sys.database_principals WHERE sid = SUSER_SID();
I don't know if this is by design, but it explains where the number comes from. The rest is as expected as explained below
Notes:
You'll get dbo for USER_NAME() because you are logged on with sysadmin rights. Everyone with "sysadmin" is dbo when using db level user functions.
After changing user context, db level user functions resolve to the database user context
For system level user functions, you'll get the login you used before

Users without login are a special case used exclusively for service broker security (remote service bindings) or for code signing. They represent identity, not impersonation. Do not use users without login for EXECUTE AS. You'll run into all sort of edge cases because they explicitly don't have a user to login mapping and almost everywhere a mapping is expected.

Just a guess here, but it looks like to me that the first select is being run as the user you're currently logged into as with the connection, and in the second select you are then telling sql server to execute as the newly created user.

Related

Logins through public role

We are trying to install a release for our application. The program uses 2 SLQ Accounts: SA and SAA2.
SAA2 should be a standard user which can run some Select Statement. SA is a super admin (Captain Obvious).
However we are stuck in 2 different ways:
1) If we grant sysadmin right to SAA2, our scripts could not run because it refers to to the defined schema implemented in login page of the account. As we understood, since it's associated to sysadmin, the default schema change to dbo.
But, the account can login successfully
If we want to resolve it by this way, we have to implements these workaround :
Force account to use his own default schema
Change our scripts with a full name without using schema (not possible)
Invalid object name ...
2) If we want to use SAA2 as a standard accounts (because script are mainly focus on SELECT), MSSSQL refuse the account to connect. Indeed, if we try to simply login using SQL Credentials, as a sysadmin it works, as a standard user, it wont. (like this https://social.msdn.microsoft.com/Forums/sqlserver/en-US/23952fef-7ad7-4374-b7e9-89476a62adc9/users-unable-to-access-their-database-unless-they-are-given-sysadmin-permission?forum=sqlsecurity)
Error number 18456, Severity 14, State 1
We just want to find a way to execute our query, as a sysadmin or not.

SQL Server User Mapping Error 15023

I try to map my other DB to a user by going to Security > Logins > right click someuser > Properties > User Mapping > Select DB > set as db_owner and then ok, but I keep on getting an error saying
User, group, or role 'someuser' already exists in the current database. (Microsoft SQL Server, Error: 15023)
What is causing the error, and how do I map that user to the database?
To fix the user and login mapping you need to open a query window in the SQL Server Management Studio. Enter the following two lines and replace myDB with the database name and myUser with the correct user name:
USE myDB
EXEC sp_change_users_login 'Auto_Fix', 'myUser'
If run successfully you should get an output like this one:
The row for user '****' will be fixed by updating its login link to a login already in existence.
The number of orphaned users fixed by updating users was 1.
The number of orphaned users fixed by adding new logins and then updating users was 0.**
Your user should now be mapped correctly.
Edit:
New way to Resolve/Fix an Orphaned User:
In the master database, use the CREATE LOGIN statement with the SID option to recreate a missing login, providing the SID of the database user.
CREATE LOGIN <login_name>
WITH PASSWORD = '<use_a_strong_password_here>',
SID = <SID>;
To map an orphaned user to a login which already exists in master, execute the ALTER USER statement in the user database, specifying the login name.
ALTER USER <user_name> WITH Login = <login_name>;
When you recreate a missing login, the user can access the database using the password provided. Then the user can alter the password of the login account by using the ALTER LOGIN statement.
ALTER LOGIN <login_name> WITH PASSWORD = '<enterStrongPasswordHere>';
if it is just one or two users, then easiest way is to drop the database user from the restored database, remap the database user to the server login using SSMS. If the server login does not exist then just create it, map the user.
Option 2: If you are migrating a large number of users, use sp_help_revlogin. sp_help_revlogin is a Microsoft supplied stored procedure that will help migrate logins from one server to another, including passwords and SIDs. Here is a good article about it SP_HELP_REVLOGIN : http://www.databasejournal.com/features/mssql/article.php/2228611/Migrating-Logins-from-One-SQL-Server-to-Another.htm
Code patches to help use it :
run following T-SQL Query in Query Analyzer. This will return all the existing users in database in result pan.
USE YourDB
GO
EXEC sp_change_users_login 'Report'
GO
Run following T-SQL Query in Query Analyzer to associate login with the username. ‘Auto_Fix’ attribute will create the user in SQL Server instance if it does not exist. In following example ‘ColdFusion’ is UserName, ‘cf’ is Password. Auto-Fix links a user entry in the sysusers table in the current database to a login of the same name in sysxlogins.
USE YourDB
GO
EXEC sp_change_users_login 'Auto_Fix', 'ColdFusion', NULL, 'cf'
GO
Run following T-SQL Query in Query Analyzer to associate login with the username. ‘Update_One’ links the specified user in the current database to login. login must already exist. user and login must be specified. password must be NULL or not specified
USE YourDB
GO
EXEC sp_change_users_login 'update_one', 'ColdFusion', 'ColdFusion'
GO
2) If login account has permission to drop other users, run following T-SQL in Query Analyzer. This will drop the user.
USE YourDB
GO
EXEC sp_dropuser 'ColdFusion'
GO
Create the same user again in the database without any error.
If you assign permissions to a database user without mapping it to the database first, it throws the error you mentioned.
You should be able to delete the user, map it to the database and then assign the user to the db_owner role.
First drop your user, then execute the script below:
USE [YOURDB]
GO
CREATE USER [USERNAME] FOR LOGIN [USERNAME]
GO
USE [YOURDB]
GO
ALTER USER [USERNAME] WITH DEFAULT_SCHEMA=[dbo]
GO
I had the problem when I was trying to copy a production database to a local test database. In SSMS, I made sure to disconnect from the production server before executing scripts on the local. However, even though I thought I had disconnected, someone pointed out that the title of the production database was still there, and I got errors that objects were already there. The solution was to totally exit from SSMS and start it again, only connecting to the local test database that time.
you can solve problem by expand database ->Security -> Users
and delete the user 'someuser' ,after that go to user mapping and assign.
this problem happen some times because the database user 'someuser' was deleted from 'Logins' in Security section in SSMS and the database still own this user
Create failed for User (Microsoft.SqlServer.Smo)
SQL Server Error User, group, or role already exists in the current database. (Microsoft SQL Server, Error: 15023)
To fix above error delete user under each database individually

Clarification as to why EXECUTE AS USER/LOGIN is not returning the expected results?

I am running the following query against a database:
execute as user = 'domain\username'
select * from fn_my_permissions(null, 'DATABASE')
order by subentity_name, permission_name
revert;
But the following error gets thrown:
Cannot execute as the database principal because the principal "dev\spadmin" does not exist, this type of principal cannot be impersonated, or you do not have permission.
The user is the dbo of the database, and when I open up the properties in management studio, I can see that it is associated with that login. Running EXECUTE AS LOGIN = 'domain\username' does return results, on the other hand. And if I explicitly run EXECUTE AS USER = 'dbo', I get results. I also have a different database where this same scenario returns results with both EXECUTE AS USER and EXECUTE AS LOGIN.
In another scenario with a different user, I have ran EXECUTE AS LOGIN = 'domain\username' and I do not get results, but I do get results with EXECUTE AS USER = 'domain\username'.
Both users in these scenarios are associated with logins that are members of db_owner for the database.
Can anybody tell me why these queries are not returning the results that I expect? And let me know if I am missing any important information. Thanks!
The problem is that because the Login domain\username is the dbo of the database, that also means that the name of their corresponding User within that database is dbo and not domain\username.
run ALTER AUTHORIZATION ON DATABASE::[<yourdb>] TO [sa]
I had the same error for a stored procedure that I wrote.
I found the error was caused by the way I had specified the database name in the query
SELECT emp_no
FROM db_name.employee
WHERE emp_no = 1234
I was executing the procedure on db_name2 once I removed the database name from my script
SELECT emp_no
FROM employee
WHERE emp_no = 1234
it worked fine.
I don't think the reduced access rights of the log allow for the use of other databases or the use db_name command.

SQL Server 2008 Grant Select Permission

I am having trouble adding a user to a test database I set up on my local machine. I have added the user fine but the user does not have permission to SELECT (Or anything else for that matter) on the database. I have tried gone the the permission tab under the server, the database, and the table (there is only one it is a very simple database just for testing) and selected grant for every single option yet it still does not work. I have also tried doing a Transact-SQL command like:
use testing
GRANT SELECT, UPDATE, DELETE, INSERT TO User
and a couple of other combinations that return successfully but I still do not have permission to select data from the table. Any suggestions?
Add the user to the db_datareader role to give the user select access to all of the tables.
Add the user to the public database role and they should be able to SELECT against the database (unless you have changed the public role's permissions).

SQL Select Permissions

I have a database that I need to connect to and select from. I have an SQL Login, let's call it myusername. When I use the following, no SELECT permission shows up:
SELECT * FROM fn_my_permissions ('dbo.mytable', 'OBJECT')
GO
Several times I tried things like:
USE mydatabase
GO
GRANT SELECT TO myusername
GO
GRANT SELECT ON DATABASE::mydatabase TO myusername
GO
GRANT SELECT ON mytable TO myusername
GO
It says the queries execute successfully, but there is never any difference in the first query. What simple thing am I missing to grant database level select permissions.
As a note, I made double sure it was the correct user, correct database, and I have already tried granting table level select permissions. So far I keep getting the error:
SELECT permission denied on object 'mytable', database 'mydatabase', schema 'dbo'.
Any ideas what I'm missing? Thanks in advance.
EDIT/UPDATE:
Upon right clicking the SQL User in SQL Server Management Studio 2008, I discovered every single Database role is checked, including db_denydatareader and db_datareader... might this be blocking my ability to grant permission at the database level? If this is so, what is the purpose of db_denydatareader? It seems silly to me to have a 'DENY' that can't be viewed when querying permissions.
SUMMARY:
Sure enough, that fixed it.
In SSMS - under Databases-->mydatabase-->Security-->Users-->myusername, right click the username, select properties. Under database role membership, make sure db_denydatareader is not checked as this will override whatever permissions you had granted.
Knew it was something simple. :)
Have you tried reconnecting with that SQL user account?