我正在尝试使用SSPI身份验证连接到Sql Server。有一个使用InitializeSecurityContext的FreeTdssspi.C的C示例(我希望如此)
问题是它调用InitializeSecurityContext两次。首先调用(tds_sspi_get_auth)函数进行身份验证,将其放入登录数据包。服务主体名称(SPN)创建为(使用项目JEDI JwaSspi)
FSPN := WideString(Format('MSSQLSvc/%s:%d', [FHostName, FPort]));
status := InitializeSecurityContext(@FCred, nil, PSecWChar(FSPN),
ISC_REQ_CONFIDENTIALITY or ISC_REQ_REPLAY_DETECT or ISC_REQ_CONNECTION,
0, SECURITY_NETWORK_DREP, nil, 0, @FCredCtx, @desc, attrs, @ts);
其中FSPN: WideString;
对InitializeSecurityContext的第二个调用(tds_sspi_handle_next)使用相同的FSPN和来自服务器的响应
status := InitializeSecurityContext(@FCred, @FCredCtx, PSecWChar(FSPN),
ISC_REQ_CONFIDENTIALITY or ISC_REQ_REPLAY_DETECT or ISC_REQ_CONNECTION,
0, SECURITY_NETWORK_DREP, @in_desc, 0, @FCredCtx, @out_desc, attrs, @ts);
现在困难的部分是:在用asprintf
创建的C SPN上,在第一次调用InitializeSecurityContext后,它发生了变化(在$08 $04 $01 $00 $4E ...
之后是$4D $00 $53 $00 $53 $00 ...
),我想它被Digest或类似的东西取代了。通过这样使用,我在oleaut32.dll中的某个位置有访问违规。
这是"绝地计划"的错误。SecHandle声明为
_SecHandle = record
dwLower: ULONG_PTR;
dwUpper: ULONG_PTR;
end;
其中
INT_PTR = Integer;
{$EXTERNALSYM INT_PTR}
PINT_PTR = ^INT_PTR;
{$EXTERNALSYM PINT_PTR}
UINT_PTR = Longword;
{$EXTERNALSYM UINT_PTR}
PUINT_PTR = ^UINT_PTR;
{$EXTERNALSYM PUINT_PTR}
LONG_PTR = Longint;
{$EXTERNALSYM LONG_PTR}
PLONG_PTR = ^LONG_PTR;
{$EXTERNALSYM PLONG_PTR}
ULONG_PTR = Longword;
{$EXTERNALSYM ULONG_PTR}
PULONG_PTR = ^ULONG_PTR;
{$EXTERNALSYM PULONG_PTR}
由Microsoft ULONG_PTR是
typedef unsigned __int3264 ULONG_PTR;
和
2.2.1 __int3264
一个别名,解析为:32位翻译和执行环境中的__int32,或64位翻译和执行环境中的__int64。为了向后兼容,它是32位的。封送处理期间,发送端必须截断较高的4个字节,并且在解组处理期间,接收端必须按照[C706]第14.2.5节的规定进行适当扩展(有符号或无符号)。
所以当我在课堂上宣布
private
FCred: CredHandle;
FCredCtx: CtxtHandle;
FSPN: WideString;
具有64位可执行文件的InitializeSecurityContext通过将更大的结构写入FCredCtx破坏FSPN来破坏我的类变量。使用NativeInt或NativeUInt代替Integer/Longword等修复了问题。