libwinpr-sspi: improve SAM management

This commit is contained in:
Marc-André Moreau 2012-06-03 19:59:35 -04:00
parent 0736077e07
commit 4a5de37c00
13 changed files with 141 additions and 170 deletions

View File

@ -57,7 +57,6 @@ endif()
# Compiler-specific flags # Compiler-specific flags
if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 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) CHECK_C_COMPILER_FLAG (-Wno-unused-result Wno-unused-result)
if(Wno-unused-result) if(Wno-unused-result)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result")

View File

@ -45,7 +45,7 @@
#define MB_ERR_INVALID_CHARS 0x00000008 #define MB_ERR_INVALID_CHARS 0x00000008
WINPR_API char* _strdup(const char* strSource); 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 LPSTR CharUpperA(LPSTR lpsz);
WINPR_API LPWSTR CharUpperW(LPWSTR lpsz); WINPR_API LPWSTR CharUpperW(LPWSTR lpsz);

View File

@ -126,8 +126,6 @@ int credssp_ntlm_server_init(rdpCredssp* credssp)
rdpSettings* settings = credssp->settings; rdpSettings* settings = credssp->settings;
instance = (freerdp*) settings->instance; instance = (freerdp*) settings->instance;
sspi_SetAuthIdentity(&(credssp->identity), "username", NULL, NULL);
sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length);
CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length);

View File

@ -41,9 +41,9 @@ char* _strdup(const char* strSource)
return strDestination; return strDestination;
} }
wchar_t* _wcsdup(const wchar_t* strSource) WCHAR* _wcsdup(const WCHAR* strSource)
{ {
wchar_t* strDestination; WCHAR* strDestination;
if (strSource == NULL) if (strSource == NULL)
return NULL; return NULL;
@ -56,7 +56,7 @@ wchar_t* _wcsdup(const wchar_t* strSource)
if (strDestination != NULL) if (strDestination != NULL)
wcscpy(strDestination, strSource); wcscpy(strDestination, strSource);
#else #else
strDestination = wcsdup(strSource); strDestination = (WCHAR*) wcsdup((wchar_t*) strSource);
#endif #endif
if (strDestination == NULL) if (strDestination == NULL)

View File

@ -251,12 +251,22 @@ const SecPkgInfoA CREDSSP_SecPkgInfoA =
"Microsoft CredSSP Security Provider" /* Comment */ "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 = const SecPkgInfoW CREDSSP_SecPkgInfoW =
{ {
0x000110733, /* fCapabilities */ 0x000110733, /* fCapabilities */
1, /* wVersion */ 1, /* wVersion */
0xFFFF, /* wRPCID */ 0xFFFF, /* wRPCID */
0x000090A8, /* cbMaxToken */ 0x000090A8, /* cbMaxToken */
L"CREDSSP", /* Name */ CREDSSP_SecPkgInfoW_Name, /* Name */
L"Microsoft CredSSP Security Provider" /* Comment */ CREDSSP_SecPkgInfoW_Comment /* Comment */
}; };

View File

@ -733,12 +733,21 @@ const SecPkgInfoA NTLM_SecPkgInfoA =
"NTLM Security Package" /* Comment */ "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 = const SecPkgInfoW NTLM_SecPkgInfoW =
{ {
0x00082B37, /* fCapabilities */ 0x00082B37, /* fCapabilities */
1, /* wVersion */ 1, /* wVersion */
0x000A, /* wRPCID */ 0x000A, /* wRPCID */
0x00000B48, /* cbMaxToken */ 0x00000B48, /* cbMaxToken */
L"NTLM", /* Name */ NTLM_SecPkgInfoW_Name, /* Name */
L"NTLM Security Package" /* Comment */ NTLM_SecPkgInfoW_Comment /* Comment */
}; };

View File

@ -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) void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{ {
WINPR_SAM* sam; WINPR_SAM* sam;
@ -274,32 +168,20 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
sam = SamOpen(1); sam = SamOpen(1);
winpr_HexDump(context->identity.User, context->identity.UserLength);
entry = SamLookupUserW(sam, entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength, (LPWSTR) context->identity.User, context->identity.UserLength,
(LPWSTR) context->identity.Domain, context->identity.DomainLength); (LPWSTR) context->identity.Domain, context->identity.DomainLength);
if (entry != NULL) if (entry != NULL)
{ {
winpr_HexDump(entry->NtHash, 16);
CopyMemory(hash, entry->NtHash, 16); CopyMemory(hash, entry->NtHash, 16);
winpr_HexDump(hash, 16);
}
else
{
printf("User could not be found!\n");
} }
SamFreeEntry(sam, entry); SamFreeEntry(sam, entry);
SamClose(sam); SamClose(sam);
printf("SamClose returned\n");
} }
#endif
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{ {
if (context->identity.PasswordLength > 0) if (context->identity.PasswordLength > 0)

View File

@ -819,6 +819,17 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
#endif #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 */ /* LmChallengeResponse */
if (context->LmCompatibilityLevel < 2) if (context->LmCompatibilityLevel < 2)
@ -1093,13 +1104,21 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
} }
/* LmChallengeResponse */ /* LmChallengeResponse */
StreamZero(s, LmChallengeResponseLen);
if (context->LmCompatibilityLevel < 2)
{
StreamWrite(s, context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen);
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset);
winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen);
printf("\n"); printf("\n");
#endif #endif
}
else
{
StreamZero(s, LmChallengeResponseLen);
}
/* NtChallengeResponse */ /* NtChallengeResponse */
StreamWrite(s, context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen); StreamWrite(s, context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen);

View File

@ -26,26 +26,6 @@
char* NEGOTIATE_PACKAGE_NAME = "Negotiate"; 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, SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
@ -277,3 +257,32 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
negotiate_DecryptMessage, /* DecryptMessage */ negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */ 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 */
};

View File

@ -251,13 +251,21 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA =
"Schannel Security Package" /* Comment */ "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 = const SecPkgInfoW SCHANNEL_SecPkgInfoW =
{ {
0x000107B3, /* fCapabilities */ 0x000107B3, /* fCapabilities */
1, /* wVersion */ 1, /* wVersion */
0x000E, /* wRPCID */ 0x000E, /* wRPCID */
0x00006000, /* cbMaxToken */ 0x00006000, /* cbMaxToken */
L"Schannel", /* Name */ SCHANNEL_SecPkgInfoW_Name, /* Name */
L"Schannel Security Package" /* Comment */ SCHANNEL_SecPkgInfoW_Comment /* Comment */
}; };

View File

@ -73,10 +73,13 @@ const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] =
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA } { "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[] = const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] =
{ {
{ L"NTLM", &NTLM_SecurityFunctionTableW }, { NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
{ L"CREDSSP", &CREDSSP_SecurityFunctionTableW } { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }
}; };
#endif #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->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
identity->UserLength = strlen(user) * 2; if (user)
identity->User = (UINT16*) malloc(identity->UserLength + 2); {
MultiByteToWideChar(CP_ACP, 0, user, strlen(user), identity->UserLength = strlen(user) * 2;
(LPWSTR) identity->User, identity->UserLength / 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) if (domain)
{ {
@ -513,7 +524,7 @@ SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, P
for (index = 0; index < (int) cPackages; index++) 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); size = sizeof(SecPkgInfoW);
pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size); pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);

View File

@ -48,6 +48,7 @@ int main(int argc, char* argv[])
{ {
int index = 1; int index = 1;
BYTE NtHash[16]; BYTE NtHash[16];
BOOL sam_entry = 0;
char* User = NULL; char* User = NULL;
UINT32 UserLength; UINT32 UserLength;
char* Domain = NULL; char* Domain = NULL;
@ -99,6 +100,10 @@ int main(int argc, char* argv[])
printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>]\n"); printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>]\n");
exit(1); exit(1);
} }
else if (strcmp("-s", argv[index]) == 0)
{
sam_entry = 1;
}
index++; index++;
} }
@ -115,10 +120,27 @@ int main(int argc, char* argv[])
NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash); NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash);
for (index = 0; index < 16; index++) if (sam_entry)
printf("%02x", NtHash[index]); {
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; return 0;
} }

View File

@ -149,6 +149,8 @@ WINPR_SAM_ENTRY* SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry)
HexStrToBin(p[3], (BYTE*) entry->NtHash, 16); HexStrToBin(p[3], (BYTE*) entry->NtHash, 16);
} }
printf("SamReadEntry: %s\n", entry->User);
return entry; 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, MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2,
(LPWSTR) EntryUser, EntryUserLength / 2); (LPWSTR) EntryUser, EntryUserLength / 2);
if (lstrcmpW(User, EntryUser) == 0) if (UserLength == EntryUserLength)
{ {
printf("Found user\n"); if (memcmp(User, EntryUser, UserLength) == 0)
found = 1; {
break; found = 1;
break;
}
} }
} }
} }