Add Negotiate SSPI authentication module filtering

This commit is contained in:
Marc-André Moreau 2022-10-06 16:47:32 -04:00 committed by David Fort
parent f620a31d57
commit 27a865af74
14 changed files with 792 additions and 106 deletions

View File

@ -3227,6 +3227,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->AuthenticationOnly = enable;
}
CommandLineSwitchCase(arg, "auth-pkg-list")
{
if (!freerdp_settings_set_string(settings, FreeRDP_AuthenticationPackageList,
arg->Value))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "auto-reconnect")
{
settings->AutoReconnectionEnabled = enable;

View File

@ -58,6 +58,8 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
"Audio output mode" },
{ "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
"Authenticate only" },
{ "auth-pkg-list", COMMAND_LINE_VALUE_REQUIRED, "<!ntlm,kerberos>", NULL, NULL, -1, NULL,
"Authentication package filter (comma-separated list, use '!' to exclude)" },
{ "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Authentication (experimental)" },
{ "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
@ -227,8 +229,8 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
"Send unicode symbols, e.g. use the local keyboard map. ATTENTION: Does not work with every "
"RDP server!" },
{ "kerberos", COMMAND_LINE_VALUE_REQUIRED,
"[lifetime:<time>,start-time:<time>,renewable-lifetime:<time>,cache:<path>,armor:<path>,"
"pkinit-anchors:<path>,pkcs11-module:<name>]",
"[kdc-url:<url>,lifetime:<time>,start-time:<time>,renewable-lifetime:<time>,cache:<path>,"
"armor:<path>,pkinit-anchors:<path>,pkcs11-module:<name>]",
NULL, NULL, -1, NULL, "Kerberos options" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info-string>", NULL, NULL, -1, NULL,
"Load balance info" },

View File

@ -645,6 +645,7 @@ typedef struct
#define FreeRDP_TLSMinVersion (1107)
#define FreeRDP_TLSMaxVersion (1108)
#define FreeRDP_TlsSecretsFile (1109)
#define FreeRDP_AuthenticationPackageList (1110)
#define FreeRDP_MstscCookieMode (1152)
#define FreeRDP_CookieMaxLength (1153)
#define FreeRDP_PreconnectionId (1154)
@ -1133,7 +1134,8 @@ struct rdp_settings
ALIGN64 UINT16 TLSMinVersion; /* 1107 */
ALIGN64 UINT16 TLSMaxVersion; /* 1108 */
ALIGN64 char* TlsSecretsFile; /* 1109 */
UINT64 padding1152[1152 - 1110]; /* 1110 */
ALIGN64 char* AuthenticationPackageList; /* 1110 */
UINT64 padding1152[1152 - 1111]; /* 1111 */
/* Connection Cookie */
ALIGN64 BOOL MstscCookieMode; /* 1152 */

View File

@ -2372,6 +2372,9 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
case FreeRDP_AssistanceFile:
return settings->AssistanceFile;
case FreeRDP_AuthenticationPackageList:
return settings->AuthenticationPackageList;
case FreeRDP_AuthenticationServiceClass:
return settings->AuthenticationServiceClass;
@ -2636,6 +2639,9 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
case FreeRDP_AssistanceFile:
return settings->AssistanceFile;
case FreeRDP_AuthenticationPackageList:
return settings->AuthenticationPackageList;
case FreeRDP_AuthenticationServiceClass:
return settings->AuthenticationServiceClass;
@ -2910,6 +2916,9 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
case FreeRDP_AssistanceFile:
return update_string(&settings->AssistanceFile, cnv.cc, len, cleanup);
case FreeRDP_AuthenticationPackageList:
return update_string(&settings->AuthenticationPackageList, cnv.cc, len, cleanup);
case FreeRDP_AuthenticationServiceClass:
return update_string(&settings->AuthenticationServiceClass, cnv.cc, len, cleanup);

View File

@ -317,6 +317,7 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_AllowedTlsCiphers, 7, "FreeRDP_AllowedTlsCiphers" },
{ FreeRDP_AlternateShell, 7, "FreeRDP_AlternateShell" },
{ FreeRDP_AssistanceFile, 7, "FreeRDP_AssistanceFile" },
{ FreeRDP_AuthenticationPackageList, 7, "FreeRDP_AuthenticationPackageList" },
{ FreeRDP_AuthenticationServiceClass, 7, "FreeRDP_AuthenticationServiceClass" },
{ FreeRDP_BitmapCachePersistFile, 7, "FreeRDP_BitmapCachePersistFile" },
{ FreeRDP_CardName, 7, "FreeRDP_CardName" },

View File

@ -52,11 +52,14 @@ struct rdp_credssp_auth
const rdpContext* rdp_ctx;
SecurityFunctionTable* table;
SecPkgInfo* info;
SEC_WINNT_AUTH_IDENTITY_WINPR identity;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINPR_NTLM_SETTINGS ntlmSettings;
SEC_WINPR_KERBEROS_SETTINGS kerberosSettings;
CredHandle credentials;
BOOL server;
SecPkgContext_Bindings* bindings;
TCHAR* spn;
WCHAR* package_list;
CtxtHandle context;
SecBuffer input_buffer;
SecBuffer output_buffer;
@ -66,7 +69,7 @@ struct rdp_credssp_auth
};
static BOOL parseKerberosDeltat(const char* value, INT32* dest, const char* message);
static BOOL auth_setup_identity(rdpCredsspAuth* auth, SEC_WINNT_AUTH_IDENTITY_WINPR* identity);
static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth);
static SecurityFunctionTable* auth_resolve_sspi_table(const rdpSettings* settings);
rdpCredsspAuth* credssp_auth_new(const rdpContext* rdp_ctx)
@ -108,7 +111,7 @@ BOOL credssp_auth_init(rdpCredsspAuth* auth, TCHAR* pkg_name, SecPkgContext_Bind
WLog_DBG(TAG, "Using package: %s (cbMaxToken: %u bytes)", pkg_name, auth->info->cbMaxToken);
/* Setup common identity settings */
if (!auth_setup_identity(auth, &auth->identity))
if (!credssp_auth_setup_identity(auth))
return FALSE;
auth->bindings = bindings;
@ -116,12 +119,45 @@ BOOL credssp_auth_init(rdpCredsspAuth* auth, TCHAR* pkg_name, SecPkgContext_Bind
return TRUE;
}
BOOL credssp_auth_setup_auth_data(rdpCredsspAuth* auth, const SEC_WINNT_AUTH_IDENTITY* identity,
SEC_WINNT_AUTH_IDENTITY_WINPR* pAuthData)
{
SEC_WINNT_AUTH_IDENTITY_EXW* identityEx;
ZeroMemory(pAuthData, sizeof(SEC_WINNT_AUTH_IDENTITY_WINPR));
identityEx = &pAuthData->identity;
identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identityEx->Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EX);
identityEx->User = identity->User;
identityEx->UserLength = identity->UserLength;
identityEx->Domain = identity->Domain;
identityEx->DomainLength = identity->DomainLength;
identityEx->Password = identity->Password;
identityEx->PasswordLength = identity->PasswordLength;
identityEx->Flags = identity->Flags;
identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
identityEx->Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
if (auth->package_list)
{
identityEx->PackageList = (UINT16*)auth->package_list;
identityEx->PackageListLength = _wcslen(auth->package_list);
}
pAuthData->ntlmSettings = &auth->ntlmSettings;
pAuthData->kerberosSettings = &auth->kerberosSettings;
return TRUE;
}
BOOL credssp_auth_setup_client(rdpCredsspAuth* auth, const char* target_service,
const char* target_hostname, const SEC_WINNT_AUTH_IDENTITY* identity,
const char* pkinit)
{
SECURITY_STATUS status;
void* identityPtr = NULL;
void* pAuthData = NULL;
SEC_WINNT_AUTH_IDENTITY_WINPR winprAuthData;
WINPR_ASSERT(auth);
WINPR_ASSERT(auth->table);
@ -133,26 +169,24 @@ BOOL credssp_auth_setup_client(rdpCredsspAuth* auth, const char* target_service,
if (identity)
{
if (sspi_CopyAuthIdentity(&auth->identity.identity, identity) < 0)
return FALSE;
auth->identity.identity.Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
credssp_auth_setup_auth_data(auth, identity, &winprAuthData);
if (pkinit)
{
auth->identity.kerberosSettings.pkinitX509Identity = _strdup(pkinit);
if (!auth->identity.kerberosSettings.pkinitX509Identity)
auth->kerberosSettings.pkinitX509Identity = _strdup(pkinit);
if (!auth->kerberosSettings.pkinitX509Identity)
{
WLog_ERR(TAG, "unable to copy pkinitArgs");
return FALSE;
}
}
identityPtr = &auth->identity;
pAuthData = (void*)&winprAuthData;
}
status =
auth->table->AcquireCredentialsHandle(NULL, auth->info->Name, SECPKG_CRED_OUTBOUND, NULL,
identityPtr, NULL, NULL, &auth->credentials, NULL);
pAuthData, NULL, NULL, &auth->credentials, NULL);
if (status != SEC_E_OK)
{
@ -161,9 +195,9 @@ BOOL credssp_auth_setup_client(rdpCredsspAuth* auth, const char* target_service,
return FALSE;
}
if (auth->identity.kerberosSettings.kdcUrl)
if (auth->kerberosSettings.kdcUrl)
{
SecPkgCredentials_KdcUrlA attr = { auth->identity.kerberosSettings.kdcUrl };
SecPkgCredentials_KdcUrlA attr = { auth->kerberosSettings.kdcUrl };
if (auth->table->SetCredentialsAttributes)
status = auth->table->SetCredentialsAttributes(
@ -185,18 +219,22 @@ BOOL credssp_auth_setup_client(rdpCredsspAuth* auth, const char* target_service,
BOOL credssp_auth_setup_server(rdpCredsspAuth* auth)
{
SECURITY_STATUS status;
void* auth_data = NULL;
void* pAuthData = NULL;
SEC_WINNT_AUTH_IDENTITY_WINPR winprAuthData;
WINPR_ASSERT(auth);
WINPR_ASSERT(auth->table);
if (auth->identity.ntlmSettings.samFile || auth->identity.ntlmSettings.hashCallback ||
auth->identity.kerberosSettings.keytab)
auth_data = &auth->identity;
if (auth->ntlmSettings.samFile || auth->ntlmSettings.hashCallback ||
auth->kerberosSettings.keytab)
{
credssp_auth_setup_auth_data(auth, &auth->identity, &winprAuthData);
pAuthData = &winprAuthData;
}
status =
auth->table->AcquireCredentialsHandle(NULL, auth->info->Name, SECPKG_CRED_INBOUND, NULL,
auth_data, NULL, NULL, &auth->credentials, NULL);
pAuthData, NULL, NULL, &auth->credentials, NULL);
if (status != SEC_E_OK)
{
WLog_ERR(TAG, "AcquireCredentialsHandleA failed with %s [0x%08X]",
@ -540,10 +578,10 @@ void credssp_auth_free(rdpCredsspAuth* auth)
auth->table->FreeContextBuffer(auth->info);
}
sspi_FreeAuthIdentity(&auth->identity.identity);
sspi_FreeAuthIdentity(&auth->identity);
krb_settings = &auth->identity.kerberosSettings;
ntlm_settings = &auth->identity.ntlmSettings;
krb_settings = &auth->kerberosSettings;
ntlm_settings = &auth->ntlmSettings;
free(krb_settings->kdcUrl);
free(krb_settings->cache);
@ -553,6 +591,7 @@ void credssp_auth_free(rdpCredsspAuth* auth)
free(krb_settings->pkinitX509Identity);
free(ntlm_settings->samFile);
free(auth->package_list);
free(auth->spn);
sspi_SecBufferFree(&auth->input_buffer);
sspi_SecBufferFree(&auth->output_buffer);
@ -634,7 +673,7 @@ static SecurityFunctionTable* auth_resolve_sspi_table(const rdpSettings* setting
return InitSecurityInterfaceEx(0);
}
static BOOL auth_setup_identity(rdpCredsspAuth* auth, SEC_WINNT_AUTH_IDENTITY_WINPR* identity)
static BOOL credssp_auth_setup_identity(rdpCredsspAuth* auth)
{
const rdpSettings* settings;
SEC_WINPR_KERBEROS_SETTINGS* krb_settings;
@ -648,9 +687,8 @@ static BOOL auth_setup_identity(rdpCredsspAuth* auth, SEC_WINNT_AUTH_IDENTITY_WI
settings = auth->rdp_ctx->settings;
WINPR_ASSERT(settings);
WINPR_ASSERT(identity);
krb_settings = &identity->kerberosSettings;
ntlm_settings = &identity->ntlmSettings;
krb_settings = &auth->kerberosSettings;
ntlm_settings = &auth->ntlmSettings;
if (settings->KerberosLifeTime)
parseKerberosDeltat(settings->KerberosLifeTime, &krb_settings->lifeTime, "lifetime");
@ -726,7 +764,17 @@ static BOOL auth_setup_identity(rdpCredsspAuth* auth, SEC_WINNT_AUTH_IDENTITY_WI
ntlm_settings->hashCallbackArg = peer;
}
identity->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
if (settings->AuthenticationPackageList)
{
ConvertToUnicode(CP_UTF8, 0, settings->AuthenticationPackageList, -1, &auth->package_list,
0);
if (!auth->package_list)
return FALSE;
}
auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
auth->identity.Flags |= SEC_WINNT_AUTH_IDENTITY_EXTENDED;
return TRUE;
}

View File

@ -593,7 +593,8 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
if (SelectedProtocol & PROTOCOL_HYBRID)
{
SEC_WINNT_AUTH_IDENTITY* identity = nego_get_identity(rdp->nego);
sspi_CopyAuthIdentity(&client->identity, identity);
sspi_CopyAuthIdentity(&client->identity,
(const SEC_WINNT_AUTH_IDENTITY_INFO*)identity);
IFCALLRET(client->Logon, client->authenticated, client, &client->identity,
TRUE);
nego_free_nla(rdp->nego);

View File

@ -326,6 +326,7 @@ static const size_t string_list_indices[] = {
FreeRDP_AllowedTlsCiphers,
FreeRDP_AlternateShell,
FreeRDP_AssistanceFile,
FreeRDP_AuthenticationPackageList,
FreeRDP_AuthenticationServiceClass,
FreeRDP_BitmapCachePersistFile,
FreeRDP_CardName,

View File

@ -661,9 +661,11 @@ typedef struct
#define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
#define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
#define SEC_WINNT_AUTH_IDENTITY_MARSHALLED 0x4
#define SEC_WINNT_AUTH_IDENTITY_ONLY 0x8
#define SEC_WINNT_AUTH_IDENTITY_EXTENDED 0x100
#if !defined(_WIN32) || defined(_UWP)
#if !defined(_WIN32) || defined(_UWP) || defined(__MINGW32__)
#if defined(__clang__)
#pragma clang diagnostic push
@ -675,7 +677,6 @@ typedef struct
typedef struct
{
/* TSPasswordCreds */
UINT16* User;
UINT32 UserLength;
UINT16* Domain;
@ -687,7 +688,6 @@ typedef struct
typedef struct
{
/* TSPasswordCreds */
BYTE* User;
UINT32 UserLength;
BYTE* Domain;
@ -697,17 +697,15 @@ typedef struct
UINT32 Flags;
} SEC_WINNT_AUTH_IDENTITY_A, *PSEC_WINNT_AUTH_IDENTITY_A;
typedef struct
{
/* TSPasswordCreds */
UINT16* User;
UINT32 UserLength;
UINT16* Domain;
UINT32 DomainLength;
UINT16* Password;
UINT32 PasswordLength;
UINT32 Flags;
} SEC_WINNT_AUTH_IDENTITY;
// Always define SEC_WINNT_AUTH_IDENTITY to SEC_WINNT_AUTH_IDENTITY_W
#ifdef UNICODE
#define SEC_WINNT_AUTH_IDENTITY SEC_WINNT_AUTH_IDENTITY_W
#define PSEC_WINNT_AUTH_IDENTITY PSEC_WINNT_AUTH_IDENTITY_W
#else
#define SEC_WINNT_AUTH_IDENTITY SEC_WINNT_AUTH_IDENTITY_W
#define PSEC_WINNT_AUTH_IDENTITY PSEC_WINNT_AUTH_IDENTITY_W
#endif
#endif /* _AUTH_IDENTITY_DEFINED */
@ -725,7 +723,7 @@ typedef struct
UINT16* Password;
UINT32 PasswordLength;
UINT32 Flags;
BYTE* PackageList;
UINT16* PackageList;
UINT32 PackageListLength;
} SEC_WINNT_AUTH_IDENTITY_EXW, *PSEC_WINNT_AUTH_IDENTITY_EXW;
@ -744,12 +742,79 @@ typedef struct
UINT32 PackageListLength;
} SEC_WINNT_AUTH_IDENTITY_EXA, *PSEC_WINNT_AUTH_IDENTITY_EXA;
#ifdef UNICODE
#define SEC_WINNT_AUTH_IDENTITY_EX SEC_WINNT_AUTH_IDENTITY_EXW
#define PSEC_WINNT_AUTH_IDENTITY_EX PSEC_WINNT_AUTH_IDENTITY_EXW
#else
#define SEC_WINNT_AUTH_IDENTITY_EX SEC_WINNT_AUTH_IDENTITY_EXA
#define PSEC_WINNT_AUTH_IDENTITY_EX PSEC_WINNT_AUTH_IDENTITY_EXA
#endif
#endif /* SEC_WINNT_AUTH_IDENTITY_VERSION */
#ifndef SEC_WINNT_AUTH_IDENTITY_VERSION_2
#define SEC_WINNT_AUTH_IDENTITY_VERSION_2 0x201
typedef struct _SEC_WINNT_AUTH_IDENTITY_EX2
{
UINT32 Version;
UINT16 cbHeaderLength;
UINT32 cbStructureLength;
UINT32 UserOffset;
UINT16 UserLength;
UINT32 DomainOffset;
UINT16 DomainLength;
UINT32 PackedCredentialsOffset;
UINT16 PackedCredentialsLength;
UINT32 Flags;
UINT32 PackageListOffset;
UINT16 PackageListLength;
} SEC_WINNT_AUTH_IDENTITY_EX2, *PSEC_WINNT_AUTH_IDENTITY_EX2;
#endif /* SEC_WINNT_AUTH_IDENTITY_VERSION_2 */
#ifndef _AUTH_IDENTITY_INFO_DEFINED
#define _AUTH_IDENTITY_INFO_DEFINED
// https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-sec_winnt_auth_identity_info
typedef union _SEC_WINNT_AUTH_IDENTITY_INFO
{
SEC_WINNT_AUTH_IDENTITY_EXW AuthIdExw;
SEC_WINNT_AUTH_IDENTITY_EXA AuthIdExa;
SEC_WINNT_AUTH_IDENTITY_A AuthId_a;
SEC_WINNT_AUTH_IDENTITY_W AuthId_w;
SEC_WINNT_AUTH_IDENTITY_EX2 AuthIdEx2;
} SEC_WINNT_AUTH_IDENTITY_INFO, *PSEC_WINNT_AUTH_IDENTITY_INFO;
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_PROCESS_ENCRYPTED 0x10
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SYSTEM_PROTECTED 0x20
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_USER_PROTECTED 0x40
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SYSTEM_ENCRYPTED 0x80
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_RESERVED 0x10000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_NULL_USER 0x20000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_NULL_DOMAIN 0x40000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_ID_PROVIDER 0x80000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_USE_MASK 0xFF000000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_CREDPROV_DO_NOT_SAVE 0x80000000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_SAVE_CRED_CHECKED 0x40000000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_NO_CHECKBOX 0x20000000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_CREDPROV_DO_NOT_LOAD 0x10000000
#define SEC_WINNT_AUTH_IDENTITY_FLAGS_VALID_SSPIPFC_FLAGS \
(SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_CREDPROV_DO_NOT_SAVE | \
SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_SAVE_CRED_CHECKED | \
SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_NO_CHECKBOX | \
SEC_WINNT_AUTH_IDENTITY_FLAGS_SSPIPFC_CREDPROV_DO_NOT_LOAD)
#endif /* _AUTH_IDENTITY_INFO_DEFINED */
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#if !defined(__MINGW32__)
typedef struct
{
ULONG_PTR dwLower;
@ -785,7 +850,9 @@ typedef struct
} SecBufferDesc;
typedef SecBufferDesc* PSecBufferDesc;
#endif /* !defined(_WIN32) || defined(_UWP) */
#endif /* __MINGW32__ */
#endif /* !defined(_WIN32) || defined(_UWP) || defined(__MINGW32__) */
typedef SECURITY_STATUS (*psSspiNtlmHashCallback)(void* client,
const SEC_WINNT_AUTH_IDENTITY* authIdentity,
@ -817,9 +884,9 @@ typedef struct
typedef struct
{
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINPR_NTLM_SETTINGS ntlmSettings;
SEC_WINPR_KERBEROS_SETTINGS kerberosSettings;
SEC_WINNT_AUTH_IDENTITY_EXW identity;
SEC_WINPR_NTLM_SETTINGS* ntlmSettings;
SEC_WINPR_KERBEROS_SETTINGS* kerberosSettings;
} SEC_WINNT_AUTH_IDENTITY_WINPR;
#define SECBUFFER_VERSION 0
@ -1357,8 +1424,26 @@ extern "C"
WINPR_API int sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY* identity,
const char* user, const char* domain,
LPWSTR password, ULONG passwordLength);
WINPR_API UINT32 sspi_GetAuthIdentityVersion(void* identity);
WINPR_API UINT32 sspi_GetAuthIdentityFlags(void* identity);
WINPR_API BOOL sspi_GetAuthIdentityUserDomainW(void* identity, WCHAR** pUser,
UINT32* pUserLength, WCHAR** pDomain,
UINT32* pDomainLength);
WINPR_API BOOL sspi_GetAuthIdentityUserDomainA(void* identity, char** pUser,
UINT32* pUserLength, char** pDomain,
UINT32* pDomainLength);
WINPR_API BOOL sspi_GetAuthIdentityPasswordW(void* identity, WCHAR** pPassword,
UINT32* pPasswordLength);
WINPR_API BOOL sspi_GetAuthIdentityPasswordA(void* identity, char** pPassword,
UINT32* pPasswordLength);
WINPR_API BOOL sspi_CopyAuthIdentityFieldsA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity,
char** pUser, char** pDomain, char** pPassword);
WINPR_API BOOL sspi_CopyAuthIdentityFieldsW(const SEC_WINNT_AUTH_IDENTITY_INFO* identity,
WCHAR** pUser, WCHAR** pDomain, WCHAR** pPassword);
WINPR_API BOOL sspi_CopyAuthPackageListA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity,
char** pPackageList);
WINPR_API int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
const SEC_WINNT_AUTH_IDENTITY* srcIdentity);
const SEC_WINNT_AUTH_IDENTITY_INFO* srcIdentity);
WINPR_API void sspi_FreeAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity);

View File

@ -179,10 +179,9 @@ static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(
PTimeStamp ptsExpiry)
{
#ifdef WITH_GSSAPI
SEC_WINNT_AUTH_IDENTITY* identity = pAuthData;
SEC_WINPR_KERBEROS_SETTINGS* krb_settings = NULL;
KRB_CREDENTIALS* credentials = NULL;
krb5_error_code rv;
krb5_error_code rv = 0;
krb5_context ctx = NULL;
krb5_ccache ccache = NULL;
krb5_keytab keytab = NULL;
@ -190,32 +189,23 @@ static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(
krb5_deltat start_time = 0;
krb5_principal principal = NULL;
krb5_init_creds_context creds_ctx = NULL;
BOOL is_unicode = FALSE;
char* domain = NULL;
char* username = NULL;
char* password = NULL;
const char* fallback_ccache = "MEMORY:";
if (identity)
if (pAuthData)
{
if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_EXTENDED)
krb_settings = &((SEC_WINNT_AUTH_IDENTITY_WINPR*)identity)->kerberosSettings;
UINT32 identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_EXTENDED)
krb_settings = (((SEC_WINNT_AUTH_IDENTITY_WINPR*)pAuthData)->kerberosSettings);
if (!sspi_CopyAuthIdentityFieldsA((const SEC_WINNT_AUTH_IDENTITY_INFO*)pAuthData, &username,
&domain, &password))
{
is_unicode = TRUE;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)identity->Domain, identity->DomainLength,
&domain, 0, NULL, NULL);
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)identity->User, identity->UserLength, &username,
0, NULL, NULL);
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)identity->Password, identity->PasswordLength,
&password, 0, NULL, NULL);
}
else
{
domain = (char*)identity->Domain;
username = (char*)identity->User;
password = (char*)identity->Password;
WLog_ERR(TAG, "Failed to copy auth identity fields");
goto cleanup;
}
if (!pszPrincipal)
@ -337,15 +327,13 @@ cleanup:
if (rv)
kerberos_log_msg(ctx, rv);
if (is_unicode)
{
if (domain)
free(domain);
if (username)
free(username);
if (password)
free(password);
}
if (domain)
free(domain);
if (username)
free(username);
if (password)
free(password);
if (principal)
krb5_free_principal(ctx, principal);
if (creds_ctx)

View File

@ -297,7 +297,6 @@ static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(
PTimeStamp ptsExpiry)
{
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
SEC_WINPR_NTLM_SETTINGS* settings = NULL;
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
@ -315,13 +314,15 @@ static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
if (identity)
if (pAuthData)
{
sspi_CopyAuthIdentity(&(credentials->identity), identity);
if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_EXTENDED)
settings = &((SEC_WINNT_AUTH_IDENTITY_WINPR*)pAuthData)->ntlmSettings;
UINT32 identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
sspi_CopyAuthIdentity(&(credentials->identity),
(const SEC_WINNT_AUTH_IDENTITY_INFO*)pAuthData);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_EXTENDED)
settings = (((SEC_WINNT_AUTH_IDENTITY_WINPR*)pAuthData)->ntlmSettings);
}
if (settings)

View File

@ -246,7 +246,49 @@ static BOOL negotiate_get_dword(HKEY hKey, const char* subkey, DWORD* pdwValue)
return TRUE;
}
static BOOL negotiate_get_config(BOOL* kerberos, BOOL* ntlm)
static BOOL negotiate_get_config_from_auth_package_list(void* pAuthData, BOOL* kerberos, BOOL* ntlm)
{
char* tok_ctx = NULL;
char* tok_ptr = NULL;
char* PackageList = NULL;
if (!sspi_CopyAuthPackageListA((const SEC_WINNT_AUTH_IDENTITY_INFO*)pAuthData, &PackageList))
return FALSE;
tok_ptr = strtok_s(PackageList, ",", &tok_ctx);
while (tok_ptr)
{
char* PackageName = tok_ptr;
BOOL PackageInclude = TRUE;
if (PackageName[0] == '!')
{
PackageName = &PackageName[1];
PackageInclude = FALSE;
}
if (!_stricmp(PackageName, "ntlm"))
{
*ntlm = PackageInclude;
}
else if (!_stricmp(PackageName, "kerberos"))
{
*kerberos = PackageInclude;
}
else
{
WLog_WARN(TAG, "Unknown authentication package name: %s", PackageName);
}
tok_ptr = strtok_s(NULL, ",", &tok_ctx);
}
free(PackageList);
return TRUE;
}
static BOOL negotiate_get_config(void* pAuthData, BOOL* kerberos, BOOL* ntlm)
{
HKEY hKey = NULL;
LONG rc;
@ -261,6 +303,11 @@ static BOOL negotiate_get_config(BOOL* kerberos, BOOL* ntlm)
#endif
*kerberos = TRUE;
if (negotiate_get_config_from_auth_package_list(pAuthData, kerberos, ntlm))
{
return TRUE; // use explicit authentication package list
}
rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, NEGO_REG_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (rc == ERROR_SUCCESS)
{
@ -1312,7 +1359,7 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(
{
BOOL kerberos, ntlm;
if (!negotiate_get_config(&kerberos, &ntlm))
if (!negotiate_get_config(pAuthData, &kerberos, &ntlm))
return SEC_E_INTERNAL_ERROR;
MechCred* creds = calloc(MECH_COUNT, sizeof(MechCred));
@ -1353,7 +1400,7 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(
{
BOOL kerberos, ntlm;
if (!negotiate_get_config(&kerberos, &ntlm))
if (!negotiate_get_config(pAuthData, &kerberos, &ntlm))
return SEC_E_INTERNAL_ERROR;
MechCred* creds = calloc(MECH_COUNT, sizeof(MechCred));

View File

@ -50,6 +50,8 @@ static wLog* g_Log = NULL;
static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
#if defined(WITH_NATIVE_SSPI)
static HMODULE g_SspiModule = NULL;
static SecurityFunctionTableW windows_SecurityFunctionTableW = { 0 };
static SecurityFunctionTableA windows_SecurityFunctionTableA = { 0 };
#endif
static SecurityFunctionTableW* g_SspiW = NULL;
@ -98,12 +100,14 @@ BOOL ShouldUseNativeSspi(void)
#if defined(WITH_NATIVE_SSPI)
BOOL InitializeSspiModule_Native(void)
{
SecurityFunctionTableW* pSspiW = NULL;
SecurityFunctionTableA* pSspiA = NULL;
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW;
INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA;
g_SspiModule = LoadLibraryA("secur32.dll");
if (!g_SspiModule)
g_SspiModule = LoadLibraryA("security.dll");
g_SspiModule = LoadLibraryA("sspicli.dll");
if (!g_SspiModule)
return FALSE;
@ -114,10 +118,44 @@ BOOL InitializeSspiModule_Native(void)
(INIT_SECURITY_INTERFACE_A)GetProcAddress(g_SspiModule, "InitSecurityInterfaceA");
if (pInitSecurityInterfaceW)
g_SspiW = pInitSecurityInterfaceW();
{
pSspiW = pInitSecurityInterfaceW();
if (pSspiW)
{
g_SspiW = &windows_SecurityFunctionTableW;
CopyMemory(g_SspiW, pSspiW,
FIELD_OFFSET(SecurityFunctionTableW, SetContextAttributesW));
g_SspiW->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
g_SspiW->SetContextAttributesW =
(SET_CONTEXT_ATTRIBUTES_FN_W)GetProcAddress(g_SspiModule, "SetContextAttributesW");
g_SspiW->SetCredentialsAttributesW = (SET_CREDENTIALS_ATTRIBUTES_FN_W)GetProcAddress(
g_SspiModule, "SetCredentialsAttributesW");
}
}
if (pInitSecurityInterfaceA)
g_SspiA = pInitSecurityInterfaceA();
{
pSspiA = pInitSecurityInterfaceA();
if (pSspiA)
{
g_SspiA = &windows_SecurityFunctionTableA;
CopyMemory(g_SspiA, pSspiA,
FIELD_OFFSET(SecurityFunctionTableA, SetContextAttributesA));
g_SspiA->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
g_SspiA->SetContextAttributesA =
(SET_CONTEXT_ATTRIBUTES_FN_W)GetProcAddress(g_SspiModule, "SetContextAttributesA");
g_SspiA->SetCredentialsAttributesA = (SET_CREDENTIALS_ATTRIBUTES_FN_W)GetProcAddress(
g_SspiModule, "SetCredentialsAttributesA");
}
}
return TRUE;
}

View File

@ -429,18 +429,465 @@ int sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY* identity, c
return 1;
}
UINT32 sspi_GetAuthIdentityVersion(void* identity)
{
UINT32 version;
if (!identity)
return 0;
version = *((UINT32*)identity);
if ((version == SEC_WINNT_AUTH_IDENTITY_VERSION) ||
(version == SEC_WINNT_AUTH_IDENTITY_VERSION_2))
{
return version;
}
return 0; // SEC_WINNT_AUTH_IDENTITY (no version)
}
UINT32 sspi_GetAuthIdentityFlags(void* identity)
{
UINT32 version;
UINT32 flags = 0;
if (!identity)
return 0;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
flags = ((SEC_WINNT_AUTH_IDENTITY_EX*)identity)->Flags;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
flags = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->Flags;
}
else // SEC_WINNT_AUTH_IDENTITY
{
flags = ((SEC_WINNT_AUTH_IDENTITY*)identity)->Flags;
}
return flags;
}
BOOL sspi_GetAuthIdentityUserDomainW(void* identity, WCHAR** pUser, UINT32* pUserLength,
WCHAR** pDomain, UINT32* pDomainLength)
{
UINT32 version;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
*pUser = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->User;
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->UserLength;
*pDomain = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->Domain;
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->DomainLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
UINT32 UserOffset = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->UserOffset;
UINT32 DomainOffset = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->DomainOffset;
*pUser = (WCHAR*)&((uint8_t*)identity)[UserOffset];
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->UserLength / 2;
*pDomain = (WCHAR*)&((uint8_t*)identity)[DomainOffset];
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->DomainLength / 2;
}
else // SEC_WINNT_AUTH_IDENTITY
{
*pUser = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_W*)identity)->User;
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_W*)identity)->UserLength;
*pDomain = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_W*)identity)->Domain;
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_W*)identity)->DomainLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityUserDomainA(void* identity, char** pUser, UINT32* pUserLength,
char** pDomain, UINT32* pDomainLength)
{
UINT32 version;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
*pUser = (char*)((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->User;
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->UserLength;
*pDomain = (char*)((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->Domain;
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->DomainLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
UINT32 UserOffset = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->UserOffset;
UINT32 DomainOffset = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->DomainOffset;
*pUser = (char*)&((uint8_t*)identity)[UserOffset];
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->UserLength;
*pDomain = (char*)&((uint8_t*)identity)[DomainOffset];
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->DomainLength;
}
else // SEC_WINNT_AUTH_IDENTITY
{
*pUser = (char*)((SEC_WINNT_AUTH_IDENTITY_A*)identity)->User;
*pUserLength = ((SEC_WINNT_AUTH_IDENTITY_A*)identity)->UserLength;
*pDomain = (char*)((SEC_WINNT_AUTH_IDENTITY_A*)identity)->Domain;
*pDomainLength = ((SEC_WINNT_AUTH_IDENTITY_A*)identity)->DomainLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityPasswordW(void* identity, WCHAR** pPassword, UINT32* pPasswordLength)
{
UINT32 version;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
*pPassword = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->Password;
*pPasswordLength = ((SEC_WINNT_AUTH_IDENTITY_EXW*)identity)->PasswordLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
return FALSE; // TODO: packed credentials
}
else // SEC_WINNT_AUTH_IDENTITY
{
*pPassword = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_W*)identity)->Password;
*pPasswordLength = ((SEC_WINNT_AUTH_IDENTITY_W*)identity)->PasswordLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityPasswordA(void* identity, char** pPassword, UINT32* pPasswordLength)
{
UINT32 version;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
*pPassword = (char*)((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->Password;
*pPasswordLength = ((SEC_WINNT_AUTH_IDENTITY_EXA*)identity)->PasswordLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
return FALSE; // TODO: packed credentials
}
else // SEC_WINNT_AUTH_IDENTITY
{
*pPassword = (char*)((SEC_WINNT_AUTH_IDENTITY_A*)identity)->Password;
*pPasswordLength = ((SEC_WINNT_AUTH_IDENTITY_A*)identity)->PasswordLength;
}
return TRUE;
}
BOOL sspi_CopyAuthIdentityFieldsA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pUser,
char** pDomain, char** pPassword)
{
BOOL success = FALSE;
char* UserA = NULL;
char* DomainA = NULL;
char* PasswordA = NULL;
WCHAR* UserW = NULL;
WCHAR* DomainW = NULL;
WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
if (!identity || !pUser || !pDomain || !pPassword)
return FALSE;
*pUser = *pDomain = *pPassword = NULL;
UINT32 identityFlags = sspi_GetAuthIdentityFlags((void*)identity);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (!sspi_GetAuthIdentityUserDomainA((void*)identity, &UserA, &UserLength, &DomainA,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordA((void*)identity, &PasswordA, &PasswordLength))
goto cleanup;
if (UserA && UserLength)
{
*pUser = _strdup(UserA);
if (!(*pUser))
goto cleanup;
}
if (DomainA && DomainLength)
{
*pDomain = _strdup(DomainA);
if (!(*pDomain))
goto cleanup;
}
if (PasswordA && PasswordLength)
{
*pPassword = _strdup(PasswordA);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
else
{
if (!sspi_GetAuthIdentityUserDomainW((void*)identity, &UserW, &UserLength, &DomainW,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordW((void*)identity, &PasswordW, &PasswordLength))
goto cleanup;
if (UserW && UserLength)
{
ConvertFromUnicode(CP_UTF8, 0, UserW, UserLength, pUser, 0, NULL, NULL);
if (!(*pUser))
goto cleanup;
}
if (DomainW && DomainLength)
{
ConvertFromUnicode(CP_UTF8, 0, DomainW, DomainLength, pDomain, 0, NULL, NULL);
if (!(*pDomain))
goto cleanup;
}
if (PasswordW && PasswordLength)
{
ConvertFromUnicode(CP_UTF8, 0, PasswordW, PasswordLength, pPassword, 0, NULL, NULL);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
cleanup:
return success;
}
BOOL sspi_CopyAuthIdentityFieldsW(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, WCHAR** pUser,
WCHAR** pDomain, WCHAR** pPassword)
{
BOOL success = FALSE;
char* UserA = NULL;
char* DomainA = NULL;
char* PasswordA = NULL;
WCHAR* UserW = NULL;
WCHAR* DomainW = NULL;
WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
if (!identity || !pUser || !pDomain || !pPassword)
return FALSE;
*pUser = *pDomain = *pPassword = NULL;
UINT32 identityFlags = sspi_GetAuthIdentityFlags((void*)identity);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (!sspi_GetAuthIdentityUserDomainA((void*)identity, &UserA, &UserLength, &DomainA,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordA((void*)identity, &PasswordA, &PasswordLength))
goto cleanup;
if (UserA && UserLength)
{
ConvertToUnicode(CP_UTF8, 0, UserA, UserLength, pUser, 0);
if (!(*pUser))
goto cleanup;
}
if (DomainA && DomainLength)
{
ConvertToUnicode(CP_UTF8, 0, DomainA, DomainLength, pDomain, 0);
if (!(*pDomain))
goto cleanup;
}
if (PasswordA && PasswordLength)
{
ConvertToUnicode(CP_UTF8, 0, PasswordA, PasswordLength, pPassword, 0);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
else
{
if (!sspi_GetAuthIdentityUserDomainW((void*)identity, &UserW, &UserLength, &DomainW,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordW((void*)identity, &PasswordW, &PasswordLength))
goto cleanup;
if (UserW && UserLength)
{
*pUser = _wcsdup(UserW);
if (!(*pUser))
goto cleanup;
}
if (DomainW && DomainLength)
{
*pDomain = _wcsdup(DomainW);
if (!(*pDomain))
goto cleanup;
}
if (PasswordW && PasswordLength)
{
*pPassword = _wcsdup(PasswordW);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
cleanup:
return success;
}
BOOL sspi_CopyAuthPackageListA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pPackageList)
{
UINT32 version;
UINT32 identityFlags;
char* PackageList = NULL;
char* PackageListA = NULL;
WCHAR* PackageListW = NULL;
UINT32 PackageListLength = 0;
UINT32 PackageListOffset = 0;
void* pAuthData = (void*)identity;
if (!pAuthData)
return FALSE;
version = sspi_GetAuthIdentityVersion(pAuthData);
identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
PackageListA = (char*)((SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData)->PackageList;
PackageListLength = ((SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData)->PackageListLength;
}
if (PackageListA && PackageListLength)
{
PackageList = _strdup(PackageListA);
}
}
else
{
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
PackageListW = (WCHAR*)((SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData)->PackageList;
PackageListLength = ((SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData)->PackageListLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
PackageListOffset = ((SEC_WINNT_AUTH_IDENTITY_EX2*)pAuthData)->PackageListOffset;
PackageListW = (WCHAR*)&((uint8_t*)pAuthData)[PackageListOffset];
PackageListLength = ((SEC_WINNT_AUTH_IDENTITY_EX2*)pAuthData)->PackageListLength / 2;
}
if (PackageListW && PackageListLength)
{
ConvertFromUnicode(CP_UTF8, 0, PackageListW, PackageListLength, &PackageList, 0, NULL,
NULL);
}
}
if (PackageList)
{
*pPackageList = PackageList;
return TRUE;
}
return FALSE;
}
int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
const SEC_WINNT_AUTH_IDENTITY* srcIdentity)
const SEC_WINNT_AUTH_IDENTITY_INFO* srcIdentity)
{
int status;
UINT32 identityFlags;
char* UserA = NULL;
char* DomainA = NULL;
char* PasswordA = NULL;
WCHAR* UserW = NULL;
WCHAR* DomainW = NULL;
WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
sspi_FreeAuthIdentity(identity);
identity->Flags = srcIdentity->Flags;
if (srcIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
identityFlags = sspi_GetAuthIdentityFlags((void*)srcIdentity);
identity->Flags = identityFlags;
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
status = sspi_SetAuthIdentity(identity, (char*)srcIdentity->User,
(char*)srcIdentity->Domain, (char*)srcIdentity->Password);
if (!sspi_GetAuthIdentityUserDomainA((void*)srcIdentity, &UserA, &UserLength, &DomainA,
&DomainLength))
{
return -1;
}
if (!sspi_GetAuthIdentityPasswordA((void*)srcIdentity, &PasswordA, &PasswordLength))
{
return -1;
}
status = sspi_SetAuthIdentity(identity, UserA, DomainA, PasswordA);
if (status <= 0)
return -1;
@ -452,8 +899,19 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
if (!sspi_GetAuthIdentityUserDomainW((void*)srcIdentity, &UserW, &UserLength, &DomainW,
&DomainLength))
{
return -1;
}
if (!sspi_GetAuthIdentityPasswordW((void*)srcIdentity, &PasswordW, &PasswordLength))
{
return -1;
}
/* login/password authentication */
identity->UserLength = srcIdentity->UserLength;
identity->UserLength = UserLength;
if (identity->UserLength > 0)
{
@ -462,11 +920,11 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
if (!identity->User)
return -1;
CopyMemory(identity->User, srcIdentity->User, identity->UserLength * sizeof(WCHAR));
CopyMemory(identity->User, UserW, identity->UserLength * sizeof(WCHAR));
identity->User[identity->UserLength] = 0;
}
identity->DomainLength = srcIdentity->DomainLength;
identity->DomainLength = DomainLength;
if (identity->DomainLength > 0)
{
@ -475,28 +933,27 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
if (!identity->Domain)
return -1;
CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength * sizeof(WCHAR));
CopyMemory(identity->Domain, DomainW, identity->DomainLength * sizeof(WCHAR));
identity->Domain[identity->DomainLength] = 0;
}
identity->PasswordLength = srcIdentity->PasswordLength;
identity->PasswordLength = PasswordLength;
if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
if (srcIdentity->Password)
if (PasswordW)
{
identity->Password = (UINT16*)calloc((identity->PasswordLength + 1), sizeof(WCHAR));
if (!identity->Password)
return -1;
CopyMemory(identity->Password, srcIdentity->Password,
identity->PasswordLength * sizeof(WCHAR));
CopyMemory(identity->Password, PasswordW, identity->PasswordLength * sizeof(WCHAR));
identity->Password[identity->PasswordLength] = 0;
}
identity->PasswordLength = srcIdentity->PasswordLength;
identity->PasswordLength = PasswordLength;
/* End of login/password authentication */
return 1;
}