Add Negotiate SSPI authentication module filtering
This commit is contained in:
parent
f620a31d57
commit
27a865af74
@ -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;
|
||||
|
@ -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" },
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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" },
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user