SEC_WINNT_AUTH_IDENTITY创建(SSPI)

时间:2015-03-05 12:23:40

标签: c++ windows credentials sspi

我尝试创建 SEC_WINNT_AUTH_IDENTITY 以用于对 AcquireCredentialsHandle 的调用,以获取此身份的凭据。但是我很难创建Authenfication日期。

以下是用于创建结构的代码:

#define SECURITY_WIN32
#include <Windows.h>
#include <sspi.h>


int main(int argc, char* argv[]) {

SEC_WINNT_AUTH_IDENTITY AuthId;
char* login = "login";
char* domain = "mydomain.com";
char* password = "pass";

AuthId.User = login;
AuthId.UserLength = strlen(login);
AuthId.Domain = domain;
AuthId.DomainLength = strlen(domain);
AuthId.Password = password;
AuthId.PasswordLength = strlen(password);
AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

//Here the call to AcquireCredentialHandle and the end of the program
}

问题在于结构需要unsigned short __RPC_FAR *User,但我无法找到关于此的任何信息以及我应该如何传递它的字符串。我在互联网上找到的例子都是直接使用字符串。

1 个答案:

答案 0 :(得分:1)

在这种情况下,ODBC的一些经验帮助了我。但是,它不能用于Unicode密码,我现在不需要它。但如果有人提示,那就太好了。

嗯,这是我的解决方案。我创建了帮助类:

部首:

class StringParam
{
public:
    StringParam();
    StringParam(const std::wstring& val);
    StringParam(const std::string& val);
    virtual ~StringParam();

    unsigned short* GetBuffer() const;
    unsigned long   GetBufferLength() const;
    unsigned long   GetLength() const;
private:
    unsigned short* buffer;
    unsigned long   bufferLength;
};

实现:

StringParam::StringParam():
    buffer(NULL),
    bufferLength(0)
{
}

StringParam::StringParam(const std::wstring& val):
    StringParam()
{
    size_t len = val.size(); // .length() is the same
    bufferLength = sizeof(unsigned short) * (len + 1);
    unsigned short* buf = new unsigned short[len + 1];
    memset(buf, 0, bufferLength);
    int i = 0;
    for (wchar_t c: val)
        buf[i++] = (unsigned short)c;

    buffer = reinterpret_cast<unsigned short*>(buf);
}

StringParam::StringParam(const std::string& val):
    StringParam()
{
    size_t len = val.size(); // .length() is the same
    bufferLength = sizeof(unsigned short) * (len + 1);
    unsigned short* buf = new unsigned short[len + 1];
    memset(buf, 0, bufferLength);
    int i = 0;
    for (char c: val)
        buf[i++] = (unsigned short)c;

    buffer = reinterpret_cast<unsigned short*>(buf);
}

StringParam::~StringParam()
{
    if (buffer)
    {
        delete[] buffer;
        buffer = NULL;
        bufferLength = 0;
    }
}

unsigned short* StringParam::GetBuffer() const
{
    return buffer;
}

unsigned long StringParam::GetBufferLength() const
{
    return bufferLength;
}

unsigned long StringParam::GetLength() const
{
    return bufferLength / sizeof(unsigned short);
}

用法:

SECURITY_STATUS res;

// Aquire credentials
CredHandle              credentials;
TimeStamp               credentialsExpiryTime;

SEC_WINNT_AUTH_IDENTITY userIdentity;
StringParam prmDomain("domain.com");
StringParam prmUser("username");
StringParam prmPassword("password#1");
// wstring version will also work:
//StringParam prmDomain(L"domain.com");
//StringParam prmUser(L"username");
//StringParam prmPassword(L"password#1");

userIdentity.Domain = prmDomain.GetBuffer();
userIdentity.DomainLength = prmDomain.GetLength();
userIdentity.User = prmUser.GetBuffer();
userIdentity.UserLength = prmUser.GetLength();
userIdentity.Password = prmPassword.GetBuffer();
userIdentity.PasswordLength = prmPassword.GetLength();
userIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
res = AcquireCredentialsHandle(NULL, L"Kerberos", SECPKG_CRED_INBOUND, NULL, &userIdentity, NULL, NULL, &credentials, &credentialsExpiryTime);

对我来说效果很好。诀窍是wchar_t长4个字节。但SSPI使用UTF-16。在ODBC中,从wstring转换的Unicode字符有效,但这里有些不同。