/* Acquire group or user name by SID */ static HRESULT getNameByStringSID( const wchar_t *sid, LPWSTR buffer, LPDWORD bufferLen) { HRESULT hr = S_OK; PSID psid = NULL; SID_NAME_USE groupType; DWORD domainNameLen = BUFFER_SIZE; wchar_t domainName[BUFFER_SIZE]; chk(ConvertStringSidToSidW(sid, &psid)); LookupAccountSidW(NULL, psid, buffer, bufferLen, domainName, &domainNameLen, &groupType); hr = HRESULT_FROM_WIN32(GetLastError()); LocalFree(psid); out: return hr; }
//MailSlot of flush DNS cache Monitor bool __fastcall FlushDNSMailSlotMonitor( void) { //System security setting std::shared_ptr<SECURITY_ATTRIBUTES> SecurityAttributes(new SECURITY_ATTRIBUTES()); std::shared_ptr<SECURITY_DESCRIPTOR> SecurityDescriptor(new SECURITY_DESCRIPTOR()); std::shared_ptr<char> ACL_Buffer(new char[PACKET_MAXSIZE]()); memset(ACL_Buffer.get(), 0, PACKET_MAXSIZE); PSID SID_Value = nullptr; InitializeSecurityDescriptor(SecurityDescriptor.get(), SECURITY_DESCRIPTOR_REVISION); InitializeAcl((PACL)ACL_Buffer.get(), PACKET_MAXSIZE, ACL_REVISION); ConvertStringSidToSidW(SID_ADMINISTRATORS_GROUP, &SID_Value); AddAccessAllowedAce((PACL)ACL_Buffer.get(), ACL_REVISION, GENERIC_ALL, SID_Value); SetSecurityDescriptorDacl(SecurityDescriptor.get(), true, (PACL)ACL_Buffer.get(), false); SecurityAttributes->lpSecurityDescriptor = SecurityDescriptor.get(); SecurityAttributes->bInheritHandle = true; //Create mailslot. HANDLE hSlot = CreateMailslotW(MAILSLOT_NAME, PACKET_MAXSIZE - 1U, MAILSLOT_WAIT_FOREVER, SecurityAttributes.get()); if (hSlot == INVALID_HANDLE_VALUE) { LocalFree(SID_Value); PrintError(LOG_ERROR_SYSTEM, L"Create mailslot error", GetLastError(), nullptr, 0); return false; } ACL_Buffer.reset(); LocalFree(SID_Value); //Initialization BOOL Result = FALSE; bool FlushDNS = false; DWORD cbMessage = 0, cMessage = 0, cbRead = 0; std::shared_ptr<wchar_t> lpszBuffer(new wchar_t[PACKET_MAXSIZE]()); wmemset(lpszBuffer.get(), 0, PACKET_MAXSIZE); //MailSlot Monitor for (;;) { cbMessage = 0; cMessage = 0; //Get mailslot messages. Result = GetMailslotInfo(hSlot, nullptr, &cbMessage, &cMessage, nullptr); if (Result == FALSE) { PrintError(LOG_ERROR_SYSTEM, L"Mailslot Monitor initialization error", GetLastError(), nullptr, 0); CloseHandle(hSlot); return false; } //Wait for messages. if (cbMessage == MAILSLOT_NO_MESSAGE) { Sleep(LOOP_INTERVAL_TIME_MONITOR); continue; } //Got messages. FlushDNS = false; while (cMessage > 0) { Result = ReadFile(hSlot, lpszBuffer.get(), cbMessage, &cbRead, nullptr); if (Result == FALSE) { PrintError(LOG_ERROR_SYSTEM, L"MailSlot read messages error", GetLastError(), nullptr, 0); CloseHandle(hSlot); return false; } if (!FlushDNS && memcmp(lpszBuffer.get(), MAILSLOT_MESSAGE_FLUSH_DNS, wcslen(MAILSLOT_MESSAGE_FLUSH_DNS)) == EXIT_SUCCESS) { FlushDNS = true; FlushAllDNSCache(); } memset(lpszBuffer.get(), 0, PACKET_MAXSIZE); //Get other mailslot messages. Result = GetMailslotInfo(hSlot, nullptr, &cbMessage, &cMessage, nullptr); if (Result == FALSE) { PrintError(LOG_ERROR_SYSTEM, L"Mailslot Monitor initialization error", GetLastError(), nullptr, 0); CloseHandle(hSlot); return false; } } Sleep(LOOP_INTERVAL_TIME_MONITOR); } //Monitor terminated CloseHandle(hSlot); PrintError(LOG_ERROR_SYSTEM, L"MailSlot module Monitor terminated", 0, nullptr, 0); return false; }
JNIEXPORT void JNICALL Java_com_microsoft_tfs_jni_internal_filesystem_NativeFileSystem_nativeSetOwner(JNIEnv *env, jclass cls, jstring jPath, jstring jOwnerSIDString) { const WCHAR * path= NULL; const WCHAR * ownerSIDString = NULL; PSID ownerSID = NULL; DWORD result = 0; if (jPath == NULL) { throwRuntimeExceptionString(env, "path must not be null"); goto cleanup; } if (jOwnerSIDString == NULL) { throwRuntimeExceptionString(env, "user must not be null"); goto cleanup; } if ((ownerSIDString = javaStringToPlatformChars(env, jOwnerSIDString)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } if (ConvertStringSidToSidW(ownerSIDString, &ownerSID) == FALSE) { throwRuntimeExceptionCode(env, GetLastError(), "Error converting string %S sid to sid", ownerSIDString); goto cleanup; } if ((path = javaStringToPlatformChars(env, jPath)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } result = SetNamedSecurityInfoW((WCHAR *) path, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, ownerSID, NULL, NULL, NULL); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error getting file security info for %S", path); goto cleanup; } cleanup: if (ownerSIDString != NULL) { releasePlatformChars(env, jOwnerSIDString, ownerSIDString); } if (path != NULL) { releasePlatformChars(env, jPath, path); } if (ownerSID != NULL) { LocalFree(ownerSID); } }
JNIEXPORT void JNICALL Java_com_microsoft_tfs_jni_internal_filesystem_NativeFileSystem_nativeRemoveExplicitAllowEntries( JNIEnv *env, jclass cls, jstring jPath, jstring jUserSIDString) { const WCHAR * path = NULL; const WCHAR * userSIDString = NULL; PSID userSID = NULL; DWORD result = 0; PACL dacl = NULL; PSECURITY_DESCRIPTOR securityDescriptor = NULL; ACL_SIZE_INFORMATION aclSizeInfo; ULONG aceCount = 0; BOOL modifiedDACL = FALSE; if (jPath == NULL) { throwRuntimeExceptionString(env, "path must not be null"); goto cleanup; } if (jUserSIDString == NULL) { throwRuntimeExceptionString(env, "user must not be null"); goto cleanup; } // Convert the SID string to a struct if ((userSIDString = javaStringToPlatformChars(env, jUserSIDString)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } if (ConvertStringSidToSidW(userSIDString, &userSID) == FALSE) { throwRuntimeExceptionCode(env, GetLastError(), "Error converting string sid %S to sid", userSIDString); goto cleanup; } if ((path = javaStringToPlatformChars(env, jPath)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } // Get file's DACL result = GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, &securityDescriptor); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error getting file security info for %S", path); goto cleanup; } // Get the count of entries int the DACL if (GetAclInformation(dacl, &aclSizeInfo, sizeof(aclSizeInfo), AclSizeInformation) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error getting DACL"); goto cleanup; } // Loop over the DACL backwards, removing matching entries for (aceCount = aclSizeInfo.AceCount; aceCount > 0; aceCount--) { ULONG aceIndex = aceCount - 1; ACCESS_ALLOWED_ACE * ace = NULL; PSID sid = NULL; if (GetAce(dacl, aceIndex, (LPVOID *) &ace) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error getting ACE at index %d", aceIndex); goto cleanup; } // Skip inherited (non-explicit) entries if ((((ACE_HEADER *) ace)->AceFlags & INHERITED_ACE) == INHERITED_ACE) { continue; } // Extract the SID for "allow" types switch(((ACE_HEADER *) ace)->AceType) { case ACCESS_ALLOWED_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_CALLBACK_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_OBJECT_ACE *) ace)->SidStart; break; default: // These are "deny" or other entries break; } if (sid != NULL && EqualSid(sid, userSID)) { if (DeleteAce(dacl, aceIndex) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error deleting ACE at index %d", aceIndex); goto cleanup; } modifiedDACL = TRUE; } // Nothing to free in the loop, all pointers are into dacl } if (modifiedDACL) { result = SetNamedSecurityInfo((WCHAR *) path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, dacl, NULL); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error setting security info for %S", path); goto cleanup; } } cleanup: if (path != NULL) { releasePlatformChars(env, jPath, path); } if (userSID != NULL) { LocalFree(userSID); } if (userSIDString != NULL) { releasePlatformChars(env, jUserSIDString, userSIDString); } // dacl points inside securityDescriptor if (securityDescriptor != NULL) { LocalFree(securityDescriptor); } }
JNIEXPORT void JNICALL Java_com_microsoft_tfs_jni_internal_filesystem_NativeFileSystem_nativeGrantInheritableFullControl( JNIEnv *env, jclass cls, jstring jPath, jstring jUserSIDString, jstring jCopyExplicitRulesFromPath) { const WCHAR * path = NULL; const WCHAR * userSIDString = NULL; const WCHAR * copyExplicitRulesFromPath = NULL; DWORD result = 0; PACL existingDACL = NULL; PACL newDACL = NULL; PSECURITY_DESCRIPTOR securityDescriptor = NULL; PSID userSID = NULL; EXPLICIT_ACCESS fullControl; if (jPath == NULL) { throwRuntimeExceptionString(env, "path must not be null"); goto cleanup; } if (jUserSIDString == NULL) { throwRuntimeExceptionString(env, "user must not be null"); goto cleanup; } // Get the existing DACL entries if (jCopyExplicitRulesFromPath != NULL) { if ((copyExplicitRulesFromPath = javaStringToPlatformChars(env, jCopyExplicitRulesFromPath)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } result = GetNamedSecurityInfo(copyExplicitRulesFromPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &existingDACL, NULL, &securityDescriptor); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error getting file security info for %S", copyExplicitRulesFromPath); goto cleanup; } } // Convert the string SID to a structure if ((userSIDString = javaStringToPlatformChars(env, jUserSIDString)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } if (ConvertStringSidToSidW(userSIDString, &userSID) == FALSE) { throwRuntimeExceptionCode(env, GetLastError(), "Error converting string sid %S to sid", userSIDString); goto cleanup; } /* * Create a new explicit access entry with rights equivalent to .NET's * FileSystemRights.FullControl (0x1F01FF; see FileSecurity.cs) and * full inheritance. */ ZeroMemory(&fullControl, sizeof(EXPLICIT_ACCESS)); fullControl.grfAccessPermissions = 0x1F01FF; fullControl.grfAccessMode = GRANT_ACCESS; fullControl.grfInheritance= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; fullControl.Trustee.TrusteeForm = TRUSTEE_IS_SID; fullControl.Trustee.TrusteeType = TRUSTEE_IS_USER; fullControl.Trustee.ptstrName = userSID; // Merge new entry with old entries into a new list result = SetEntriesInAcl(1, &fullControl, existingDACL, &newDACL); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error setting entries in ACL"); goto cleanup; } // Set the list on the path if ((path = javaStringToPlatformChars(env, jPath)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } result = SetNamedSecurityInfo((WCHAR *) path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newDACL, NULL); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error setting file security info for %S", path); goto cleanup; } cleanup: if (path != NULL) { releasePlatformChars(env, jPath, path); } if (userSIDString != NULL) { releasePlatformChars(env, jUserSIDString, userSIDString); } if (copyExplicitRulesFromPath != NULL) { releasePlatformChars(env, jCopyExplicitRulesFromPath, copyExplicitRulesFromPath); } if (securityDescriptor != NULL) { LocalFree(securityDescriptor); } if (userSID != NULL) { LocalFree(userSID); } if (newDACL != NULL) { LocalFree(newDACL); } // existingDACL points inside securityDescriptor }
//MailSlot of flush DNS cache Monitor bool FlushDNSMailSlotMonitor( void) { //System security setting std::shared_ptr<uint8_t> ACL_Buffer(new uint8_t[FILE_BUFFER_SIZE]()); memset(ACL_Buffer.get(), 0, FILE_BUFFER_SIZE); SECURITY_ATTRIBUTES SecurityAttributes; SECURITY_DESCRIPTOR SecurityDescriptor; memset(&SecurityAttributes, 0, sizeof(SecurityAttributes)); memset(&SecurityDescriptor, 0, sizeof(SecurityDescriptor)); PSID SID_Value = nullptr; InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); InitializeAcl((PACL)ACL_Buffer.get(), FILE_BUFFER_SIZE, ACL_REVISION); ConvertStringSidToSidW(SID_ADMINISTRATORS_GROUP, &SID_Value); AddAccessAllowedAce((PACL)ACL_Buffer.get(), ACL_REVISION, GENERIC_ALL, SID_Value); SetSecurityDescriptorDacl(&SecurityDescriptor, true, (PACL)ACL_Buffer.get(), false); SecurityAttributes.lpSecurityDescriptor = &SecurityDescriptor; SecurityAttributes.bInheritHandle = true; //Create mailslot. HANDLE hSlot = CreateMailslotW(MAILSLOT_NAME, FILE_BUFFER_SIZE - 1U, MAILSLOT_WAIT_FOREVER, &SecurityAttributes); if (hSlot == INVALID_HANDLE_VALUE) { LocalFree(SID_Value); PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"Create mailslot error", GetLastError(), nullptr, 0); return false; } ACL_Buffer.reset(); LocalFree(SID_Value); //Initialization std::shared_ptr<wchar_t> lpszBuffer(new wchar_t[FILE_BUFFER_SIZE]()); wmemset(lpszBuffer.get(), 0, FILE_BUFFER_SIZE); std::wstring Message; std::string Domain; DWORD cbMessage = 0; BOOL Result = 0; //MailSlot monitor for (;;) { //Reset parameters. wmemset(lpszBuffer.get(), 0, FILE_BUFFER_SIZE); cbMessage = 0; //Read message from mailslot. Result = ReadFile(hSlot, lpszBuffer.get(), FILE_BUFFER_SIZE, &cbMessage, nullptr); if (Result == FALSE) { PrintError(LOG_LEVEL_3, LOG_ERROR_SYSTEM, L"MailSlot read messages error", GetLastError(), nullptr, 0); CloseHandle(hSlot); return false; } else { Message = lpszBuffer.get(); Domain.clear(); //Read message. if (Message == MAILSLOT_MESSAGE_FLUSH_DNS) //Flush all DNS cache. { FlushDNSCache(nullptr); } else if (Message.find(MAILSLOT_MESSAGE_FLUSH_DNS_DOMAIN) == 0 && //Flush single domain cache. Message.length() > wcslen(MAILSLOT_MESSAGE_FLUSH_DNS_DOMAIN) + DOMAIN_MINSIZE && //Domain length check Message.length() < wcslen(MAILSLOT_MESSAGE_FLUSH_DNS_DOMAIN) + DOMAIN_MAXSIZE) { if (WCSToMBSString(Message.c_str() + wcslen(MAILSLOT_MESSAGE_FLUSH_DNS_DOMAIN), DOMAIN_MAXSIZE, Domain) && Domain.length() > DOMAIN_MINSIZE && Domain.length() < DOMAIN_MAXSIZE) FlushDNSCache((const uint8_t *)Domain.c_str()); else PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"Convert multiple byte or wide char string error", 0, nullptr, 0); } else { Sleep(Parameter.FileRefreshTime); } } } //Monitor terminated CloseHandle(hSlot); PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"MailSlot module Monitor terminated", 0, nullptr, 0); return false; }
//MailSlot of flush DNS cache Monitor bool __fastcall FlushDNSMailSlotMonitor( void) { //System security setting std::shared_ptr<char> ACL_Buffer(new char[FILE_BUFFER_SIZE]()); memset(ACL_Buffer.get(), 0, FILE_BUFFER_SIZE); SECURITY_ATTRIBUTES SecurityAttributes; SECURITY_DESCRIPTOR SecurityDescriptor; memset(&SecurityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); memset(&SecurityDescriptor, 0, sizeof(SECURITY_DESCRIPTOR)); PSID SID_Value = nullptr; InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); InitializeAcl((PACL)ACL_Buffer.get(), FILE_BUFFER_SIZE, ACL_REVISION); ConvertStringSidToSidW(SID_ADMINISTRATORS_GROUP, &SID_Value); AddAccessAllowedAce((PACL)ACL_Buffer.get(), ACL_REVISION, GENERIC_ALL, SID_Value); SetSecurityDescriptorDacl(&SecurityDescriptor, true, (PACL)ACL_Buffer.get(), false); SecurityAttributes.lpSecurityDescriptor = &SecurityDescriptor; SecurityAttributes.bInheritHandle = true; //Create mailslot. HANDLE hSlot = CreateMailslotW(MAILSLOT_NAME, FILE_BUFFER_SIZE - 1U, MAILSLOT_WAIT_FOREVER, &SecurityAttributes); if (hSlot == INVALID_HANDLE_VALUE) { LocalFree(SID_Value); PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"Create mailslot error", GetLastError(), nullptr, 0); return false; } ACL_Buffer.reset(); LocalFree(SID_Value); //Initialization std::shared_ptr<wchar_t> lpszBuffer(new wchar_t[FILE_BUFFER_SIZE]()); wmemset(lpszBuffer.get(), 0, FILE_BUFFER_SIZE); DWORD cbMessage = 0; BOOL Result = 0; //MailSlot monitor for (;;) { Sleep(LOOP_INTERVAL_TIME_NO_DELAY); //Reset parameters. wmemset(lpszBuffer.get(), 0, FILE_BUFFER_SIZE); cbMessage = 0; //Read message from mailslot. Result = ReadFile(hSlot, lpszBuffer.get(), FILE_BUFFER_SIZE, &cbMessage, nullptr); if (Result == FALSE) { PrintError(LOG_LEVEL_3, LOG_ERROR_SYSTEM, L"MailSlot read messages error", GetLastError(), nullptr, 0); CloseHandle(hSlot); return false; } else if (memcmp(lpszBuffer.get(), MAILSLOT_MESSAGE_FLUSH_DNS, sizeof(wchar_t) * wcslen(MAILSLOT_MESSAGE_FLUSH_DNS)) == 0) { FlushAllDNSCache(); } else { Sleep(LOOP_INTERVAL_TIME_MONITOR); } } //Monitor terminated CloseHandle(hSlot); PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"MailSlot module Monitor terminated", 0, nullptr, 0); return false; }