Manage Learn to apply best practices and optimize your operations.

Extract the public key from the current active user

Have you peformed or are about to perform a massive user recertification? Or, have you peformed or are about to perform a domain merge? Or, do you sometimes get errors where renaming users via Adminp is not working? Or, are users? recertification dates and name changes not getting updated in the users ID file?

Have you had problems where the user does not get prompted for a user name change that has been completed by Adminp? Or, do you have problems where you have recertified a user from the Domino Directory but the user never gets their ID updated automatically?

So, what do you do? Re-Register the user?

Wrong! You should never re-register a user!

By re-registering your user, a new ID file is created and a new public key is given. Hence, they will never be able to access their encrypted memos and databases that have encryption enabled.

The public key stored in the ID File should be identical to the Public Key stored in the Person Document for that user. If the two public keys are not identical, then you will have problems somewhere along the track.

The Lotus Script code here allows you to extract the public key from the current active user ID. Then, you can optionally mail the key to a central point (user or mail-in-database).

You could insert this script, say, into the Post-Open event of all users mail files and only allow the script to execute once. By doing this, all users? public keys can be mailed to a central point on your server.

Once you have collected all of the users Public Keys from their ID File, you can then check the Public Keys against the Public Key entry in their Person Document.

Why do this?

Public keys often get out of sync for some unknown reason. I am sure that everyone has had at least one instance where user renames did not take. By doing this, you can be sure that every user ID is in synchronization with their public address book entry.

I would highly recommend performing this prior to a massive user recertification or domain merge. It will ensure that minimal or no problems with user IDs occur in the future.

To test this application, create a Lotus Script agent then copy the code below into the appropriate sections.

Nearly all these functions are undocumented by Lotus so I will not be able to provide you with much detail on the exact function that these API calls perform.

+++ Copy this code into the OPTIONS section of the script agent

Option Public
Option Explicit

+++ Copy this code into the DECLARATIONS section of the script agent

Declare Function W32_SECKFMKfcTearDown Lib "nnotes.dll" Alias "SECKFMKfcTearDown" (Byval Memory
As Long) As Integer
Declare Function W32_SECKFMKfcSetup Lib "nnotes.dll" Alias "SECKFMKfcSetup" (Byval Memory As Long,
Return1 As Long, Byval Flags As Long) As Integer
Declare Function W32_SECKFMFileRead Lib "nnotes.dll" Alias "SECKFMFileRead" (Byval Memory As Long,
Byval Memory2 As Long, Byval Flag1 As Long, Byval Flag2 As Long, Byval flag3 As Long) As Integer
Declare Function W32_SECKFMAccess Lib "nnotes.dll" Alias "SECKFMAccess" (Byval Flag1 As Long,
Byval Memory1 As Long, Byval Memory2 As Long, Byval Flag2 As Long) As Integer
Declare Function W32_SECKFMGetIDConvertToHAC Lib "nnotes.dll" Alias "SECKFMGetIDConvertToHAC"
(Byval Memory1 As Long, Byval Flags As Long, retHandle1 As Long, retHandle2 As Long) As Integer

Declare Function W32_Csetmem Lib "nnotes.dll" Alias "Csetmem" (Byval Dest As Long, Length As Long, Value As Long) As Long
Declare Function W32_Cmovmem Lib "nnotes.dll" Alias "Cmovmem" (Byval source As Long, Dest As Long, Byval Length As Long) As Integer
Declare Function W32_OSLockObject Lib "nnotes.dll" Alias "OSLockObject" (Byval handle As Long) As Long
Declare Function W32_OSUnlockObject Lib "nnotes.dll" Alias "OSUnlockObject" (Byval handle As Long) As Long
Declare Function W32_OSMemAlloc Lib "nnotes.dll" Alias "OSMemAlloc" (Byval BlkType As Long, swSize As Long, retHandle As Long) As Integer
Declare Function W32_OSMemFree Lib "nnotes.dll" Alias "OSMemFree" (Byval Handle As Long) As Integer

+++ Copy this code over the top of the INITIALIZE routine of the script agent

Sub Intialize


Const SendTo = "Dennis Fry/Administrators/Acme"    'user name or mail-in-database to send the public key to


Dim session As NotesSession    'notes session - only used in the script when sending the public key
    Dim db As NotesDatabase    'current notes database - as above
    Dim doc As NotesDocument    'new notes document - as above
    Dim nnUserName As NotesName    'current user name
    Dim hKeyData As Long    'handle to some allocated memory, used to retrieve the public key
    Dim aKeyData As Long    'physical memory address to the allocated memory
    Dim hPublicKey As Long    'handle to the public key object
    Dim aPublicKey As Long    'physical memory address of the public key object
    Dim PublicKeyLength As Long    'length of the retrieved public key - in bytes
    Dim Memory As Long    'contains a pointer to a memory address or handle that is require to retrieve the public key
    Dim RetVal1 As Long    'unknown, undocumented - used with SECKFMfcSetup
    Dim lret As Long    'long return value from a function call
    Dim iret As Integer    'integer return value from a function call
    Dim Char As Long    'stores each ascii character of the public key, when retrieved
    Dim PublicKey As String    'string to store the public key from the Char value above
    Dim PosCounter As Integer    'counter for each character to translate into a valid string, from the public key


Set session = New NotesSession
    Set nnUserName = New NotesName(session.UserName)

'The ID file information retrieved, needs 608 bytes of data to store the information, so allocate 608 bytes of memory


iret = W32_OSMemAlloc(6145, 608, hKeyData)
    If iret <> 0 Then
        Msgbox "Unable to allocate memory...."
        Goto Clean_Up
    End If

'Key the physical memory address of the allocated memory, then clear the memory (fill with 0), all 608 bytes


aKeyData = W32_OSLockObject(hKeyData)
    lret = W32_Csetmem(aKeyData + 46, 608, 0)

'Extract the security key information from the current users ID file. Value parameters and offsets has been set by Lotus

    iret = W32_SECKFMKfcTearDown(aKeyData)
    iret = W32_SECKFMKfcSetup(aKeyData + 46, RetVal1, 0)
    iret = W32_SECKFMFileRead(aKeyData + 46, aKeyData + 99, 0, 0, 33)

'Extract 4 bytes (long data type) of memory from an offset of 46 from the security key information
'This value contains an object that stores the public key (probably in encrypted format ?)


iret = W32_Cmovmem(aKeyData + 46, Memory, 4)

'Access the security information that we require, then extract a memory handle to the public key and get the length of the public key


iret = W32_SECKFMAccess(49, Memory, aKeyData + 99, 0)
    iret = W32_SECKFMGetIDConvertToHAC (Memory, 3, hPublicKey, PublicKeyLength)

'The handle of the public key has been retrieved, so now get the physical memory address to the public key, so we can extract it in ASCII format


aPublicKey = W32_OSLockObject(hPublicKey)

'Extract each character of the public key, referencing the physical memory address, one byte at a time
'Each line of the public key (same as the format in the person document in the Domino Directory), is terminated with a null character
'As each character is read, populate the end-result public key string. Check for a null terminating character and insert this into the
'string as a carriage return & line feed (CRLF). Keep extracting the public key for the entire length of the key, as determined by
'the variable PublicKeyLength


For PosCounter = 0 To PublicKeyLength - 1
        iret = W32_Cmovmem(PosCounter + aPublicKey, Char, 1)
        Char = Char And 255
        If Char = 0 Then
            PublicKey = PublicKey & Chr$(10) & Chr$(13)
            PublicKey = PublicKey + Chr$(Char)
        End If

'The public key as now been extracted. Close the open memory objects of the public key and allocated memory


Call W32_OSUnLockObject(hPublicKey)
    Call W32_OSUnLockObject(hKeyData)

'Free up the resources used by the allocated memory. If the memory was not allocated earlier, exit the program

    If hKeyData <> 0 Then
        iret = W32_OSMemFree(hKeyData)
    End If

'Display the public key for the current user


Msgbox PublicKey,,"Public Key for " & nnUserName.Abbreviated

'This code allows you to send the public key to a person or mail-in-database



Set db = session.CurrentDatabase
    Set doc = db.CreateDocument


doc.Form = "Memo"
    doc.SendTo = SendTo
    doc.Subject = nnUserName.Abbreviated & " - Public Key"
    doc.Body = PublicKey
    Call doc.Send(False)

End Sub

Dig Deeper on Domino Resources - Part 4



  • Favorite iSeries cheat sheets

    Here you'll find a collection of valuable cheat sheets gathered from across the iSeries/ community. These cheat ...

  • HTML cheat sheet

    This is a really cool cheat sheet if you're looking to learn more about HTML. You'll find just about everything you every wanted ...

  • Carol Woodbury: Security

    Carol Woodbury