000025425 - How to access RSA ACE/Agent SDK synchronous API from Microsoft .NET

Document created by RSA Customer Support Employee on Jun 16, 2016Last modified by RSA Customer Support Employee on Apr 21, 2017
Version 5Show Document
  • View in full screen mode

Article Content

Article Number000025425
Applies ToRSA ACE/Agent 5.0.3 Authentication API
Microsoft .NET
Microsoft Windows Server 2003
Microsoft Windows 2000 Professional
IssueHow to access RSA ACE/Agent SDK synchronous API from Microsoft .NET
CauseThe RSA ACE/Agent Authentication SDK is designed directly for WIN32 programming in languages such as C or C++. At the current time, it has no direct .NET implementation.
Resolution

RSA ACE/Agent WIN32 API can be accessed from a .NET application if it is treated as 'unmanaged' code. The following example shows a simple example of how results can be achieved with Visual Basic or C# (the C++ interface is fully supported by existing documentation and examples). This specific example shows the use of the synchronous API calls, which are designed to closely mirror legacy calls from an earlier version of RSA ACE/Agent.

These examples show how the unmanaged calls can be made. For additional advice on how to managed the marshalling of data in these unmanaged calls, contact Microsoft or read MSDN information at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconmarshalingdatawithplatforminvoke.asp.

The example code does not show all appropriate logic you would use in an implementation (e.g. error checking, next token, and new PIN handling), but simply shows the mechanics of how calls can be made. For additional advice on how to use the RSA ACE/Agent SDK, refer to the "RSA ACE/Agent Authentication API 5.0 Guide" which is supplied as a PDF file in the RSA ACE/Agent 5.0.x SDK.

[Visual Basic]

Imports System

Imports System.Text

Imports System.Diagnostics

Imports Microsoft.VisualBasic

Imports System.Runtime.InteropServices

 

Module Module1

    REM Holds pin limits and related values

    <StructLayout(LayoutKind.Sequential)> _

    Structure SD_PIN_STRUCT

        Public Min As Byte

        Public Max As Byte

        Public Selectable As Byte

        Public Alphanumeric As Byte

        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=9)> _

        Public System As String

    End Structure

 

    REM initialization and shutdown calls

    Declare Ansi Function AceInitialize _

        Lib "aceclnt" Alias "AceInitialize" () As Integer

 

    REM New Synchronous and thread-safe calls

    Declare Ansi Function SD_Init _

        Lib "aceclnt" Alias "SD_Init" (ByRef SdiHandle As Integer) As Integer

    Declare Ansi Function SD_Lock _

        ' note the .DLL suffix is assumed by VB

        Lib "aceclnt" Alias "SD_Lock" (ByVal SdiHandle As Integer, _

        ByVal userID As String) As Integer

    Declare Ansi Function SD_Check _

        ' the suffix is allowed, VB knows what is intended

        Lib "aceclnt.dll" Alias "SD_Check" (ByVal SdiHandle As Integer, _

        ByVal passcode As String, _

        ByVal userID As String) As Integer

    Declare Ansi Function SD_Pin _

        Lib "aceclnt.dll" Alias "SD_Pin" (ByVal SdiHandle As Integer, _

        ByVal pin As String) As Integer

    Declare Ansi Function SD_Close _

        Lib "aceclnt.dll" Alias "SD_Close" (ByVal SdiHandle As Integer) As Integer

 

    Const ACM_NEW_PIN_REQUIRED = 5

 

    Sub   Main()

        Dim SdiHandle As Integer = 0

        Dim userid As String

        Dim passcode As String

        Dim res As Integer

        Dim val As SD_PIN_STRUCT

        val = New SD_PIN_STRUCT

        val.Min = 0

        val.Max = 0

        val.Alphanumeric = 0

        val.Selectable = 0

 

        Dim buffer As StringBuilder

        buffer = New StringBuilder(9)

        val.System = buffer.ToString()

 

        userid = "jdoe"

        passcode = "1234"

 

        AceInitialize()

        res = SD_Init(SdiHandle)

        res = SD_Lock(SdiHandle, userid)

        res = SD_Check(SdiHandle, passcode, userid)

        If (res = ACM_NEW_PIN_REQUIRED) Then

            res = AceGetPinParams(SdiHandle, val)

            System.Console.WriteLine("Min size = {0}", val.Min)

            System.Console.WriteLine("Max size = {0}", val.Max)

            System.Console.WriteLine("Selectable = {0}", val.Selectable)

            System.Console.WriteLine("Alphanumeric = {0}", val.Alphanumeric)

            System.Console.WriteLine("System generated = {0}", val.System)

        End If

        SD_Close(SdiHandle)

    End Sub

End Module

 

[C#]

using System;

using System.Text;

using System.Runtime.InteropServices;

 

namespace ACEClntdotNet

{

                public class SyncDemo

                {

                                /* Holds pin limits and related values */

                                public struct SD_PIN

                                {

                                                public byte Min;

                                                public byte Max;

                                                public byte Selectable;

                                                public byte Alphanumeric;

                                                [MarshalAs(UnmanagedType.ByValTStr,SizeConst=18)]

                                                public String System;

                                }

 

                                /* initialization and shutdown calls */

                                [DllImport("aceclnt.dll")]

                                public static extern int AceInitialize();

 

                                [DllImport("aceclnt.dll")]

                                public static extern int AceGetPinParams(int SdiHandle, ref SD_PIN val);

 

                                /* Synchronous and thread-safe calls */

                                [DllImport("aceclnt.dll")]

                                public static extern int SD_Init(out int SdiHandle);

                                [DllImport("aceclnt.dll")]

                                public static extern int SD_Lock(int SdiHandle,String userID);

                                [DllImport("aceclnt.dll")]

                                public static extern int SD_Check(int SdiHandle,String passcode,String userID);

                                [DllImport("aceclnt.dll")]

                                public static extern int SD_Pin(int SdiHandle,String pin);

                                [DllImport("aceclnt.dll")]

                                public static extern int SD_Close(int SdiHandle);                   

 

                                public static int ACM_NEW_PIN_REQUIRED        =5;

 

                                /// <summary>

                                /// The main entry point for the application.

                                /// </summary>

                                [STAThread]

                                static void Main(string[] args)

                                {             

                                                int handle;

                                                int res;

 

                                                AceInitialize();

                                                res=SD_Init(out handle);

                                                res=SD_Lock(handle,"jdoe");

                                                res=SD_Check(handle,"1234","jdoe");

                                                if (res==ACM_NEW_PIN_REQUIRED)

                                                {

                                                                SD_PIN val;

                                                                val.Min=0;

                                                                val.Max=0;

                                                                val.Alphanumeric=0;

                                                                val.Selectable=0;

                                                                StringBuilder buffer = new StringBuilder(128);

 

                                                                val.System=buffer.ToString();

                                                                res=AceGetPinParams(hanlde,ref val);

                                                                System.Console.WriteLine("Minimum PIN length ={0}",val.Min);

                                                                System.Console.WriteLine("Maximum PIN length ={0}",val.Max);

                                                                System.Console.WriteLine("Alphanumeric option ={0}",val.Alphanumeric);

                                                                System.Console.WriteLine("User selectable PIN option ={0}",val.Selectable);

                                                                System.Console.WriteLine("System assigned PIN ={0}",val.System);

                                                }

                                                res=SD_Close(handle);

                                }

                }

}

 

If the .NET code is performing ASP.NET work (for example is being used for a .NET Web Service then care should be taken of the level of privilege that is required to use the ACE/Agent API.   Key to an agent working correctly is the ability fo the back-end agent to have read-access to the registry.  Specifically it needs to read HKEY_LOCAL_MACHINE\SOFTWARE\SDTI\ACECLIENT\NodeSecret.  A default installation will not allow this and the .NET custom code will fail.

One potential resolution is to allow read access for the ASP.NET process to read this one specific key.  This is done by updating the permissions on the key with the regedit.exe command as follows:

For Windows 2003 and Windows XP:
    Run regedit
    Locate the HKEY_LOCAL_MACHINE\SOFTWARE\SDTI\ACECLIENT key in the left hand panel
    Right Click the key and select "Permissions..."
    Add READ permissions for the user "ASPNET"

For Windows 2000
    Run regedit
    Locate the HKEY_LOCAL_MACHINE\SOFTWARE\SDTI\ACECLIENT key in the left hand panel
    Right Click the key and select "Permissions..."
    Add READ permissions for the user "NT AUTHORITY\NETWORK SERVICE"

For more comprehensive advice on the subject of the privilege mechanisms involved the initial Microsoft document at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchsecurityconcernsforvisualbasicnetprogrammers.asp should prove useful.

For full information on the C API see the RSA Authentication Agent API 5.0.3 for C documentation or

RSA Authentication Agent API 6.1 for C Developer?s Guide the which is also available online at

https://knowledge.rsasecurity.com/docs/rsa_securid/rsa_ace_agents/61/APIGuide.pdf

 

Other related solutions which might be useful:

 

     How to accessRSA Cookie API from Microsoft.NETa22141         How to accessRSA Cookie API from Microsoft.NETHow to access RSA Cookie API from .NET

     How to access the RSAACE/Server Admin API from Microsoft.NETa22689         How to access the RSAACE/Server Admin API from Microsoft.NETHow to access the RSA ACE/Server Admin API from Microsoft .NET

     How to use RSACookieAPI from ASP.NET with RSA ACE/Agent 5.x for Weba26304         How to use RSACookieAPI from ASP.NET with RSA ACE/Agent 5.x for WebHow to use RSACookieAPI from ASP.NET with RSA ACE/Agent 5.x for Web

     How toutilize RSA ACE/Agent Authentication APIfrom an ASP.NET Applicationa22650         How toutilize RSA ACE/Agent Authentication APIfrom an ASP.NET ApplicationHow to utilize RSA ACE/Agent Authentication API from an ASP.NET application

     How to use Microsoft Visual Studio .NET 2003 to write RSA ACE/Server Administration API programsa24600         How to use Microsoft Visual Studio .NET 2003 to write RSA ACE/Server Administration API programsHow to use Microsoft Visual Studio .NET 2003 to write RSA Ace/Server Administration API programs

 

Legacy Article IDa22506

Attachments

    Outcomes