I'm making a call to odbc32.dll (SQLBrowseConnect) to return a list of databases on a sql server.
From running a trace I can see the query being executed is
select name from master..sysdatabases where has_dbaccess(name)=1
If the credentials I pass aren't the sa user it returns just the system databases. Is there anyway I can use SQLBrowseConnect with another user (whose default database is also not guarenteed to be the master database) to return all databases on the server?
Also I want to avoid smo objects
The query does work without sysadmin credentials.
You need to ensure that you / the credentials you are using are at least in the public database role on each of the databases that you need to connect to.
As you would guess, select name from master..sysdatabases returns all database names irrespective of your access to the DB.
Related
It is possible to view and analyze queries in SQL Server before implement on database and log or drop it if necessary?
For example some application send an update query to SQL Server, can I first log it to a database, and then possibly reject it if the query is illegal based on my roles?
You can use SQL Profiler to monitor queries sent to server, but you can't do what you wnat to.
If you say it is illegal for smoe roles to execute some queries it should be specified in permissions - every role have assigned permissions.
One way to achieve what you want is to define user, which mentioned applciation would use (I would even create dedicated user). Then, if you want this user to execute SELECT, just execute such command
GRANT SELECT ON [table] TO [user]
Then the user won't be able to update table, just select rows from it.
I found solution to use SQL SERVER triggers so after insert or update I check my role so if there is any access problem I can rollback transaction and send error to user.
The standard in our company is to log the user name that inserts or updates a record at the time the record is inserted or updated. We inset and update the tables calling stored procedures from applications. We use SUSER_SNAME() in the stored procedures to get the name. Now we've added inserting records in a table on a linked server. The SUSER_SNAME function not is returning the same login name as it does on the native database. Instead it is returning the name of the account created to link with. I know I can pass the user name as another parameter to the query, but it would be easier if there is a built-in function that works both when connected to the server directly, and when connecting to a linked server. Is there a built-in function that does this?
Stored procedure
INSERT INTO Account (ForeignKey, AccountNumber, IsProcessed,
Origin, Updated, LoginName, Total)
VALUES (#ForeignKey, #AccountNumber, #IsProcessed,
GETDATE(), NULL, SUSER_SNAME(), #Total)
RETURN SCOPE_IDENTITY()
No, there's no function to do this. When you create a linked server, the linked server "opens a connection" to the 2nd server. You, the user, have a connection to the 1st server. So when you run suser_sname() on the 1st server, you get your username that you are connected with. When you run it on the 2nd server, you STILL get the user name that you are using to connect to the second server. The difference is that the connection to the 2nd server is controlled by the administrator that configured the Linked Server. In your case, it sounds like he created a special account that is used for a linked server connection. Another option is to map accounts from the current server to accounts on the 2nd server. (If your DBA had done that, you might be getting the results that you want right now and not had any issues.) There are different ways to configure a linked server, and security should generally be a priority when doing so.
So, if you want to execute a query on the 2nd server and use your user name from the 1st server, then you need to pass it to the 2nd server, because it has no way of knowing who you are on a different machine.
I know this can be done in code (C#) by using WindowsIdentity, but is there a way to do this within the SP itself?
I tried using the USER function but it's returning dbo instead of the name. Is this because the user is the owner of the database? If that's so, how can I get the db owner's login name?
EDIT:
The application that executes the SP uses the sa user account, so if I use SYSTEM_USER, the returned value is sa.
SELECT SYSTEM_USER
Will return name of user which excecute code in SQL. More in this aricle
If SQL server service work from sa there is no way to get (windows) username from SQL Server side. I suppose it is security issue. Most information about connection to your SQL Server you may get from table sys.dm_exec_connections. There are stored IP addreses and port s and other useful things for existings connections.
I have many databases in one SQL Server instance. Also I have many individual domain users for logins and also domain groups as logins. These logins are attached to databases as database users. Now I would like to create a report (or a query) to find out when and where (which database) these logins take a connection. I tried to find this information from sys-schema, but I could not find this kind of information. Where SQL Server store this information and how to create this kind of report? I would also like to automate this using a stored procedure.
in the login stored procedure, along with the username, add a GetDate() and DB_NAME() to each record in a table called LoginData (or whatever you prefer)
You could set up a SQL trace logging all login events then just query that.
I have several stored procedures in my database that are used to load data from a datamart that is housed in a separate database. These procedures are, generally, in the form:
CREATE PROCEDURE load_stuff
WITH EXECUTE AS OWNER AS
INSERT INTO my_db.dbo.report_table
(
column_a
)
SELECT
column_b
FROM data_mart.dbo.source_table
WHERE
foo = 'bar';
These run fine when I execute the query in SQL Server Management Studio. When I try to execute them using EXEC load_stuff, the procedure fails with a security warning:
The server principal "the_user" is not able to access the database "data_mart" under the current security context.
The OWNER of the sproc is dbo, which is the_user (for the sake of our example). The OWNER of both databases is also the_user and the_user is mapped to dbo (which is what SQL Server should do).
Why would I be seeing this error in SQL Server? Is this because the user in question is being aliased as dbo and I should use a different user account for my cross-database data access?
Edit
I understand that this is because SQL Server disables cross database ownership chaining by default, which is good. However, I'm not sure of the best practice in this situation. If anyone has any input on the best practice for this scenario, it would be greatly appreciated.
Edit 2
The eventual solution was to set TRUSTWORTHY ON on both of the databases. This allows for limited ownership chaining between the two databases without resorting to full database ownership chaining.
Why not remove EXECUTE AS OWNER?
Usually, my user executing the SP would have appropriate rights in both databases, and I don't have to do that at all.
There is no need to create login, you can just enable guest user in target DB.
grant connect to guest
This allows executing user to enter DB under guest context, and when "db chaining is ON access will not be checked in target DB.
Actually, DBO is a role (you can consider it as a group of users), not a user in himself. (Unless you can connect to SQL SERVER using dbo:passwordfordbo it's not a user).
Usually, in the wonderful world of SQL Server, if you grant userX right to execute storedprocY then X gets the right to perform all the task Y contains even if he doesn't have all the permission on all the objects used in Y.
That's an extremely useful feature to encapsulate business logic in a stored procedure. (Your user have NO access on the table but they do can EXECUTE one stored proc).
When we talk about "ownership chaining" it means the following (please correct me if I am wrong though)
- If ownership chaining is disabled: the right to execute procedureX will work as long as all the required objects are in the same database
- Of chaining is enabled: That "privilege" will expands towards all databases.
Hope that helps,