#define FreeRDP_AuthenticationLevel 1100
#define FreeRDP_AllowedTlsCiphers 1101
#define FreeRDP_VmConnectMode 1102
+#define FreeRDP_NtlmSamFile 1103
#define FreeRDP_MstscCookieMode 1152
#define FreeRDP_CookieMaxLength 1153
#define FreeRDP_PreconnectionId 1154
ALIGN64 BOOL AuthenticationLevel; /* 1100 */
ALIGN64 char* AllowedTlsCiphers; /* 1101 */
ALIGN64 BOOL VmConnectMode; /* 1102 */
- UINT64 padding1152[1152 - 1103]; /* 1103 */
+ ALIGN64 char* NtlmSamFile; /* 1103 */
+ UINT64 padding1152[1152 - 1104]; /* 1104 */
/* Connection Cookie */
ALIGN64 BOOL MstscCookieMode; /* 1152 */
case FreeRDP_AuthenticationServiceClass:
return settings->AuthenticationServiceClass;
+ case FreeRDP_AllowedTlsCiphers:
+ return settings->AllowedTlsCiphers;
+
+ case FreeRDP_NtlmSamFile:
+ return settings->NtlmSamFile;
+
case FreeRDP_PreconnectionBlob:
return settings->PreconnectionBlob;
tmp = &settings->AuthenticationServiceClass;
break;
+ case FreeRDP_AllowedTlsCiphers:
+ tmp = &settings->AllowedTlsCiphers;
+ break;
+
+ case FreeRDP_NtlmSamFile:
+ tmp = &settings->NtlmSamFile;
+ break;
+
case FreeRDP_PreconnectionBlob:
tmp = &settings->PreconnectionBlob;
break;
if (PromptPassword && settings->Username && strlen(settings->Username))
{
- sam = SamOpen(TRUE);
+ sam = SamOpen(NULL, TRUE);
if (sam)
{
return -1;
nla->status = nla->table->AcceptSecurityContext(&nla->credentials,
- nla-> haveContext? &nla->context: NULL,
- &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
- &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
+ nla->haveContext? &nla->context: NULL,
+ &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
+ &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
WLog_VRB(TAG, "AcceptSecurityContext status %s [%08X]",
GetSecurityStatusString(nla->status), nla->status);
if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
{
+ if (nla->SamFile)
+ {
+ nla->table->SetContextAttributes(&nla->context,
+ SECPKG_ATTR_AUTH_NTLM_SAM_FILE, nla->SamFile, strlen(nla->SamFile) + 1);
+ }
+
if (nla->table->CompleteAuthToken)
{
SECURITY_STATUS status;
status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
+
if (status != SEC_E_OK)
{
WLog_WARN(TAG, "CompleteAuthToken status %s [%08X]",
return -1;
}
}
+
if (nla->status == SEC_I_COMPLETE_NEEDED)
nla->status = SEC_E_OK;
else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
{
-
rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla));
if (!nla)
return NULL;
nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
+
if (!nla->identity)
{
- free (nla);
+ free(nla);
return NULL;
}
nla->recvSeqNum = 0;
nla->version = 3;
+ if (settings->NtlmSamFile)
+ nla->SamFile = _strdup(settings->NtlmSamFile);
+
ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
}
}
+ if (nla->SamFile)
+ {
+ free(nla->SamFile);
+ nla->SamFile = NULL;
+ }
+
sspi_SecBufferFree(&nla->PublicKey);
sspi_SecBufferFree(&nla->tsCredentials);
freerdp* instance;
CtxtHandle context;
LPTSTR SspiModule;
+ char* SamFile;
rdpSettings* settings;
rdpTransport* transport;
UINT32 cbMaxToken;
CHECKED_STRDUP(RemoteAssistanceRCTicket); /* 1028 */
CHECKED_STRDUP(AuthenticationServiceClass); /* 1098 */
CHECKED_STRDUP(AllowedTlsCiphers); /* 1101 */
+ CHECKED_STRDUP(NtlmSamFile); /* 1103 */
CHECKED_STRDUP(PreconnectionBlob); /* 1155 */
CHECKED_STRDUP(KerberosKdc); /* 1344 */
CHECKED_STRDUP(KerberosRealm); /* 1345 */
free(settings->ClientAddress);
free(settings->ClientDir);
free(settings->AllowedTlsCiphers);
+ free(settings->NtlmSamFile);
free(settings->CertificateFile);
free(settings->PrivateKeyFile);
free(settings->ConnectionFile);
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
+ { "sam-file", COMMAND_LINE_VALUE_REQUIRED, "<file>", NULL, NULL, -1, NULL, "NTLM SAM file for NLA authentication" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "Print help" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
{
settings->ExtSecurity = arg->Value ? TRUE : FALSE;
}
+ CommandLineSwitchCase(arg, "sam-file")
+ {
+ freerdp_set_param_string(settings, FreeRDP_NtlmSamFile, arg->Value);
+ }
CommandLineSwitchDefault(arg)
{
FILE* fp;
char* line;
char* buffer;
- BOOL read_only;
+ BOOL readOnly;
};
typedef struct winpr_sam WINPR_SAM;
WINPR_API void SamResetEntry(WINPR_SAM_ENTRY* entry);
WINPR_API void SamFreeEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry);
-WINPR_API WINPR_SAM* SamOpen(BOOL read_only);
+WINPR_API WINPR_SAM* SamOpen(const char* filename, BOOL readOnly);
WINPR_API void SamClose(WINPR_SAM* sam);
#ifdef __cplusplus
#define SECPKG_ATTR_AUTH_IDENTITY 1001
#define SECPKG_ATTR_AUTH_PASSWORD 1002
#define SECPKG_ATTR_AUTH_NTLM_HASH 1003
+#define SECPKG_ATTR_AUTH_NTLM_SAM_FILE 1004
#define SECPKG_ATTR_AUTH_NTLM_MESSAGE 1100
#define SECPKG_ATTR_AUTH_NTLM_TIMESTAMP 1101
-#define SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE 1102
-#define SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE 1103
+#define SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE 1102
+#define SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE 1103
#define SECPKG_ATTR_AUTH_NTLM_NTPROOF_VALUE 1104
#define SECPKG_ATTR_AUTH_NTLM_RANDKEY 1105
-#define SECPKG_ATTR_AUTH_NTLM_MIC 1106
+#define SECPKG_ATTR_AUTH_NTLM_MIC 1106
#define SECPKG_ATTR_AUTH_NTLM_MIC_VALUE 1107
return SEC_E_OK;
}
+ else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_SAM_FILE)
+ {
+ const char* filename = (char*) pBuffer;
+
+ free(context->SamFile);
+ context->SamFile = filename ? _strdup(filename) : NULL;
+
+ return SEC_E_OK;
+ }
else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MESSAGE)
{
SecPkgContext_AuthNtlmMessage* AuthNtlmMessage = (SecPkgContext_AuthNtlmMessage*) pBuffer;
NTLM_STATE state;
int SendSeqNum;
int RecvSeqNum;
+ char* SamFile;
BYTE NtlmHash[16];
BYTE NtlmV2Hash[16];
BYTE MachineID[32];
WINPR_SAM_ENTRY* entry;
SSPI_CREDENTIALS* credentials = context->credentials;
- sam = SamOpen(TRUE);
+ sam = SamOpen(context->SamFile, TRUE);
if (!sam)
return -1;
#include <winpr/print.h>
#include "../log.h"
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#define TAG WINPR_TAG("utils")
-WINPR_SAM* SamOpen(BOOL read_only)
+WINPR_SAM* SamOpen(const char* filename, BOOL readOnly)
{
FILE* fp = NULL;
WINPR_SAM* sam = NULL;
- if (read_only)
+ if (!filename)
+ filename = WINPR_SAM_FILE;
+
+ if (readOnly)
{
- fp = fopen(WINPR_SAM_FILE, "r");
+ fp = fopen(filename, "r");
}
else
{
- fp = fopen(WINPR_SAM_FILE, "r+");
+ fp = fopen(filename, "r+");
if (!fp)
- fp = fopen(WINPR_SAM_FILE, "w+");
+ fp = fopen(filename, "w+");
}
if (fp)
{
sam = (WINPR_SAM*) malloc(sizeof(WINPR_SAM));
+
if (!sam)
{
fclose(fp);
return NULL;
}
- sam->read_only = read_only;
+
+ sam->readOnly = readOnly;
sam->fp = fp;
}
else
+ {
WLog_DBG(TAG, "Could not open SAM file!");
+ }
return sam;
}
static BOOL SamLookupStart(WINPR_SAM* sam)
{
- size_t read_size;
- long int file_size;
+ size_t readSize;
+ long int fileSize;
+
fseek(sam->fp, 0, SEEK_END);
- file_size = ftell(sam->fp);
+ fileSize = ftell(sam->fp);
fseek(sam->fp, 0, SEEK_SET);
- if (file_size < 1)
+ if (fileSize < 1)
return FALSE;
- sam->buffer = (char*) malloc(file_size + 2);
+ sam->buffer = (char*) malloc(fileSize + 2);
+
if (!sam->buffer)
return FALSE;
- read_size = fread(sam->buffer, file_size, 1, sam->fp);
+ readSize = fread(sam->buffer, fileSize, 1, sam->fp);
- if (!read_size)
+ if (!readSize)
{
if (!ferror(sam->fp))
- read_size = file_size;
+ readSize = fileSize;
}
- if (read_size < 1)
+ if (readSize < 1)
{
free(sam->buffer);
sam->buffer = NULL;
return FALSE;
}
- sam->buffer[file_size] = '\n';
- sam->buffer[file_size + 1] = '\0';
+ sam->buffer[fileSize] = '\n';
+ sam->buffer[fileSize + 1] = '\0';
sam->line = strtok(sam->buffer, "\n");
+
return TRUE;
}
free(entry->Domain);
entry->Domain = NULL;
}
+
ZeroMemory(entry->LmHash, sizeof(entry->LmHash));
ZeroMemory(entry->NtHash, sizeof(entry->NtHash));
}
-
WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength)
{
int length;
BOOL found = FALSE;
WINPR_SAM_ENTRY* entry;
+
entry = (WINPR_SAM_ENTRY*) calloc(1, sizeof(WINPR_SAM_ENTRY));
+
if (!entry)
return NULL;