我有一些软件使用 RSA 身份验证代理的文档化 API。这是一个作为服务在域中的客户端计算机上运行的产品,并通过与集中安装的“RSA 身份验证管理器”通信来对本地用户进行身份验证。
Authentication Agent 的 API 在此处公开记录:Authentication Agent API 8.1.1 for C Developers Guide。但是,文档似乎不正确,我无权访问 RSA 头文件——它们不是公开的;只有 PDF 文档可供下载,无需向 RSA 支付 $$。如果这里有人可以访问最新的头文件,您能否帮我确认文档是否已过时?
API 文档中给出的函数签名似乎不正确——事实上,我完全相信它们在 x64 机器上是错误的。例如,最新的 PDF 文档显示如下:
int WINAPI AceSetUserData(SDI_HANDLE hdl, unsigned int userData)
int WINAPI AceGetUserData(SDI_HANDLE hdl, unsigned int *pUserData)
文档多次声明“userData”值是一个 32 位的数量,例如在 、 和 的AceInit
文档AceSetUserData
中AceGetUserData
。文档的相关摘录AceGetUserData
:
该函数是同步的,调用者必须提供一个指针作为第二个参数,指向一个 32 位存储区(即无符号整数),将用户数据值复制到该存储区。
这显然是错误的——从一些实验来看,如果你传入一个指向填充 0xff 的缓冲区中心的指针,那么AceGetUserData
肯定会写出一个 64 位的值,而不是 32 位的数量。
我的版本aceclnt.dll
是 8.1.3.563;相应的文档标记为“Authentication Agent API 8.1 SP1”,这对应于 Authentication Agent 本身的 7.3.1 版本。
测试代码
给出了完整的测试代码,即使它根本与问题无关......如果其他人运行测试代码(我知道它的作用!),我需要的是可以访问 RSA 标头的人可以确认函数签名的文件。
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef WIN32
#include <Windows.h>
#include <tchar.h>
#define SDAPI WINAPI
#else
#define SDAPI
#endif
typedef int SDI_HANDLE;
typedef uint32_t SD_BOOL;
typedef void (SDAPI* AceCallback)(SDI_HANDLE);
#define ACE_SUCCESS 1
#define ACE_PROCESSING 150
typedef SD_BOOL (SDAPI* AceInitializeEx_proto)(const char*, char*, uint32_t);
typedef int (SDAPI* AceInit_proto)(SDI_HANDLE*, void*, AceCallback);
typedef int (SDAPI* AceClose_proto)(SDI_HANDLE, AceCallback);
typedef int (SDAPI* AceGetUserData_proto)(SDI_HANDLE, void*);
typedef int (SDAPI* AceSetUserData_proto)(SDI_HANDLE, void*);
struct Api {
AceInitializeEx_proto AceInitializeEx;
AceInit_proto AceInit;
AceClose_proto AceClose;
AceGetUserData_proto AceGetUserData;
AceSetUserData_proto AceSetUserData;
} api;
static void api_init(struct Api* api) {
// All error-checking stripped...
HMODULE dll = LoadLibrary(_T("aceclnt.dll")); // leak this for the demo
api->AceInitializeEx = (AceInitializeEx_proto)GetProcAddress(dll, "AceInitializeEx");
api->AceInit = (AceInit_proto)GetProcAddress(dll, "AceInit");
api->AceClose = (AceClose_proto)GetProcAddress(dll, "AceClose");
api->AceGetUserData = (AceGetUserData_proto)GetProcAddress(dll, "AceGetUserData");
api->AceSetUserData = (AceSetUserData_proto)GetProcAddress(dll, "AceSetUserData");
int success = api->AceInitializeEx("C:\\my\\conf\\directory", 0, 0);
assert(success);
}
static void demoFunction(SDI_HANDLE handle) {
union {
unsigned char testBuffer[sizeof(void *) * 3];
void *forceAlignment;
} u;
memset(u.testBuffer, 0xA5, sizeof u.testBuffer);
int err = api.AceGetUserData(handle, (void*)(u.testBuffer + sizeof(void*)));
assert(err == ACE_SUCCESS);
fputs("DEBUG: testBuffer =", stderr);
for (size_t i = 0; i < sizeof(u.testBuffer); i++) {
if (i % 4 == 0)
putc(' ', stderr);
fprintf(stderr, "%02x", u.testBuffer[i]);
}
fputc('\n', stderr);
// Prints:
// DEBUG: testBuffer = a5a5a5a5 a5a5a5a5 00000000 00000000 a5a5a5a5 a5a5a5a5
// According to the docs, this should only write out a 32-bit value
}
static void SDAPI demoCallback(SDI_HANDLE h) {
fprintf(stderr, "Callback invoked, handle = %p\n", (void*)h);
}
int main(int argc, const char** argv)
{
api_init(&api);
SDI_HANDLE h;
int err = api.AceInit(&h, /* contentious argument */ 0, &demoCallback);
assert(err == ACE_PROCESSING);
demoFunction(h);
api.AceClose(h, 0);
return 0;
}