multi-user MS Access Database- how to lock completely - c#

We have an MS Access database (accdb) out on our network, that multiple users will edit & read by means of a .NET application. I am aware that a server db such as SQL Server would be the best choice for this situation, but currently that's out of my hands.
The .Net application will use both ADO.Net (ie OleDBConnections) and the tools inside the Microsoft.Office.Interop.Access.Dao namespace to connect to the database.
I have read a few articles and posts about multiple users connecting to Access, and there seems to be some confusion and differing opinions about Access's capabilities in this regard. How/can I achieve the following in my application:
Establish connections to write to the database, that will lock the entire database (all records and tables) until the connection is ended. If other users attempting to write simultaneously are halted by an exception, that is okay.
Establish connections designated as read-only, that have no conflicts with any other user's actions.
Thanks.

To open a ACCDB in exclusive mode you need to add this key/value to your connection string
Mode=Share Exclusive;
This will block other user to connect to the same database until you close and dispose the
connection that opens the database in this way.
If I remember well, the possible values (pretty self explanatory) for the Mode keyword in the JET connection string are
Mode='Read';
Mode='Write';
Mode='ReadWrite';
Mode='Share Deny None';
Mode='Share Deny Read';
Mode='Share Deny Write';
Mode='Share Exclusive';
I have tried various combination of the flags above, but I can't find a simple solution that allows a single connection to be opened in ReadWrite while the following connections fall back to Read Only automatically. Probably in your scenario the best path is to have a local connection (not a global one), try to open it in Share Exclusive if you need to write to the database and catch the exception if you cannot open the database giving the user a Retry option. Not an easy path I know. Let's see if a user with a better knowledge of MS-Access could give a more elaborate solution.
I agree with the comment above (and your own assesment) that this is not the best database tool to use in situations of concurrency, however things are a lot better now.
I find this answer well written, comprensive and with a balanced view of the strength and weakness of Access about concurrency issues.

Related

Securing sqllite database in WPF application

Hi I have a wpf application, developed using C# .net, and framework used is 4.5.
I was able to achieve Create, retrieve and delete operations related to the sql lite using EF6, and also was able to password secure the connection the sqlite db.
My problem is I want to secure the db file, I went through many links and googled for almost 3 days and came across various options, but few of them commercial and open ones are on C, nothing for .net.
So next approach was to keep file hidden for general user, as I dont want them to delete the file, as file is deleted then all the information in it will be lost.
I am willing to understand,the best practices out there to secure sqlite database file (please note the database is secured with Key).
I tried below things
Storing the file on Appdata folder, but it is accessible and easy
to remove the file, also someone can take the database file and try
to bruteforce to know the password, which may not be worthy :)
Storing the file in program data folder, but if the use installed
windows app is not admin, it may throw exception.
I came across IsolatedStorage, which seems to be hidden from general user,
and also we can define the scope for the sotrage, but the problem is I am not
able to implement if for .sqlite, as I do not know the exact path,
and to initialize the sqlite connection, we require exact path.
What could be the best way to secure the file. I do not want user to read, update or delete using other application, but should be accessible only through my application.
(Just comment for this post)
Sqlite database is normally can read and write from other user (Not from you app).For the problem of Open,Delete,Copy the sqlite db,I think you can lock the db file by Locking File(There are many type of locking file structure on google).So if you want to read data from your db,you unlock the db file with your specified key and open the connection.After that,you can lock the db file.

How can I expand my program to make it used on multiple devices and give them access to the old database without losing data?

I built a software for a farm using C#, the program was meant to keep track of the inventory and the financial exchanges related to the farms work.
The software was built to be installed on the manager's computer who then entered the farms data and retrieved reports and so. While the accountant used the same PC to use the financial part of the program with a different account.
Now the farm's business grew and more users need to use the system, can I move the database with the old data to a server so users can log in the system from different PC's at the time and continue the old tasks?
If I can - what do I change in my code?
P.S. the database was done in MS Access.
Not a lot of information to go on here. I can tell you that Access is a file based database system, and so whilst you could put the database files on a server or a NAS device with no problem with multiple users you should expect to run into the usual problems of Windows file sharing - VERY SLOW performance as a minimum.
It is also possible that the database may have been limited to a single user at a time, and without any more information impossible to know whether the developers have allowed for multi-user at all or whether you could have a situation where if several people do open the file at once one person may be overwriting another's data leading to corruption.
The short answer is that if the original developers are no longer around and you cannot ask the question of them then you probably need a new dedicated application to do the work which would mean either a complete rewrite or an alternative commercial application.
For multi-user Microsoft SQL Server, MySql, or even Firebird or another dedicated database back end would be the way to go. The front end could be anything - Winforms, WPF, even a web application if that is what you want, but it would have to be written.
I hope that this is helpful.

How can I safely let users query my database using (Postgre)SQL?

I'm currently writing a web app which would largely be used by developers, and I figured (from personal experience) that there would be times where it would be handy to run custom searches in an unrestricted way. I would like to let my users run arbitrary multi-statement SQL searches on their personal data (for an extra fee), so they can retrieve the data that's relevant to their question at the time.
Obviously, this is something that needs to be done with extreme caution, so I would like to make sure I'm going to tackle this the right way.
As I see it, the main points of concern are:
A malicious user could run a DOS (can track this via logging and remove their permissions)
Someone could run a function in a malicious way
Someone could access/modify data that doesn't belong to them (including database schema)
Someone could delete or modify data in a query (I would prefer they do that in a controlled manner)
What would be the safest way to go about providing this kind of ability to users safely?
This is dangerous territory (and I strongly recommend you weigh up this requirement carefully due to the obvious dangers you will be exposing yourself to), however I will try to give you the safest way to proceed if you must.
The only assumption I am making here is that you are running a current version of PostgreSQL and that you require users to remotely connect to the server (using their own tools) to execute their custom queries. Even if they will be entering them into a webpage, most of the same techniques will still apply as long as they each have a separate user log in for the database server.
First, (as NoBugs pointed out) to prevent users executing obvious malicious statements (like UPDATES, DELETES, DROPS, etc) you need to ensure that the user account connecting to the server has only SELECT permissions on the db(s) and table(s) they should be able to read from. Have a look in manual to see how to define roles for users, and grant specific permissions to those roles.
http://www.postgresql.org/docs/9.0/static/user-manag.html
http://www.postgresql.org/docs/9.0/static/database-roles.html
Note that you can only limit a user down to a particular table. If
users each need to be given access to different parts of a table, then
PostgreSQL (and nearly all DBMS's) will not support this out of the
box. Your only option would be to try and create some kind of SQL/TCP
proxy that intercepts requests, and modifies them somehow to limit
query results, before passing on to the database server. This would be
extremely difficult even for a very experienced developer!
To prevent (or at least detect) DOS attacks, you will need an external script or process to keep an eye on the resource usage of the database (and/or the entire server) every few seconds, and possibly build in a mechanism to restart the PostgreSQL service if it is maxed-out.
You will need to experiment with how long before you should intervene
carefully, as it is quite possible for a legitimate query to max
things for a few seconds.
As you mentioned, you would need to keep a careful log of who was trying to execute what, & when so, if necessary you can work backwards from a failure, to find out the culprit. You can really only rely on the system logs for this, which can be configured to write out to files, CSV, or Syslog.
I would suggest you pre-create some tools to help you quickly search
these logs to find what you need before you need to try and find it
(pun intended).
Finally you should also try to follow the other standard best practices for administration and security (all of which can be found in the manuals) including:
Only allow access for your users from specific ip's/hosts (dont give the general public any chance at connecting to your server. Your customers will need static IP's to access the system, but this is certainly worth considering to mitigate risks.
Keep a close eye on all of your standard administrative tasks for the server (especially backups, disk space, log file maintenance, index usage, etc.)
Make sure the user the sql is running as has permissions only to the tables/files the user should be able to modify.
There are also some other considerations - only allow trusted input (maybe use https in your api calls?) and know Mysql could access files and stuff you wouldn't want to let it access.
See also: http://www.greensql.com/article/protect-yourself-sqli-attacks-create-backdoor-web-server-using-mysql

What native technology exists to encrypt a string in the database for reading into a single application?

What native technology exists to encrypt/decrypt a string in the database for reading into a single application?
Scenario:
I have a set of connection strings that I need to use to securely access a set of production servers, for a polling application. I would like to store those in a table in a database and pull them out as I need them via a service. That will give me the ability for a handful of users (with permissions) to edit/add those entries.
My target audience using this application are all developers, these are servers to monitor our production and staging environments for some specific SQL flaws that I may need to later fix. This is a devops application.
Knowing that my target audience is developers, and that these are production servers, I would like to "lock the door" to keep people from actively seeing the production passwords/useraccounts unless they need them (auditing purposes). I realize that a lock is only as good as the frame around the door, and is only to keep honest people and petty thieves out, and that anyone dedicated will eventually be able to get past whatever safeguards I try to set.
Problem:
What technology in C# exists to secure this information and still allow me to dynamically add/alter connection strings but still keeps the data in the database reasonably secure? I am willing to make some changes to a machine.config or the like, but I need to actively develop the application too, so would like if it could be done in either machine.config1 or web.config, to allow for local development before deployment to the devops servers.
I understand that some of my alternative suggestions are:
Use strong database passwords to keep people out
Use strong schema organization to keep people out
Trust the developers, they work for your org (see "audit trail". I need to make some stab at securing production credentials)
Don't let people have access to the server and store them in the web.config (already plan on this in the first place)
Ideally:
Ideally I would just use a private key for encryption/decryption on the application server, but I don't exactly know the most secure way to do this, other than base64. I know this is not encryption.
What technology exists in the .NET native stack to securely encrypt/decrypt a string that may contain special characters in a single application and what is an example usage of this technology?
If I knew a name and technique, I would not be asking this question.
1 using machine.config/web.config to indicate something inherent in the .NET stack. I'm open to any suggestions.
Saving connection information in a database table is going to be unsecure, always. At some point, you're going to have to decrypt the password, and send it to the server. Developers tend to be smart enough to figure out any "security by obscurity" approach, and get to the passwords at some point. Even if you encrypt the password in the DB (not too hard), as long as you pass it to the SqlConnection at some point, you still have to decrypt it somewhere on the user (developer) end.
Rather, the only way to do this securely, is to make sure the password actually never gets anywhere close to the developers (or anyone else). There's a few ways to handle this:
Use an external security provider, such as Windows authentication. This means you don't have to use any username or password at all.
Create some kind of a tunnel to send any required SQL. This is very easy if your developers only ever need to run SQL commands, and a bit trickier if they want to use productivity tools like Management Studio; however, even that's doable - SQL can run fine over TCP, and you should be able to emulate that quite easily. Only the tunneling server would have access to the actual credentials, your developers would only have credentials to the tunneling server (and limited ones at that).
Use the Linked servers feature. This allows you to link local users (your devs) to remote users (su on the target server or whatever). It should work just fine with all the usual security settings.
Out of these, I'd say linked servers might be the best. They're quite easy to use, they can be administrated by the select few, and they don't publish the password at all. You can also do queries that span servers this way - very handy for a maintenance tool :)
Windows authentication is incredibly useful, but usually only on LAN, since we're talking about having all the DB servers in a domain. VPN could help, but that's getting into complicated territory.
Using a tunnel isn't necessarily a bad idea, although I assume you'll run into a few issues before you get it working 100%. And in the end, that's what Linked servers do for you for free, so why not use that?
Now, if you really do want to go through with the encryption idea instead, you can pick from a plenty of .NET supported encryption schemes. AES should work fine - it's assymetrical, so knowing the encryption key doesn't mean you can decrypt the data (the decryption / private key should only be stored in a secure location and on the maintenance application server, in a place noone but the application itself can reach; do note that admins can reach anything, so if your people have administrator rights, this isn't going to work).
For an example, see the AesManaged class in System.Security.Cryptography - http://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged(v=vs.110).aspx
Most applications only need one database, but you can use the Manager to create as many as you need. Multiple databases are independent of each other. If your application supports switching between multiple users, each with their own separate content and settings, you should consider using a database for each user. Otherwise, it's usually best to stick with one database.

Database on a server without installation?

Right now I am having a customer who is working with several businesses. He is working with their data but is not allowed to directly access their databases. We thought of using SQLite or SQL CE and storing a copy/part of the original database as a file on a network share. Now the problem is that SQL CE is not supporting it and SQLite highly recommends not to do so.
First of all the performance is a huge problem, since our customer is working with a lot of data (up to several gb). The second problem is that SQLite has problems (actually the underlying os functionality for file locking is the problem) with concurrent usage of the database, when it is stored on a network share. I did a lot of research on that topic and many people say that it is just a matter of time that the database gets currupt.
Does anyone know a better solution to that problem or a workaroung which lets me use SQLite? It does not need to be a file based database, as long as nothing needs to be installed or run on the server.
Thanks, David.
If you are going to store data on a network share and have concurrent users accessing it you are going to need a db that can handle concurrent access. MS Access will quickly die if under concurrent access as will SQL Lite.
SQL Server Express is free and works very well. PostgreSQL as suggested by Maxim is an open source full featured db that will do the job very well but may be overkill.
You could also look at Redis ... fast lightweight in memory no sql db that also has capability to persist to file.
You can try PostgreSQL. It is very easy to configure, and is rather reliable. It also support server export/import options.
And any of this makes sense, if you client is able to get his hands on an exported database somehow.

Categories