static void smb_display_status_1( PCSTR pszId, OM_uint32 code, int type ) { OM_uint32 min_stat; gss_buffer_desc msg; OM_uint32 msg_ctx; if ( code == 0 ) { return; } msg_ctx = 0; while (1) { (void) gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, &msg_ctx, &msg); switch(code) { #ifdef WIN32 case SEC_E_OK: case SEC_I_CONTINUE_NEEDED: #else case GSS_S_COMPLETE: case GSS_S_CONTINUE_NEEDED: #endif LWIO_LOG_VERBOSE("GSS-API error calling %s: %d (%s)\n", pszId, code, LWIO_SAFE_LOG_STRING((char *)msg.value)); break; default: LWIO_LOG_ERROR("GSS-API error calling %s: %d (%s)\n", pszId, code, LWIO_SAFE_LOG_STRING((char *)msg.value)); } (void) gss_release_buffer(&min_stat, &msg); if (!msg_ctx) break; } }
static VOID SrvLogEchoState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PECHO_REQUEST_HEADER pEchoHeader = NULL; // Do not Free PBYTE pEchoBlob = NULL; // Do Not Free PSTR pszHexString = NULL; ULONG ulLen = 0; va_list msgList; va_start(msgList, ulLine); pEchoHeader = va_arg(msgList, PECHO_REQUEST_HEADER); pEchoBlob = va_arg(msgList, PBYTE); if (pEchoHeader) { if (pEchoHeader->byteCount) { ntStatus = SrvGetHexDump( pEchoBlob, pEchoHeader->byteCount, SrvLogContextGetMaxLogLength(pLogContext), &pszHexString, &ulLen); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Delete directory state: EchoCount(%u),EchoBlob[%u/%u bytes](%s)", pEchoHeader->echoCount, ulLen, pEchoHeader->byteCount, LWIO_SAFE_LOG_STRING(pszHexString)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszHexString); return; }
static VOID SrvLogOpenState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL; PSTR pszPath = NULL; va_list msgList; va_start(msgList, ulLine); pOpenState = va_arg(msgList, PSRV_OPEN_STATE_SMB_V1); if (pOpenState) { ntStatus = SrvUnicodeStringToMbs( &pOpenState->pFilename->Name, &pszPath); BAIL_ON_NT_STATUS(ntStatus); LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Open state: " "alloc-size(%u),creation-time(0x%x),desired-access(0x%x)," "file-attrs(0x%x),flags(0x%x),open-function(%u)," "search-attrs(0x%x),path(%s)", pOpenState->pRequestHeader->ulAllocationSize, pOpenState->pRequestHeader->ulCreationTime, pOpenState->pRequestHeader->usDesiredAccess, pOpenState->pRequestHeader->usFileAttributes, pOpenState->pRequestHeader->usFlags, pOpenState->pRequestHeader->usOpenFunction, pOpenState->pRequestHeader->usSearchAttributes, LWIO_SAFE_LOG_STRING(pszPath)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszPath); return; }
VOID SrvLogRequest_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; PSTR pszBuffer = NULL; ULONG ulLen = 0; va_list msgList; va_start(msgList, ulLine); pExecContext = va_arg(msgList, PSRV_EXEC_CONTEXT); if (pExecContext) { ntStatus = SrvGetHexDump( (PBYTE)pExecContext->pSmbRequest->pSMBHeader, pExecContext->pSmbRequest->bufferUsed - sizeof(NETBIOS_HEADER), SrvLogContextGetMaxLogLength(pLogContext), &pszBuffer, &ulLen); BAIL_ON_NT_STATUS(ntStatus); LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "SMB Request:[%u/%u bytes][%s]", ulLen, pExecContext->pSmbRequest->bufferUsed - sizeof(NETBIOS_HEADER), LWIO_SAFE_LOG_STRING(pszBuffer)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszBuffer); }
static VOID SrvLogDeleteState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_DELETE_STATE_SMB_V1 pDeleteState = NULL; PSTR pszSearchPattern = NULL; va_list msgList; va_start(msgList, ulLine); pDeleteState = va_arg(msgList, PSRV_DELETE_STATE_SMB_V1); if (pDeleteState) { if (pDeleteState->pwszSearchPattern) { ntStatus = SrvWc16sToMbs(pDeleteState->pwszSearchPattern, &pszSearchPattern); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Delete directory state: SearchAttrs(0x%x),UseLongFilenames(%s),SearchPattern(%s)", pDeleteState->pRequestHeader->usSearchAttributes, pDeleteState->bUseLongFilenames ? "TRUE" : "FALSE", LWIO_SAFE_LOG_STRING(pszSearchPattern)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszSearchPattern); return; }
static VOID SrvLogCheckDirState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState = NULL; PSTR pszPath = NULL; va_list msgList; va_start(msgList, ulLine); pCheckdirState = va_arg(msgList, PSRV_CHECKDIR_STATE_SMB_V1); if (pCheckdirState) { if (pCheckdirState->pwszPathFragment) { ntStatus = SrvWc16sToMbs(pCheckdirState->pwszPathFragment, &pszPath); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "lwio", pszFunction, pszFile, ulLine, "Check directory state: Path(%s)", LWIO_SAFE_LOG_STRING(pszPath)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszPath); return; }
DWORD SMBKrb5SetDefaultCachePath( PCSTR pszCachePath, PSTR* ppszOrigCachePath ) { DWORD dwError = 0; DWORD dwMajorStatus = 0; DWORD dwMinorStatus = 0; PSTR pszOrigCachePath = NULL; // Set the default for gss dwMajorStatus = gss_krb5_ccache_name( (OM_uint32 *)&dwMinorStatus, pszCachePath, (ppszOrigCachePath) ? (const char**)&pszOrigCachePath : NULL); BAIL_ON_SEC_ERROR(dwMajorStatus); if (ppszOrigCachePath) { if (!IsNullOrEmptyString(pszOrigCachePath)) { dwError = SMBAllocateString(pszOrigCachePath, ppszOrigCachePath); BAIL_ON_LWIO_ERROR(dwError); } else { *ppszOrigCachePath = NULL; } } LWIO_LOG_DEBUG("Cache path set to [%s]", LWIO_SAFE_LOG_STRING(pszCachePath)); cleanup: return dwError; sec_error: error: if (ppszOrigCachePath) { *ppszOrigCachePath = NULL; } goto cleanup; }
DWORD SMBGSSContextBuild( PCWSTR pwszServerName, PIO_CREDS pCreds, PHANDLE phSMBGSSContext ) { DWORD dwError = 0; DWORD dwMajorStatus = 0; DWORD dwMinorStatus = 0; PSMB_GSS_SEC_CONTEXT pContext = NULL; PSTR pszTargetName = NULL; PSTR pszServerName = NULL; PSTR pszUsername = NULL; PSTR pszDomain = NULL; PSTR pszPassword = NULL; gss_buffer_desc usernameBuffer = {0}; gss_buffer_desc inputNameBuffer = {0}; gss_buffer_desc authDataBuffer = {0}; gss_name_t pUsername = NULL; gss_OID_set_desc desiredMechs; gss_OID_set actualMechs; OM_uint32 timeRec = 0; SEC_WINNT_AUTH_IDENTITY authData; static gss_OID_desc gssCredOptionPasswordOidDesc = { .length = GSS_CRED_OPT_PW_LEN, .elements = GSS_CRED_OPT_PW }; static gss_OID_desc gssNtlmOidDesc = { .length = GSS_MECH_NTLM_LEN, .elements = GSS_MECH_NTLM }; size_t sCopyServerChars = 0; dwError = LwRtlCStringAllocateFromWC16String(&pszServerName, pwszServerName); BAIL_ON_LWIO_ERROR(dwError); LWIO_LOG_DEBUG("Build GSS Context for server [%s]", LWIO_SAFE_LOG_STRING(pszServerName)); dwError = LwIoAllocateMemory( sizeof(SMB_GSS_SEC_CONTEXT), (PVOID*)&pContext); BAIL_ON_LWIO_ERROR(dwError); pContext->state = SMB_GSS_SEC_CONTEXT_STATE_INITIAL; if (pCreds) { switch (pCreds->type) { case IO_CREDS_TYPE_KRB5_CCACHE: dwError = STATUS_ACCESS_DENIED; BAIL_ON_LWIO_ERROR(dwError); break; case IO_CREDS_TYPE_KRB5_TGT: sCopyServerChars = strlen(pszServerName); if (sCopyServerChars > 0 && pszServerName[sCopyServerChars - 1] == '.') { // Strip the trailing dot sCopyServerChars --; } if (sCopyServerChars > INT_MAX) { dwError = STATUS_INTEGER_OVERFLOW; BAIL_ON_LWIO_ERROR(dwError); } dwError = SMBAllocateStringPrintf( &pszTargetName, "cifs/%.*s@", (int)sCopyServerChars, pszServerName); BAIL_ON_LWIO_ERROR(dwError); inputNameBuffer.value = pszTargetName; inputNameBuffer.length = strlen(pszTargetName) + 1; dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &inputNameBuffer, (gss_OID) gss_nt_krb5_name, &pContext->target_name); smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus); BAIL_ON_SEC_ERROR(dwMajorStatus); dwError = LwRtlCStringAllocateFromWC16String( &pszUsername, pCreds->payload.krb5Tgt.pwszClientPrincipal); BAIL_ON_NT_STATUS(dwError); usernameBuffer.value = pszUsername; usernameBuffer.length = strlen(pszUsername) + 1; dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &usernameBuffer, GSS_C_NT_USER_NAME, &pUsername); BAIL_ON_SEC_ERROR(dwMajorStatus); desiredMechs.count = 1; desiredMechs.elements = (gss_OID) gss_mech_krb5; dwMajorStatus = gss_acquire_cred( (OM_uint32 *)&dwMinorStatus, pUsername, 0, &desiredMechs, GSS_C_INITIATE, &pContext->credHandle, &actualMechs, &timeRec); BAIL_ON_SEC_ERROR(dwMajorStatus); break; case IO_CREDS_TYPE_PLAIN: inputNameBuffer.value = (void*) "unset"; inputNameBuffer.length = strlen("unset"); dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &inputNameBuffer, (gss_OID) gss_nt_krb5_name, &pContext->target_name); smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus); BAIL_ON_SEC_ERROR(dwMajorStatus); if (pCreds->payload.plain.pwszUsername) { dwError = LwRtlCStringAllocateFromWC16String(&pszUsername, pCreds->payload.plain.pwszUsername); BAIL_ON_LWIO_ERROR(dwError); usernameBuffer.value = pszUsername; usernameBuffer.length = strlen(pszUsername); // If "" is passed in, that means to use anonymous // authentication. gss_import_name fails on "" though if (usernameBuffer.length) { dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &usernameBuffer, GSS_C_NT_USER_NAME, &pUsername); BAIL_ON_SEC_ERROR(dwMajorStatus); } } desiredMechs.count = 1; desiredMechs.elements = (gss_OID) &gssNtlmOidDesc; dwMajorStatus = gss_acquire_cred( (OM_uint32 *)&dwMinorStatus, pUsername, 0, &desiredMechs, GSS_C_INITIATE, &pContext->credHandle, &actualMechs, &timeRec); BAIL_ON_SEC_ERROR(dwMajorStatus); if (pCreds->payload.plain.pwszUsername && pCreds->payload.plain.pwszPassword && pCreds->payload.plain.pwszDomain) { dwError = LwRtlCStringAllocateFromWC16String(&pszDomain, pCreds->payload.plain.pwszDomain); BAIL_ON_LWIO_ERROR(dwError); dwError = LwRtlCStringAllocateFromWC16String(&pszPassword, pCreds->payload.plain.pwszPassword); BAIL_ON_LWIO_ERROR(dwError); authData.User = pszUsername; authData.UserLength = strlen(pszUsername); authData.Domain = pszDomain; authData.DomainLength = strlen(pszDomain); authData.Password = pszPassword; authData.PasswordLength = strlen(pszPassword); authData.Flags = 0; authDataBuffer.value = &authData; authDataBuffer.length = sizeof(authData); dwMajorStatus = gssspi_set_cred_option( (OM_uint32 *)&dwMinorStatus, pContext->credHandle, (gss_OID) &gssCredOptionPasswordOidDesc, &authDataBuffer); BAIL_ON_SEC_ERROR(dwMajorStatus); } break; } } dwError = LwIoAllocateMemory( sizeof(CtxtHandle), (PVOID*)&pContext->pGSSContext); BAIL_ON_LWIO_ERROR(dwError); *pContext->pGSSContext = GSS_C_NO_CONTEXT; *phSMBGSSContext = (HANDLE)pContext; cleanup: if (pUsername != NULL) { gss_release_name((OM_uint32 *)&dwMinorStatus, &pUsername); } LWIO_SAFE_FREE_STRING(pszTargetName); LWIO_SAFE_FREE_STRING(pszServerName); LWIO_SAFE_FREE_STRING(pszUsername); LWIO_SAFE_FREE_STRING(pszDomain); LWIO_SAFE_FREE_STRING(pszPassword); return dwError; sec_error: dwError = LWIO_ERROR_GSS; error: *phSMBGSSContext = NULL; if (pContext) { SMBGSSContextFree(pContext); } goto cleanup; }