libwinpr-sspi: improve SAM management
This commit is contained in:
parent
0736077e07
commit
4a5de37c00
@ -57,7 +57,6 @@ endif()
|
||||
# Compiler-specific flags
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fshort-wchar")
|
||||
CHECK_C_COMPILER_FLAG (-Wno-unused-result Wno-unused-result)
|
||||
if(Wno-unused-result)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result")
|
||||
|
@ -45,7 +45,7 @@
|
||||
#define MB_ERR_INVALID_CHARS 0x00000008
|
||||
|
||||
WINPR_API char* _strdup(const char* strSource);
|
||||
WINPR_API wchar_t* _wcsdup(const wchar_t* strSource);
|
||||
WINPR_API WCHAR* _wcsdup(const WCHAR* strSource);
|
||||
|
||||
WINPR_API LPSTR CharUpperA(LPSTR lpsz);
|
||||
WINPR_API LPWSTR CharUpperW(LPWSTR lpsz);
|
||||
|
@ -126,8 +126,6 @@ int credssp_ntlm_server_init(rdpCredssp* credssp)
|
||||
rdpSettings* settings = credssp->settings;
|
||||
instance = (freerdp*) settings->instance;
|
||||
|
||||
sspi_SetAuthIdentity(&(credssp->identity), "username", NULL, NULL);
|
||||
|
||||
sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length);
|
||||
CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length);
|
||||
|
||||
|
@ -41,9 +41,9 @@ char* _strdup(const char* strSource)
|
||||
return strDestination;
|
||||
}
|
||||
|
||||
wchar_t* _wcsdup(const wchar_t* strSource)
|
||||
WCHAR* _wcsdup(const WCHAR* strSource)
|
||||
{
|
||||
wchar_t* strDestination;
|
||||
WCHAR* strDestination;
|
||||
|
||||
if (strSource == NULL)
|
||||
return NULL;
|
||||
@ -56,7 +56,7 @@ wchar_t* _wcsdup(const wchar_t* strSource)
|
||||
if (strDestination != NULL)
|
||||
wcscpy(strDestination, strSource);
|
||||
#else
|
||||
strDestination = wcsdup(strSource);
|
||||
strDestination = (WCHAR*) wcsdup((wchar_t*) strSource);
|
||||
#endif
|
||||
|
||||
if (strDestination == NULL)
|
||||
|
@ -251,12 +251,22 @@ const SecPkgInfoA CREDSSP_SecPkgInfoA =
|
||||
"Microsoft CredSSP Security Provider" /* Comment */
|
||||
};
|
||||
|
||||
WCHAR CREDSSP_SecPkgInfoW_Name[] = { 'C','R','E','D','S','S','P','\0' };
|
||||
|
||||
WCHAR CREDSSP_SecPkgInfoW_Comment[] =
|
||||
{
|
||||
'M','i','c','r','o','s','o','f','t',' ',
|
||||
'C','r','e','d','S','S','P',' ',
|
||||
'S','e','c','u','r','i','t','y',' ',
|
||||
'P','r','o','v','i','d','e','r','\0'
|
||||
};
|
||||
|
||||
const SecPkgInfoW CREDSSP_SecPkgInfoW =
|
||||
{
|
||||
0x000110733, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0xFFFF, /* wRPCID */
|
||||
0x000090A8, /* cbMaxToken */
|
||||
L"CREDSSP", /* Name */
|
||||
L"Microsoft CredSSP Security Provider" /* Comment */
|
||||
CREDSSP_SecPkgInfoW_Name, /* Name */
|
||||
CREDSSP_SecPkgInfoW_Comment /* Comment */
|
||||
};
|
||||
|
@ -733,12 +733,21 @@ const SecPkgInfoA NTLM_SecPkgInfoA =
|
||||
"NTLM Security Package" /* Comment */
|
||||
};
|
||||
|
||||
WCHAR NTLM_SecPkgInfoW_Name[] = { 'N','T','L','M','\0' };
|
||||
|
||||
WCHAR NTLM_SecPkgInfoW_Comment[] =
|
||||
{
|
||||
'N','T','L','M',' ',
|
||||
'S','e','c','u','r','i','t','y',' ',
|
||||
'P','a','c','k','a','g','e','\0'
|
||||
};
|
||||
|
||||
const SecPkgInfoW NTLM_SecPkgInfoW =
|
||||
{
|
||||
0x00082B37, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x000A, /* wRPCID */
|
||||
0x00000B48, /* cbMaxToken */
|
||||
L"NTLM", /* Name */
|
||||
L"NTLM Security Package" /* Comment */
|
||||
NTLM_SecPkgInfoW_Name, /* Name */
|
||||
NTLM_SecPkgInfoW_Comment /* Comment */
|
||||
};
|
||||
|
@ -161,112 +161,6 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
|
||||
}
|
||||
}
|
||||
|
||||
static void ascii_hex_string_to_binary(char* str, unsigned char* hex)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
||||
CharUpperA(str);
|
||||
|
||||
length = strlen(str);
|
||||
|
||||
for (i = 0; i < length / 2; i++)
|
||||
{
|
||||
hex[i] = 0;
|
||||
|
||||
if ((str[i * 2] >= '0') && (str[i * 2] <= '9'))
|
||||
hex[i] |= (str[i * 2] - '0') << 4;
|
||||
|
||||
if ((str[i * 2] >= 'A') && (str[i * 2] <= 'F'))
|
||||
hex[i] |= (str[i * 2] - 'A' + 10) << 4;
|
||||
|
||||
if ((str[i * 2 + 1] >= '0') && (str[i * 2 + 1] <= '9'))
|
||||
hex[i] |= (str[i * 2 + 1] - '0');
|
||||
|
||||
if ((str[i * 2 + 1] >= 'A') && (str[i * 2 + 1] <= 'F'))
|
||||
hex[i] |= (str[i * 2 + 1] - 'A' + 10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* username // password
|
||||
* username:661e58eb6743798326f388fc5edb0b3a
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
{
|
||||
FILE* fp;
|
||||
char* data;
|
||||
char* line;
|
||||
int length;
|
||||
char* db_user;
|
||||
char* db_hash;
|
||||
UINT16* User;
|
||||
UINT32 UserLength;
|
||||
long int file_size;
|
||||
BYTE db_hash_bin[16];
|
||||
|
||||
/* Fetch NTLMv2 hash from database */
|
||||
|
||||
fp = fopen("/etc/winpr/SAM.txt", "r");
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
file_size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (file_size < 1)
|
||||
return;
|
||||
|
||||
data = (char*) malloc(file_size + 2);
|
||||
|
||||
if (fread(data, file_size, 1, fp) != 1)
|
||||
{
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
data[file_size] = '\n';
|
||||
data[file_size + 1] = '\0';
|
||||
line = strtok(data, "\n");
|
||||
|
||||
while (line != NULL)
|
||||
{
|
||||
length = strlen(line);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
length = strcspn(line, ":");
|
||||
line[length] = '\0';
|
||||
|
||||
db_user = line;
|
||||
db_hash = &line[length + 1];
|
||||
|
||||
UserLength = strlen(db_user) * 2;
|
||||
User = (UINT16*) malloc(UserLength);
|
||||
MultiByteToWideChar(CP_ACP, 0, db_user, strlen(db_user),
|
||||
(LPWSTR) User, UserLength / 2);
|
||||
|
||||
if (UserLength == context->identity.UserLength)
|
||||
{
|
||||
if (memcmp(User, context->identity.User, UserLength) == 0)
|
||||
{
|
||||
ascii_hex_string_to_binary(db_hash, db_hash_bin);
|
||||
CopyMemory(hash, db_hash_bin, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line = strtok(NULL, "\n");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
free(data);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
{
|
||||
WINPR_SAM* sam;
|
||||
@ -274,32 +168,20 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
|
||||
sam = SamOpen(1);
|
||||
|
||||
winpr_HexDump(context->identity.User, context->identity.UserLength);
|
||||
|
||||
entry = SamLookupUserW(sam,
|
||||
(LPWSTR) context->identity.User, context->identity.UserLength,
|
||||
(LPWSTR) context->identity.Domain, context->identity.DomainLength);
|
||||
|
||||
if (entry != NULL)
|
||||
{
|
||||
winpr_HexDump(entry->NtHash, 16);
|
||||
CopyMemory(hash, entry->NtHash, 16);
|
||||
winpr_HexDump(hash, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("User could not be found!\n");
|
||||
}
|
||||
|
||||
SamFreeEntry(sam, entry);
|
||||
|
||||
SamClose(sam);
|
||||
|
||||
printf("SamClose returned\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
{
|
||||
if (context->identity.PasswordLength > 0)
|
||||
|
@ -819,6 +819,17 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
#endif
|
||||
}
|
||||
|
||||
context->identity.User = (UINT16*) malloc(UserNameLen);
|
||||
CopyMemory(context->identity.User, UserNameBuffer, UserNameLen);
|
||||
context->identity.UserLength = UserNameLen;
|
||||
|
||||
if (DomainNameLen > 0)
|
||||
{
|
||||
context->identity.Domain = (UINT16*) malloc(DomainNameLen);
|
||||
CopyMemory(context->identity.Domain, DomainNameBuffer, DomainNameLen);
|
||||
context->identity.DomainLength = DomainNameLen;
|
||||
}
|
||||
|
||||
/* LmChallengeResponse */
|
||||
|
||||
if (context->LmCompatibilityLevel < 2)
|
||||
@ -1093,13 +1104,21 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
}
|
||||
|
||||
/* LmChallengeResponse */
|
||||
StreamZero(s, LmChallengeResponseLen);
|
||||
|
||||
if (context->LmCompatibilityLevel < 2)
|
||||
{
|
||||
StreamWrite(s, context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset);
|
||||
winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen);
|
||||
printf("\n");
|
||||
printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset);
|
||||
winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
StreamZero(s, LmChallengeResponseLen);
|
||||
}
|
||||
|
||||
/* NtChallengeResponse */
|
||||
StreamWrite(s, context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen);
|
||||
|
@ -26,26 +26,6 @@
|
||||
|
||||
char* NEGOTIATE_PACKAGE_NAME = "Negotiate";
|
||||
|
||||
const SecPkgInfoA NEGOTIATE_SecPkgInfoA =
|
||||
{
|
||||
0x00083BB3, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x0009, /* wRPCID */
|
||||
0x00002FE0, /* cbMaxToken */
|
||||
"Negotiate", /* Name */
|
||||
"Microsoft Package Negotiator" /* Comment */
|
||||
};
|
||||
|
||||
const SecPkgInfoW NEGOTIATE_SecPkgInfoW =
|
||||
{
|
||||
0x00083BB3, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x0009, /* wRPCID */
|
||||
0x00002FE0, /* cbMaxToken */
|
||||
L"Negotiate", /* Name */
|
||||
L"Microsoft Package Negotiator" /* Comment */
|
||||
};
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
|
||||
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
|
||||
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
|
||||
@ -277,3 +257,32 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
|
||||
negotiate_DecryptMessage, /* DecryptMessage */
|
||||
NULL, /* SetContextAttributes */
|
||||
};
|
||||
|
||||
const SecPkgInfoA NEGOTIATE_SecPkgInfoA =
|
||||
{
|
||||
0x00083BB3, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x0009, /* wRPCID */
|
||||
0x00002FE0, /* cbMaxToken */
|
||||
"Negotiate", /* Name */
|
||||
"Microsoft Package Negotiator" /* Comment */
|
||||
};
|
||||
|
||||
WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N','e','g','o','t','i','a','t','e','\0' };
|
||||
|
||||
WCHAR NEGOTIATE_SecPkgInfoW_Comment[] =
|
||||
{
|
||||
'M','i','c','r','o','s','o','f','t',' ',
|
||||
'P','a','c','k','a','g','e',' ',
|
||||
'N','e','g','o','t','i','a','t','o','r','\0'
|
||||
};
|
||||
|
||||
const SecPkgInfoW NEGOTIATE_SecPkgInfoW =
|
||||
{
|
||||
0x00083BB3, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x0009, /* wRPCID */
|
||||
0x00002FE0, /* cbMaxToken */
|
||||
NEGOTIATE_SecPkgInfoW_Name, /* Name */
|
||||
NEGOTIATE_SecPkgInfoW_Comment /* Comment */
|
||||
};
|
||||
|
@ -251,13 +251,21 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA =
|
||||
"Schannel Security Package" /* Comment */
|
||||
};
|
||||
|
||||
WCHAR SCHANNEL_SecPkgInfoW_Name[] = { 'S','c','h','a','n','n','e','l','\0' };
|
||||
|
||||
WCHAR SCHANNEL_SecPkgInfoW_Comment[] =
|
||||
{
|
||||
'S','c','h','a','n','n','e','l',' ',
|
||||
'S','e','c','u','r','i','t','y',' ',
|
||||
'P','a','c','k','a','g','e','\0'
|
||||
};
|
||||
|
||||
const SecPkgInfoW SCHANNEL_SecPkgInfoW =
|
||||
{
|
||||
0x000107B3, /* fCapabilities */
|
||||
1, /* wVersion */
|
||||
0x000E, /* wRPCID */
|
||||
0x00006000, /* cbMaxToken */
|
||||
L"Schannel", /* Name */
|
||||
L"Schannel Security Package" /* Comment */
|
||||
SCHANNEL_SecPkgInfoW_Name, /* Name */
|
||||
SCHANNEL_SecPkgInfoW_Comment /* Comment */
|
||||
};
|
||||
|
||||
|
@ -73,10 +73,13 @@ const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] =
|
||||
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA }
|
||||
};
|
||||
|
||||
WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' };
|
||||
WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' };
|
||||
|
||||
const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] =
|
||||
{
|
||||
{ L"NTLM", &NTLM_SecurityFunctionTableW },
|
||||
{ L"CREDSSP", &CREDSSP_SecurityFunctionTableW }
|
||||
{ NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
|
||||
{ CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -273,10 +276,18 @@ void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* d
|
||||
{
|
||||
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||||
|
||||
identity->UserLength = strlen(user) * 2;
|
||||
identity->User = (UINT16*) malloc(identity->UserLength + 2);
|
||||
MultiByteToWideChar(CP_ACP, 0, user, strlen(user),
|
||||
(LPWSTR) identity->User, identity->UserLength / 2);
|
||||
if (user)
|
||||
{
|
||||
identity->UserLength = strlen(user) * 2;
|
||||
identity->User = (UINT16*) malloc(identity->UserLength + 2);
|
||||
MultiByteToWideChar(CP_ACP, 0, user, strlen(user),
|
||||
(LPWSTR) identity->User, identity->UserLength / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
identity->User = (UINT16*) NULL;
|
||||
identity->UserLength = 0;
|
||||
}
|
||||
|
||||
if (domain)
|
||||
{
|
||||
@ -513,7 +524,7 @@ SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, P
|
||||
|
||||
for (index = 0; index < (int) cPackages; index++)
|
||||
{
|
||||
if (wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
|
||||
if (lstrcmpW(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
|
||||
{
|
||||
size = sizeof(SecPkgInfoW);
|
||||
pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
|
||||
|
@ -48,6 +48,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
int index = 1;
|
||||
BYTE NtHash[16];
|
||||
BOOL sam_entry = 0;
|
||||
char* User = NULL;
|
||||
UINT32 UserLength;
|
||||
char* Domain = NULL;
|
||||
@ -99,6 +100,10 @@ int main(int argc, char* argv[])
|
||||
printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>]\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (strcmp("-s", argv[index]) == 0)
|
||||
{
|
||||
sam_entry = 1;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
@ -115,10 +120,27 @@ int main(int argc, char* argv[])
|
||||
|
||||
NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash);
|
||||
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
if (sam_entry)
|
||||
{
|
||||
printf("%s:", User);
|
||||
|
||||
printf("\n");
|
||||
if (DomainLength > 0)
|
||||
printf("%s:", Domain);
|
||||
else
|
||||
printf(":");
|
||||
|
||||
printf(":");
|
||||
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -149,6 +149,8 @@ WINPR_SAM_ENTRY* SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry)
|
||||
HexStrToBin(p[3], (BYTE*) entry->NtHash, 16);
|
||||
}
|
||||
|
||||
printf("SamReadEntry: %s\n", entry->User);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -235,11 +237,13 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength,
|
||||
MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2,
|
||||
(LPWSTR) EntryUser, EntryUserLength / 2);
|
||||
|
||||
if (lstrcmpW(User, EntryUser) == 0)
|
||||
if (UserLength == EntryUserLength)
|
||||
{
|
||||
printf("Found user\n");
|
||||
found = 1;
|
||||
break;
|
||||
if (memcmp(User, EntryUser, UserLength) == 0)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user