en · de

Quick Tip: Validate current user by enforcing him to enter his password

by Thomas,
assono GmbH, Standort Kiel,

Quick-TippIBM Notes I had a "small" request from a customer last week: He'd be interested in the extended commercial version of our assono Password-Safe. But his internal audit team had the requirement that a user should have to re-enter his Notes client password when opening a document or copying it directly to the clipboard from a view.

There is a @Command for this: ToolsUserLogoff. It just logs the user off, thus you have to combine it with some kind of server access to get the password input dialog to appear, like described here: Forcing user re-entry of passwords for electronic signatures in script.

This approach has three drawbacks:
1. It doesn't work offline, i.e. on a local replica, because it depends on the server contact for the password input dialog to be opened.
2. I need it to protect the opening of existing documents. When the user just cancels the password input dialog, the document continues to be opened.
3. The formula code must be placed in the QueryOpen event of the form. But I really need to put some LotusScript there.

Thus I had to search further for a solution working in LotusScript. And I found one by Eknori from 2004: @Command(ToolsUserLogoff) in Lotus Script.
It had to be adopted for the current versions of Notes, because the log out key had been changed from F5 to Ctrl-F5.

I still wasn't convinced this would be the best possible solution. Its strictly Windows only and the user keeps logged out, when he cancels the dialog, I don't know, it would work locally etc.

I looked further and found a great idea: Use the Notes C api to access privat portions of the user's ID file, namely the REGGetIDInfoString function with REGIDGetPrivateKey as infoType.

Thank you, Davy Vanherbergen, for
your OpenNTF Code Bin post (from 2003!): Call
notes password prompt from lotusscript

I took the idea and implemented it "my
way", using my C api helper functions and letting the user choose
another ID file, if the configured ID file is not his own.


Function
ValidateCurrentUser As
Boolean

'/**

'
* validates current user by letting him enter his password


'
*


'
* @return True, if user has successfully entered his password


'
*


'
* @author Thomas Bahn/assono <tbahn@assono.de>


'
* @version 2014-09-30


'
*/



Const
MAXOUTBUFRLEN% = 4096



Dim
idFileName As
String

Dim
returnCode As
Integer

Dim
userNameBuffer As
String*MAXUSERNAME

Dim
actualLen As
Long

Dim
currentUserName As
String


Dim
outBufrLen As
String*MAXOUTBUFRLEN



If
Not
IsDebugMode() Then
On
Error
GoTo
errorHandler



ValidateCurrentUser
= False



idFileName
= session.GetEnvironmentString("KeyFileName",
True)

returnCode
= REGGetIDInfoString(idFileName, REGIDGetName, _


userNameBuffer, MAXUSERNAME, actualLen)

Call
ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo",
_


NULLHANDLE)



currentUserName
= Left(userNameBuffer,
actualLen - 1)


Do
While
session.UserName <> currentUserName


'
ID file configured in notes.ini is not the ID file of the



'
current user



idFileName = uiws.OpenFileDialog(False,
_


"Choose
your ID file:"
, "*.ID|",
_


GetNotesDataDirectory(),
idFileName)(0)


returnCode = REGGetIDInfoString(idFileName,
REGIDGetName, _


userNameBuffer,
MAXUSERNAME, actualLen)


Call
ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo",
_


NULLHANDLE)





currentUserName = Left(userNameBuffer,
actualLen - 1)

Loop



returnCode
= REGGetIDInfoString(idFileName, REGIDGetPrivateKey, _


outBufrLen,
MAXOUTBUFRLEN, actualLen)

If
returnCode = -32355
Then


Exit
Function
' user cancelled
dialog


Else


Call
ShowCAPIErrorIfAnyAndEnd(returnCode, "REGGetIDInfo",
_


NULLHANDLE)

End
If


'
when we get here, the user must have entered his password


'
successfully


ValidateCurrentUser
= True

Exit
Function



errorHandler:

If
HandleError() = RESUME_NEXT_LINE Then
Resume
Next

Exit
Function

End
Function


GetNotesDataDirectory()
is a helper function to get the name of the Notes data directory. Replace
it by your own function or a String constant.

And adopt the error handling code (IsDebugMode()
and HandleError())
to your standard.

It needs some (Declarations):

Private Const LIBRARY = "Eintrag utils"

' WORD LNPUBLIC OSLoadString(HMODULE hModule, STATUS StringCode, char far *retBuffer, WORD BufferLength);
Declare Function OSLoadString Lib "nnotes" Alias "OSLoadString" (ByVal hModule As Long, ByVal stringCode As Integer, ByVal retBuffer As LMBCS String, ByVal bufferLength As Integer) As Integer

' STATUS LNPUBLIC REGGetIDInfo(char far *IDFileName, WORD InfoType, void far *OutBufr, WORD OutBufrLen, WORD far *ActualLen);
Declare Function REGGetIDInfoString Lib "nnotes" Alias "REGGetIDInfo" (ByVal idFileName As String, ByVal infoType As Integer, ByVal outBufr As String, ByVal outBufrLen As Integer, actualLen As Long) As Integer
Declare Function REGGetIDInfoBoolean Lib "nnotes" Alias "REGGetIDInfo" (ByVal idFileName As String, ByVal infoType As Integer, ByVal outBufr As Long, ByVal outBufrLen As Integer, actualLen As Long) As Integer

Const REGIDGetName = 7 ' Data structure returned Is char xx[MAXUSERNAME]
Const REGIDGetPrivateKey = 9 ' Data structure returned Is char xx[xx]


' STATUS LNPUBLIC NSFDbClose(DBHANDLE hDB);
Declare Function NSFDbClose Lib "nnotes.dll" (ByVal hDB As Long) As Integer


Const NOERROR = 0

Const NULLHANDLE = 0&

Const MAXUSERNAME = 256


And two support functions for the C API error handling:

Sub ShowCAPIErrorIfAnyAndEnd(errorCode As Integer, functionName As String, hDB As Long)
'/**
' * shows user the C API error and aborts execution.
' *
' * @param errorCode return code of the function's execution
' * @param functionName name of the C API function called
' * @param hDB handle to the open database
' *
' * @author Thomas Bahn/assono <tbahn@assono.de>
' * @version 2014-07-17
' */

If errorCode = NOERROR Then Exit Sub ' exit if no error occured

If hDB <> 0 Then
' if there is a valid handle, try to close database
Call NSFDbClose(hDB)
End If

Error Err, "Error in library '" & LIBRARY & "'" & Chr$(10) & _
"An error has occurred in the C api function '" & _
functionName & "': " & Chr$(10) &_
"Error code: " & Trim$(Str$(errorCode)) & Chr$(10) & _
"Error text: " & Chr$(10) & GetCAPIErrorMsg(errorCode)
End Sub

Function GetCAPIErrorMsg(errorCode As Integer) As String
'/**
' * gets error message for the C API error.
' *
' * @param errorCode return code of the function's execution
' * @return error message for the C API error
' *
' * @author Thomas Bahn/assono <tbahn@assono.de>
' * @version 2014-07-17
' */

Dim length As Integer
Dim buffer As String

' initialize a buffer of adequate length to accept the error string
buffer = String$(256, 0)

' get the API error message from the internal Notes/Domino string
' tables
length = OSLoadString(NULLHANDLE, errorCode, buffer, Len(buffer))
If length > 0 Then
' remove any trailing characters from the string and
' return it to the caller
GetCAPIErrorMsg = Left$(buffer, InStr(1,buffer,Chr$(0))-1)
Else
' couldn?t locate the error message in the string tables
GetCAPIErrorMsg = "Unknown error"
End If
End Function


Finally place some code like this into the QueryOpen event handler of your form:

If continue Then
continue = ValidateCurrentUser()

If continue Then
' do some stuff if necessary
End If
End If

Since this code only uses Notes C api calls, it can easily be extended to other platforms than Windows, but for now it is restricted to this operating system.

Event AdminCamp Technical article IBM Notes Security Development

You have questions about this article? Contact us: blog@assono.de

Sie wollen eine individuelle Beratung oder einen Workshop? Read more

More interesting entries

Any questions? Contact us.

If you want to know more about our offers, you can contact us at any time. There are several ways to contact us for a non-binding first consultation.

assono GmbH

Location Kiel (headquarters)
assono GmbH
Lise-Meitner-Straße 1–7
24223 Schwentinental

Location Hamburg
assono GmbH
Bornkampsweg 58
22761 Hamburg

Phone numbers:
Human resources department: +49 4307 900 407
Marketing department: +49 4307 900 411

E-Mail adresses:
contact@assono.de
bewerbung@assono.de