int main( int argc, char** ppszArgv ) { NTSTATUS status = STATUS_SUCCESS; if (argc >= 2) { if (LwRtlCStringIsEqual(ppszArgv[1], "status", TRUE)) { status = Status(argc - 1, ppszArgv + 1); BAIL_ON_NT_STATUS(status); } else if (LwRtlCStringIsEqual(ppszArgv[1], "load", TRUE)) { int iArg = 2; for (; iArg < argc; iArg++) { status = Load(ppszArgv[iArg]); BAIL_ON_NT_STATUS(status); } } else if (LwRtlCStringIsEqual(ppszArgv[1], "unload", TRUE)) { int iArg = 2; for (; iArg < argc; iArg++) { status = Unload(ppszArgv[iArg]); BAIL_ON_NT_STATUS(status); } } else { Usage(ppszArgv[0]); } } else { Usage(ppszArgv[0]); } cleanup: return status ? 1 : 0; error: goto cleanup; }
static NTSTATUS PvfsFindParentFCB( PPVFS_FCB *ppParentFcb, PCSTR pszFilename ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_FCB pFcb = NULL; PSTR pszDirname = NULL; PPVFS_CB_TABLE_ENTRY pBucket = NULL; if (LwRtlCStringIsEqual(pszFilename, "/", TRUE)) { ntError = STATUS_SUCCESS; *ppParentFcb = NULL; goto cleanup; } ntError = PvfsFileDirname(&pszDirname, pszFilename); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCbTableGetBucket(&pBucket, &gPvfsDriverState.FcbTable, pszDirname); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCbTableLookup((PPVFS_CONTROL_BLOCK*)OUT_PPVOID(&pFcb), pBucket, pszDirname); if (ntError == STATUS_OBJECT_NAME_NOT_FOUND) { ntError = PvfsCreateFCB( &pFcb, pszDirname, FALSE, 0, 0); } BAIL_ON_NT_STATUS(ntError); *ppParentFcb = PvfsReferenceFCB(pFcb); cleanup: if (pFcb) { PvfsReleaseFCB(&pFcb); } if (pszDirname) { LwRtlCStringFree(&pszDirname); } return ntError; error: goto cleanup; }
static BOOLEAN PvfsSysIsEmptyDir( PSTR pszDirname ) { NTSTATUS ntError = STATUS_SUCCESS; BOOLEAN isEmptyDir = TRUE; DIR *pDir = NULL; struct dirent *pDirEntry = NULL; struct dirent dirEntry = { 0 }; ntError = PvfsSysOpenDir(pszDirname, &pDir); BAIL_ON_NT_STATUS(ntError); for (ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry); pDirEntry; ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry)) { /* First check the error return */ BAIL_ON_NT_STATUS(ntError); if (!LwRtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) && !LwRtlCStringIsEqual(pDirEntry->d_name, "..", FALSE)) { isEmptyDir = FALSE; break; } } error: if (pDir) { PvfsSysCloseDir(pDir); } return NT_SUCCESS(ntError) ? isEmptyDir : FALSE; }
static NTSTATUS SrvBuildNegotiateResponseForDialect( IN PLWIO_SRV_CONNECTION pConnection, IN PSMB_PACKET pSmbRequest, IN PSTR* ppszDialectArray, IN ULONG ulNumDialects, OUT PSMB_PACKET* ppSmbResponse ) { NTSTATUS ntStatus = STATUS_SUCCESS; SHORT dialectIdx = 0; BOOLEAN supportSMBV2 = SrvProtocolConfigIsSmb2Enabled(); PSMB_PACKET pSmbResponse = NULL; SMB_PROTOCOL_VERSION protocolVersion = SMB_PROTOCOL_VERSION_UNKNOWN; SMB_PROTOCOL_DIALECT protocolDialect = SMB_PROTOCOL_DIALECT_UNKNOWN; for (dialectIdx = ulNumDialects-1; dialectIdx >= 0; dialectIdx--) { if (supportSMBV2 && LwRtlCStringIsEqual( ppszDialectArray[dialectIdx], SRV_NEGOTIATE_DIALECT_STRING_SMB_2_1, TRUE)) { protocolVersion = SMB_PROTOCOL_VERSION_2; protocolDialect = SMB_PROTOCOL_DIALECT_SMB_2_1; } else if (supportSMBV2 && LwRtlCStringIsEqual( ppszDialectArray[dialectIdx], SRV_NEGOTIATE_DIALECT_STRING_SMB_2, TRUE)) { protocolVersion = SMB_PROTOCOL_VERSION_2; protocolDialect = SMB_PROTOCOL_DIALECT_SMB_2_0; } else if (LwRtlCStringIsEqual( ppszDialectArray[dialectIdx], SRV_NEGOTIATE_DIALECT_STRING_NTLM_0_12, TRUE)) { protocolVersion = SMB_PROTOCOL_VERSION_1; protocolDialect = SMB_PROTOCOL_DIALECT_NTLM_0_12; } if (protocolVersion != SMB_PROTOCOL_VERSION_UNKNOWN) { // Found the dialect we want so exit loop break; } } switch (protocolVersion) { case SMB_PROTOCOL_VERSION_UNKNOWN: ntStatus = SrvBuildNegotiateResponse_SMB_V1_Invalid( pConnection, pSmbRequest, &pSmbResponse); break; case SMB_PROTOCOL_VERSION_1: ntStatus = SrvBuildNegotiateResponse_SMB_V1_NTLM_0_12( pConnection, pSmbRequest, protocolDialect, dialectIdx, &pSmbResponse); break; case SMB_PROTOCOL_VERSION_2: ntStatus = SrvBuildNegotiateResponse_SMB_V2( pConnection, pSmbRequest, protocolDialect, &pSmbResponse); break; } BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvConnectionSetProtocolVersion( pConnection, protocolVersion, protocolDialect); BAIL_ON_NT_STATUS(ntStatus); error: if (!NT_SUCCESS(ntStatus)) { if (pSmbResponse) { SMBPacketRelease(pConnection->hPacketAllocator, pSmbResponse); pSmbResponse = NULL; } } *ppSmbResponse = pSmbResponse; return ntStatus; }
DWORD RegShellUtilExport( HANDLE hReg, PREG_EXPORT_STATE pExportState, HKEY hKey, PCSTR pszKeyName, DWORD dwNumSubKeys, DWORD dwMaxSubKeyLen ) { DWORD dwError = 0; REG_DATA_TYPE prevType = REG_NONE; SECURITY_INFORMATION SecInfoAll = OWNER_SECURITY_INFORMATION |GROUP_SECURITY_INFORMATION |DACL_SECURITY_INFORMATION |SACL_SECURITY_INFORMATION; PBYTE pSecDescRel = NULL; ULONG ulSecDescLen = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; PSTR pszStringSecurityDescriptor = NULL; dwError = RegGetKeySecurity(hReg, hKey, SecInfoAll, NULL, &ulSecDescLen); BAIL_ON_REG_ERROR(dwError); dwError = RegAllocateMemory(ulSecDescLen, (PVOID)&pSecDescRel); BAIL_ON_REG_ERROR(dwError); dwError = RegGetKeySecurity(hReg, hKey, SecInfoAll, (PSECURITY_DESCRIPTOR_RELATIVE)pSecDescRel, &ulSecDescLen); BAIL_ON_REG_ERROR(dwError); if (LwRtlCStringIsEqual(pszKeyName,HKEY_THIS_MACHINE,TRUE) || ulSecDescLen != pExportState->ulRootKeySecDescLen || !LwRtlEqualMemory(pSecDescRel, pExportState->pRootKeySecDescRel, ulSecDescLen)) { dwError = RegNtStatusToWin32Error( RtlAllocateSddlCStringFromSecurityDescriptor( &pszStringSecurityDescriptor, (PSECURITY_DESCRIPTOR_RELATIVE)pSecDescRel, SDDL_REVISION_1, SecInfoAll) ); BAIL_ON_REG_ERROR(dwError); } if (hKey) { dwError = ProcessExportedKeyInfo(hReg, pExportState, hKey, pszKeyName, pExportState->dwExportFormat == 1 ? NULL : pszStringSecurityDescriptor, &prevType); BAIL_ON_REG_ERROR(dwError); } if (hKey && dwNumSubKeys != 0) { dwError = ProcessSubKeys(hReg, pExportState, hKey, pszKeyName, dwNumSubKeys, dwMaxSubKeyLen); BAIL_ON_REG_ERROR(dwError); } else if (hKey == NULL && dwNumSubKeys == 0) { dwError = ProcessRootKeys(hReg, pExportState); BAIL_ON_REG_ERROR(dwError); } else if (hKey == NULL && dwNumSubKeys != 0) { dwError = ERROR_INTERNAL_ERROR; BAIL_ON_REG_ERROR(dwError); } cleanup: if (pszStringSecurityDescriptor) { RegFreeString(pszStringSecurityDescriptor); } LWREG_SAFE_FREE_MEMORY(pSecDescRel); if (pSecDescRel) { RegMemoryFree(pSecDescRel); pSecDescRel = NULL; } return dwError; error: goto cleanup; }
DWORD SrvSvcRegisterForRPC( PSTR pszServiceName, rpc_binding_vector_p_t* ppServerBinding ) { volatile DWORD dwError = 0; volatile DWORD dwRpcStatus = 0; rpc_binding_vector_p_t pServerBinding = NULL; BOOLEAN bRegistered = FALSE; BOOLEAN bBound = FALSE; BOOLEAN bEPRegistered = FALSE; static ENDPOINT endpoints[] = { {"ncacn_np", "\\\\pipe\\\\srvsvc"}, {"ncalrpc", NULL}, // endpoint is fetched from config parameter {NULL, NULL}, // placeholder for ncacn_ip_tcp (if enabled) {NULL, NULL} }; DWORD i = 0; PSTR lpcSocketPath = NULL; BOOLEAN registerTcpIp = FALSE; dwError = SrvSvcConfigGetLpcSocketPath(&lpcSocketPath); BAIL_ON_SRVSVC_ERROR(dwError); // Fill in the socket path for local procedure calls (ncalrpc) while (endpoints[i].protocol) { if (lpcSocketPath && LwRtlCStringIsEqual(endpoints[i].protocol, "ncalrpc", TRUE)) { endpoints[i].endpoint = lpcSocketPath; } i++; } dwError = SrvSvcConfigGetRegisterTcpIp(®isterTcpIp); BAIL_ON_SRVSVC_ERROR(dwError); // Append ncacn_ip_tcp endpoint if it's enabled in the configuration if (registerTcpIp) { endpoints[i++].protocol = "ncacn_ip_tcp"; } DCETHREAD_TRY { rpc_server_register_if (srvsvc_v3_0_s_ifspec, NULL, NULL, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if ( dwRpcStatus == RPC_S_OK ) { dwError = dcethread_exc_getstatus (THIS_CATCH); if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bRegistered = TRUE; SRVSVC_LOG_INFO("RPC Service registered successfully."); DCETHREAD_TRY { dwError = bind_server(&pServerBinding, srvsvc_v3_0_s_ifspec, endpoints); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if(!dwError) { dwError = dcethread_exc_getstatus (THIS_CATCH); } if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } DCETHREAD_ENDTRY; BAIL_ON_SRVSVC_ERROR(dwError); bBound = TRUE; DCETHREAD_TRY { rpc_ep_register(srvsvc_v3_0_s_ifspec, pServerBinding, NULL, (idl_char*)pszServiceName, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if ( dwRpcStatus == RPC_S_OK ) { dwError = dcethread_exc_getstatus (THIS_CATCH); if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bEPRegistered = TRUE; SRVSVC_LOG_INFO("RPC Endpoint registered successfully."); *ppServerBinding = pServerBinding; cleanup: // DCE/RPC runtime makes a copy of ncalrpc socket path internally // so it is safe to free it here LW_SAFE_FREE_MEMORY(lpcSocketPath); return dwError; error: SRVSVC_LOG_ERROR("Failed to register RPC endpoint. Error Code: [%u]\n", dwError); if (bEPRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_ep_unregister(srvsvc_v3_0_s_ifspec, pServerBinding, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bBound) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_binding_vector_free(&pServerBinding, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_server_unregister_if (srvsvc_v3_0_s_ifspec, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } *ppServerBinding = NULL; goto cleanup; }
static NTSTATUS PvfsSysRemoveDir( PSTR pszDirname ) { NTSTATUS ntError = STATUS_SUCCESS; DIR *pDir = NULL; struct dirent *pDirEntry = NULL; struct dirent dirEntry = { 0 }; PSTR pszPath = NULL; PVFS_STAT streamDirStat = { 0 }; ntError = PvfsSysOpenDir(pszDirname, &pDir); BAIL_ON_NT_STATUS(ntError); for (ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry); pDirEntry; ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry)) { /* First check the error return */ BAIL_ON_NT_STATUS(ntError); memset(&streamDirStat, 0, sizeof(PVFS_STAT)); if (pszPath) { LwRtlCStringFree(&pszPath); } ntError = LwRtlCStringAllocatePrintf( &pszPath, "%s/%s", pszDirname, pDirEntry->d_name); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStat(pszPath, &streamDirStat); if (ntError == STATUS_SUCCESS) { if(S_ISDIR(streamDirStat.s_mode)) { if (!LwRtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) && !LwRtlCStringIsEqual(pDirEntry->d_name, "..", FALSE)) { ntError = PvfsSysRemoveDir(pszPath); BAIL_ON_NT_STATUS(ntError); } } else { ntError = PvfsSysRemove(pszPath); BAIL_ON_NT_STATUS(ntError); } } else { // Squash the error is the stream directory did not exist ntError = STATUS_SUCCESS; } } ntError = PvfsSysCloseDir(pDir); BAIL_ON_NT_STATUS(ntError); pDir = NULL; ntError = PvfsSysRemove(pszDirname); BAIL_ON_NT_STATUS(ntError); error: if (pszPath) { LwRtlCStringFree(&pszPath); } if (pDir) { PvfsSysCloseDir(pDir); } return ntError; }
NTSTATUS PvfsRenameCCB( IN PPVFS_CCB pCcb, IN PPVFS_FILE_NAME pDestFileName ) { NTSTATUS ntError = STATUS_SUCCESS; PVFS_FILE_NAME srcFileName = { 0 }; ntError = PvfsValidatePathSCB(pCcb->pScb, &pCcb->FileId); BAIL_ON_NT_STATUS(ntError); ntError = PvfsBuildFileNameFromScb(&srcFileName, pCcb->pScb); BAIL_ON_NT_STATUS(ntError); if (!PvfsIsDefaultStreamName(&srcFileName) && !PvfsIsDefaultStreamName(pDestFileName)) { // Two named streams if (LwRtlCStringIsEqual( PvfsGetCStringBaseStreamName(&srcFileName), PvfsGetCStringBaseStreamName(pDestFileName), FALSE)) { // Both src and dst stream names are the same // renaming the underlying file object ntError = PvfsRenameFile(pCcb, pDestFileName); } else if (LwRtlCStringIsEqual( PvfsGetCStringBaseFileName(&srcFileName), PvfsGetCStringBaseFileName(pDestFileName), FALSE)) { // Renaming the named stream, file name stays the same ntError = PvfsRenameStream(pCcb, pDestFileName); } else { // Don't allow renaming both the file name and stream name at the // same time (yet) ntError = STATUS_OBJECT_NAME_INVALID; } } else if (PvfsIsDefaultStreamName(&srcFileName) && PvfsIsDefaultStreamName(pDestFileName)) { // Two default streams rename object itself ntError = PvfsRenameFile(pCcb, pDestFileName); } else if (!PvfsIsDefaultStreamName(&srcFileName) && PvfsIsDefaultStreamName(pDestFileName)) { // rename name stream -> default stream // A stream on a directory cannot be renamed to the default data stream if (!LwRtlCStringIsEqual( PvfsGetCStringBaseFileName(&srcFileName), PvfsGetCStringBaseFileName(pDestFileName), FALSE) || PVFS_IS_DIR(pCcb)) { ntError = STATUS_OBJECT_NAME_INVALID; } else { ntError = PvfsRenameStream(pCcb, pDestFileName); } } else { // disallow rename object->stream as what smbtorture expects // TODO: // we may want to allow "Renaming" the default data stream // it is not a true rename, and it leaves behind a zero-length default data streams ntError = STATUS_OBJECT_NAME_INVALID; } BAIL_ON_NT_STATUS(ntError); error: PvfsDestroyFileName(&srcFileName); return ntError; }