Ask for password when opening Database - LotusNotes/DominoDesigner - lotus-domino

My task is, when opening a database in Lotus Notes, the current user will be ask to input his/her password that was given by his superior. Is there a way how to do that? Just a simple prompt or form that will ask for your password before viewing the database.

Please understand that I do not intend this answer to be disrespectful, but this is really not a task for a beginner at Notes and Domino, as you have stated that you are. You should tell that to your boss. This is a task for someone who has deep understanding of the principles of security and of the mechanisms Notes and Domino provide for it. If you do not understand my comments on #Thomas Adrian's answer, then that applies to you. Again, no disrespect intended.
As security guru Bruce Schneier said, "if you ask amateurs to act as front-line security personnel, you shouldn't be surprised when you get amateur security".

Yes you can put code in queryopendatabase which is located in database script.
Create a button for your superior to store the password in a general profile document within the database
2 when users open the database use the queryopendatabase script to present a password prompt. You can use inputbox in lotus script. Verify the password against the profile document. If a wrong password is entered close the database.
You can use the following code as an embryo, This code use a "real" document but you can easily modify this to be a profile document.
Remember when you test this to close Domino Designer as the NSF is cached as long as DDE is open
Sub Postopen(Source As Notesuidatabase)
Dim db As NotesDatabase
Set db = source.Database
Dim d As NotesDocument, flag As Integer, upw As String, pw As String
upw = InputBox("Enter Password")
Set d = db.getView("Main").getFirstDocument()
If Not d Is Nothing Then
pw = d.password(0)
If pw = upw Then
flag = 1
End If
End If
If flag <> 1 Then Call source.Close()
End Sub

Related

calling a uid and pwd file into an access db for a system dsn

I have 5 different MS Access 2013 db files which connect to system dsn files(Linked Server)
The machine/system dsn's are Oracle based but the issue I am running into is 1 my password isn't encryped and has to be changed every 90 days and
2 I have to open each file and save my password multiple times when its changed.
I want to have a secure location which has the credentials stored and pass this into access so that they are not visible to other users and
not having to save my password on each access file and relink it.
I have googled for over 2 days but can't find anything other than looking at connection strings which still doesn't solve the problem. What do I need to look at to solve this?
Sorry I dont have code as I just use the linked tables wizard inside of ms access.
#Albert D I couldn't get your code to work but I have done the following which fixes the issue on the tables but not the Pass Through queries
Created a File DSN and linked some tables to the access database.
Created an Excel File to store my UserName And Passwords but my credentials in the pass-through query still show which I am stuck on?
Option Compare Database
Function Connections()
On Error Resume Next
'delete query if exists
DoCmd.DeleteObject acQuery, "PTQ"
Err.Clear
On Error GoTo 0 '"on error" statement here
'GET EXCEL LOGIN DETAILS
Set xlsApp = CreateObject("Excel.Application")
Dim WkBk As Excel.WorkBook
Set WkBk = xlsApp.WorkBooks.Open(FileName:="C:\folderlocation\filename.xlsx")
Dim USERLIST As String
Dim PWDLIST As String
USERLIST = WkBk.Sheets(1).Range("A2").Value
PWDLIST = WkBk.Sheets(1).Range("B2").Value
If Not (xlsApp Is Nothing) Then xlsApp.Quit
'end excel stuff
Dim db As DAO.Database
Dim qdExtData As QueryDef
Dim strSQL As String
Set db = CurrentDb
'passthrough query statement
strSQL = "SELECT * FROM table"
Set qdExtData = db.CreateQueryDef("PTQ")
ServerName = "Server1"
qdExtData.Connect = "ODBC;DRIVER={Oracle in OraClient11g_home1};Server=" & ServerName & ";DBQ=Server1;UID=" & USERLIST & ";Pwd=" & PWDLIST & ""
qdExtData.SQL = strSQL
qdExtData.Close
db.Close
Set db = Nothing
End Function
I then Set up a runcode macro called AutoExec
Ok, first up?
I would avoid (not use) a system, or a user DSN. The reasons are MANY, but these types of DSN's require not only a external reference, but also often require elevated registry rights. And worse yet, your password will be in plain view.
The best solution is to use what is called a DSN-less connection. And you can create these connections even without code!
And even better? If the server + database name is NOT changed, but ONLY the password? You can change the userID + password WITHOUT having to re-link the tables (ideal for you with a changing password, but NOT the server + database being changed).
Even better better? If you adopt a wee bit of "log on" code, then you don't have to store the password in the table links! What this means if someone decides to fire up access, and say import your linked tables? Well, for one, they will not be able to open the tables, and EVEN better yet the uid/password is NOT part of, nor is it stored in the connection string for each linked table. As noted, because of this, you can change the UID, and not have to re-link the tables.
The first step:
First up, ALWAYS (but ALWAYS!) when you link the tables, use a FILE dsn. this is imporant since when using a FILE dsn in access, they are automatic converted to DSN-less connections for you.
In other words, if you link your tables with a FILE dsn, then once the tables are re-linked, then you can even delete or toss out the DSN. And this means you can deploy the linked database (front end) to any workstation. You will not have to setup a DSN on that workstation, and in fact don't have to setup anything at all. (you will as before of course require the oracle database driver).
What the above means is when a password is updated/changed, you could then simply roll out a new front end. In fact, you likely have some auto updating ability for your application. (and if you don't', then you could (should) cobble together a bit of code to do this for you). So, you should have some means to roll out a new version of your software. After all, you REALLY have to install your "application" on each workstation LIKE you do with all other software, right???
So, there are two parts here:
Adopting a FILE dsn for the table links. As noted, once you do this, then you don't need the DSN anymore. This is great for distribution to each workstation.
Also MAKE SURE when you do link, you do NOT check the box to save the password. This is to ensure that uid/password is NOT saved in the connection strings.
So, if tables don't have uid/password, then how will they work?
Well, what you do is execute a "logon" to the database in your startup code. Once you execute this logon, then all linked tables will work! It is this "small" bit of code that can read the uid/password you place in an external file. Where you place this uid/password is up to you. It could be embedder in the code, or even some external text file that you read on startup. And it could even be a local table in the front end. (this idea would work well if you have some kind of automatic update system for when you roll out the next great version of your software.
So, with the ability to execute a logon, and not having to re-link the tables, then we have a EASY means to change the password.
So, you have to:
go dsn-less. Thankfully, access does this by default, but ONLY if you use a FILE dsn.
Get/grab the code to execute a logon to the database. In fact, you likly have to delete all your table links. Exit Access, then re-start Access. Now, run your logon code, and THEN re-link your tables (using a FILE dsn you make).
The code to execute a logon is this:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
The above of course requires a correctly formed conneciton string.
So, to make ALL of this work, you can adopt the FILE dsn, and use above. You will likly cobbile together some code to build you a connection string. Then add to your code some code to read an external ext file, or have the UID/password in some table. This logon code as per above has to run BEFORE any form or linked table is used or touched.
The whole process is simple, but only if you break down this into the correct steps.
How this logon trick, and example code works is not complex, but a full article explaining this approach is outlined here
Power Tip: Improve the security of database connections
https://www.microsoft.com/en-us/microsoft-365/blog/2011/04/08/power-tip-improve-the-security-of-database-connections/

String comparison functions are not working properly

So I have a program that I have three groups of users, and I am storing user names, permission levels, usernames and passwords in a veryhidden/protected sheet. (Yes I know this is not particularly secure but it is not to prevent malintent it simply will avoid people stumbling upon things they shouldnt. Nobody is going to be able to uncover very hidden sheets or get into the code.)
The function below is what I have been using. The for each loop is going into the users sheet and finding the username, but for some reason it says that the password is wrong no matter what. I do not know a ton about string comparison and I suspect that one of my conversions or the way I am comparing the passwords is not doing it's job. I have tweaked this a bunch of different ways, but I am missing something basic I think.
Function getSecurityLevel(user As String, pw As String) As Single
Dim userNames As Range
Dim thisUser As Range
Dim uName
Dim userWS As Worksheet
Set userWS = Worksheets("Users")
Application.ScreenUpdating = False
Module4.unprotectUsers
Set userNames = userWS.ListObjects("userTable").ListColumns(3).DataBodyRange
For Each thisUser In userNames
If LCase(CStr(thisUser.Text)) = LCase(user) Then
uName = thisUser.Address
Range(uName).Offset(0, 1).Select
If CStr(ActiveCell.Text) <> pw Then
MsgBox "Your password is incorrect", vbOKOnly
Exit For
Else
ActiveCell.Offset(0, 1).Select
getSecurityLevel = ActiveCell.Value
Exit For
End If
End If
Next thisUser
Module4.hideAll
Application.ScreenUpdating = True
MsgBox "Your username could not be found, please try again", vbOKOnly
End Function
I just need it to properly compare the input password from the userform to the cell next to the matching username, then offset one more and read the security level
This isn't the answer you want but you need to know this.
"Nobody is going to be able to uncover very hidden sheets or get into the code." That is a bold statement and also very untrue.
Setting aside the fact that password protection offered by the VB editor is easily broken.
Anyone with access to the file can change the extension to ZIP. From there, everyone's password is visible as plain text in xl\sharedstrings.xml and your vaunted very hidden worksheet is plainly visible in the file structure and can be unhidden by removing state="veryHidden" in xl\workbook.xml then rezipping and replacing ZIP with the appropriate Excel extension.
Do your users a favor. If you're not going to encrypt passwords and insist on storing them as plain text - then at the very least, do not save them in a file that is distributed to all of your users.
What happens if that file is sent to someone outside the organization or if anyone in your company caught whiff of you sending unencrypted passwords to your users... Think man! This is not the way forward!!!

how to use environ function to avoid other from using my Access DB

I manage an Access DB (accdb) and it contains some information about my company that I don´t want others to access it out of my company´s server.
I thought to use Environ (5)=computername or Environ (12)=path to retrieve some references such as LEN(environ(path)). With this function, I could, for instance, make sure that the accdb file only works if LEN(environ(path))/2+15=55 (the lenght at my company´s server divided by 2 plus 15 = 80/2+15=55 = algorhytm).
So, on opening the db, it should prompt for a number/code. If the user inserts 55 and the filepath = 80, it will open. If filepath=100 (filepath out of my company´s server), must be prompted 100/2+15=65 to open the db.
Unfortunelly, I don't know how to programe it neither I know how to block the use of SHIFT (that breakes the VBA code on opening) because I'm a rookie.
So, if you please, can you help me to solve these huge problems (1. algorhytm using Environ, 2. avoid using SHIFT on opening).
Thanks in advance.
Bruno
Add this code to your startup form. When the form opens it will check for the username and computername, and if both match the form will open.
Private Sub Form_Open(Cancel As Integer)
If Not (Environ("username") = "santosh" And Environ("computername") = "ABC-CAP1-093") Then
Cancel = True
Application.Quit
End If
End Sub
Avoid using shift key - I have already answered see this link

Using Access to store Usernames and Passwords and opening via Visual Basic

Basically i am trying to create a programme, which needs to have some authorisation.
When the application starts up, it starts straight into the login screen.
I want the Username and Password textboxes to read the database and if they match then progress to the next form but if they dont match then a message box will appear.
I also want to create groups of people so if a certain group of people log in they go to a certain form and if the another group of people log in i want them to go to a different form.
Also i want the password box to be * instead of visable text.
Can any one help, this is my code so far...
dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = D:/Users.mdb"
con.ConnectionString = dbProvider & dbSource
con.Open()
sql = "SELECT * FROM tblUsers"
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "Users")
con.Close()
MaxRows = ds.Tables("Users").Rows.Count
inc = -1
If UserIDTextBox.Text = ds.Tables("tblUsers").Rows(0).Item("UserID") & User_PasswordTextBox.Text = ds.Tables("tblUsers").Rows(0).Item("Password") Then
MsgBox("This have worked correctly!")
Else
MsgBox("This has not worked, try again!")
End If
The first and most important thing you need to know is that it's almost always a bad idea to code your own authentication system. It's just so easy to do this in ways that seem to be right and even pass all your tests, but still have subtle, hard to spot errors that won't show up until a year later when you find out you were cracked six months ago. Always lean as much as possible on whatever authentication features are made available to you in your platform.
The next thing you need to know is that you do not store passwords in the database. Ever. The correct way to handle password matching is to use a salt to alter the original password in some simple way so that simple dictionary passwords will now no longer result in values that can be easily reversed by a google lookup, and then use use a cryptographic hashing algorithm like bcrypt, scrypt, or (if your really have to) sha1. Do not use md5. Examples of this are readily available on google, and will explain it far better than I can here. When someone wants to log in, you perform the same steps on their attempted password and now compare only the hashes. If you're not doing it this way, it's only a matter of time before your user's passwords become public knowledge.
Next up I noticed a problem with your database connection handling in your code. The code you have is not guaranteed to close the connection. con.Close() should always be in a Finally block, and for preference I like the Using block shorthand.
Finally, way near the bottom you try to use VB's string concatenation operator (&) as a logical AND. Oops. You want to use the AndAlso operator here instead.
Sam,
First of I second what Joel said, hash the passwords. Here's a link: What is the easiest way to encrypt a password when I save it to the registry?
As for the TextBox, just set the PasswordChar property to something like *, and it will mask the characters. You can also limit the length.
As for only allowing certain groups, if you're in a windows domain, you should use active directory groups. To determine is someone is a member of a group you can do something like:
def IsMemberOfAdGroup(grouName as string):
windID = System.Security.PrincipalWindowsIdentity.GetCurrent()
return System.Security.PrincipalWindowsPrincipal(windID).IsInRole(grouName)
This looks like a really good page, that covers what you're trying to accomplish.
ASP.NET 2.0 Forms Authentication Using Access Database

Intermittent error when attempting to control another database

I have the following code:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.Run "Routine"
obj.CloseCurrentDatabase
Set obj = Nothing
The problem I'm experimenting is a pop-up that tells me Access can't set the focus on the other database. As you can see from the code, I want to run a Subroutine in another mdb. Any other way to achieve this will be appreciated.
I'm working with MS Access 2003.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've tried this in our development database and it works. This doesn't mean anything as the other code also workes fine in development.
I guess this error message is linked to the state of one of your databases. You are using here Jet connections and Access objects, and you might not be able, for multiple reasons (multi-user environment, unability to delete LDB Lock file, etc), to properly close your active database and open another one. So, according to me, the solution is to forget the Jet engine and to use another connexion to update the data in the "other" database.
When you say "The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database", I assume that the role of your "Routine" is to update some data, either via SQL instructions or equivalent recordset updates.
Why don't you try to make the corresponding updates by opening a connexion to your other database and (1) send the corresponding SQL instructions or (2) opening recordset and making requested updates?
One idea would be for example:
Dim cn as ADODB.connexion,
qr as string,
rs as ADODB.recordset
'qr can be "Update Table_Blablabla Set ... Where ...
'rs can be "SELECT * From Table_Blablabla INNER JOIN Table_Blobloblo
set cn = New ADODB.connexion
cn.open
You can here send any SQL instruction (with command object and execute method)
or open and update any recordset linked to your other database, then
cn.close
This can also be done via an ODBC connexion (and DAO.recordsets), so you can choose your favorite objects.
If you would like another means of running the function, try the following:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.DoCmd.RunMacro "MyMacro"
obj.CloseCurrentDatabase
Set obj = Nothing
Where 'MyMacro' has an action of 'RunCode' with the Function name you would prefer to execute in Working.mdb
I've been able to reproduce the error in 'development'.
"This action cannot be completed because the other application is busy. Choose 'Switch To' to activate ...."
I really can't see the rest of the message, as it is blinking very fast. I guess this error is due to 'switching' between the two databases. I hope that, by educating the user, this will stop.
Philippe, your answer is, of course, correct. I'd have chosen that path if I hadn't developed the 'routine' beforehand.
"I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user." As it is impossible to prevent the user to switch application in Windows, I'd like to close the subject.